emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/repology cfcf12bddc 1/5: repology: Add finer control ov


From: Nicolas Goaziou
Subject: [elpa] externals/repology cfcf12bddc 1/5: repology: Add finer control over outdated package definition
Date: Tue, 22 Feb 2022 05:19:59 -0500 (EST)

branch: externals/repology
commit cfcf12bddcaf794f905f95f4e3a62ee62031675a
Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
Commit: Nicolas Goaziou <mail@nicolasgoaziou.fr>

    repology: Add finer control over outdated package definition
    
    * repology.el (repology-outdated-project-definition): New variable.
    * repology-utils.el (repology-filter-outdated-projects):
    (repology--masked-package-p): New functions.
---
 repology-utils.el | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 repology.el       | 73 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 163 insertions(+)

diff --git a/repology-utils.el b/repology-utils.el
index d4f5fd0264..99c911decc 100644
--- a/repology-utils.el
+++ b/repology-utils.el
@@ -147,6 +147,64 @@ Return \"-\" if PACKAGE has no version field."
         (propertize version 'face (repology--package-status-face package))
       "-")))
 
+(defun repology-filter-outdated-projects (projects repository)
+  "Filter outdated projects from PROJECTS list.
+
+PROJECTS is a list of Repology projects.  REPOSITORY is the name
+of the reference repository, as a string.
+
+Outdated projects are defined according to the value of the
+variable `repology-outdated-project-definiton', which see.
+
+Return a list of Repology projects."
+  (seq-filter
+   (lambda (project)
+     (let ((reference-package
+            (seq-find (lambda (p)
+                        (equal repository (repology-package-field p 'repo)))
+                      (repology-project-packages project))))
+       (cond
+        ((not reference-package)
+         (user-error "No package for project %S in repository %S"
+                     project repository))
+        ;; Default definition for outdated projects: trust Repology's
+        ;; status from reference package.
+        ((not repology-outdated-project-definition)
+         (equal "outdated" (repology-package-field reference-package 'status)))
+        (t
+         ;; Custom definition: compare versions of non-masked outdated
+         ;; or newest packages.
+         (let ((version (repology-package-field reference-package 'version))
+               ;; Ignore masks not applicable to the current project.
+               (masks
+                (seq-filter (let ((name (repology-project-name project)))
+                              (pcase-lambda (`(,name-re ,_ ,_))
+                                (or (not name-re)
+                                    (string-match name-re name))))
+                            repology-outdated-project-definition))
+               ;; Cache limiting the number of versions comparison.
+               (older nil))
+           (seq-some
+            (lambda (package)
+              (pcase (repology-package-field package 'status)
+                ;; Ignore reference package.
+                ((guard (equal package reference-package)) nil)
+                ;; Ignore packages with a dubious status.
+                ((or "devel" "ignored" "incorrect" "legacy" "noscheme" 
"rolling"
+                     "untrusted")
+                 nil)
+                ;; Ignore masked packages.
+                ((guard (repology--masked-package-p package masks))
+                 nil)
+                ;; Otherwise, compare versions.
+                (_
+                 (let ((v (repology-package-field package 'version)))
+                   (and (not (member v older))
+                        (prog1 (repology-version-< version v)
+                          (push v older)))))))
+            (repology-project-packages project)))))))
+   projects))
+
 
 ;;; Projects
 (defun repology-project-p (object)
@@ -203,6 +261,38 @@ Versions are sorted in descending order."
           ;; Return versions in decreasing order.
           (lambda (s1 s2) (repology-version-< s2 s1)))))
 
+(defun repology--masked-package-p (package masks)
+  "Return non-nil if PACKAGE is masked.
+PACKAGE is a Repology package. MASKS is a list of
+masks, as defined in `repology-outdated-project-definition'."
+  (seq-some
+   (pcase-lambda (`(,_ ,version ,repository-re))
+     (and (or (not version)
+              (progn
+                (unless (string-match
+                         (rx string-start
+                             (or "<=" "<" "=" ">" ">=")
+                             (zero-or-more space))
+                         version)
+                  (user-error "Invalid version comparison string: %S"
+                              version))
+                (let ((prefix (match-string 0 version))
+                      (base (substring version (match-end 0)))
+                      (package-version
+                       (repology-package-field package 'version)))
+                  (pcase prefix
+                    ("=" (and
+                          (not (repology-version-< base package-version))
+                          (not (repology-version-< package-version base))))
+                    ("<=" (not (repology-version-< base package-version)))
+                    (">=" (not (repology-version-< package-version base)))
+                    ("<" (repology-version-< package-version base))
+                    (">" (repology-version-< base package-version))))))
+          (or (not repository-re)
+              (string-match-p repository-re
+                              (repology-package-field package 'repo)))))
+   masks))
+
 
 ;;; Problems
 (defun repology-problem-field (problem field)
diff --git a/repology.el b/repology.el
index 7baa7f8147..36f8b89c6b 100644
--- a/repology.el
+++ b/repology.el
@@ -65,6 +65,30 @@
 ;;                 (repology-search-projects
 ;;                  :search "emacs" :inrepo "gnuguix" :outdated "on")))
 
+;; By default, the package trusts Repology's status values to report
+;; outdated packages.  However, this can introduce false positives.
+;; You can then set `repology-outdated-project-definition' accordingly
+;; to ignore those.
+
+;; For example, with the following set-up, I can look for every
+;; outdated Emacs packages and Asymptote package in GNU Guix, ignoring
+;; bogus versions for "emacs:circe", and "emacs:erlang" package
+;; altogether.  I also sort projects alphabetically.
+
+;; (setq repology-outdated-project-definition
+;;       '(("emacs:circe" "<=2.11" nil)
+;;         ("emacs:erlang" nil nil))
+;;       repology-display-projects-sort-key '("Project" . nil))
+;;
+;;    (let ((repo "gnuguix"))
+;;      (repology-display-projects
+;;       (repology-filter-outdated-projects
+;;           (append (repology-search-projects :search "emacs:" :outdated "on"
+;;                                             :inrepo repo)
+;;                   '("asymptote"))
+;;           repo)
+;;       repo))
+
 ;; Eventually, this library provides an interactive function with
 ;; a spartan interface wrapping this up: `repology'.  Since it builds
 ;; and displays incrementally search filters, you may use it as
@@ -138,6 +162,55 @@ See `repology-check-freedom' for more information."
           (const :tag "Free and unknown projects" include-unknown)
           (const :tag "Every project" nil)))
 
+(defcustom repology-outdated-project-definition nil
+  "Determine how projects are considered as \"outdated\".
+
+This function affects `repology-filter-outdated-projects' function.
+
+When nil, a project is considered as \"outdated\" relatively to
+a repository whenever the corresponding package from that
+repository has the \"outdated\" status.
+
+Otherwise, it can be set to a list of masks.  A mask is a triplet
+
+  (NAME VERSION REPOSITORY)
+
+where NAME is a regexp or nil, VERSION is a string prefixed with
+either \"<\", \"<=\", \"=\", \">\" or \">=\", and REPOSITORY is
+a regexp or nil.
+
+Project's packages are matched against every non-nil criteria in
+the mask.  For example, the mask
+
+  (\"^Foo$\" \"=2\" nil)
+
+matches against project Foo at version 2 (or 2.0.0) only, in any
+repository.
+
+The mask
+
+  (nil nil \"BSD\")
+
+matches against any project from *BSD repositories.
+
+In this case, a project is \"outdated\" when the version of the
+package from the reference repository is older than the version
+of any non-masked package."
+  :type
+  '(choice
+    (const :tag "Use Repology packages status" nil)
+    (repeat :tag "Compare version with unmasked packages"
+     (list :tag "Mask"
+           (choice
+            (regexp :tag "Regexp matching project name")
+            (const :tag "Any project" nil))
+           (choice
+            (string :tag "Version comparison string")
+            (const :tag "Any version" nil))
+           (choice
+            (regexp :tag "Regexp matching repository name")
+            (const :tag "Any repository" nil))))))
+
 (defcustom repology-display-problems-columns
   `(("Project" effname 20 t)
     ("Package name" visiblename 20 t)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]