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

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

[elpa] externals/repology afe973b 3/4: * repology.el: Keep free packages


From: Stefan Monnier
Subject: [elpa] externals/repology afe973b 3/4: * repology.el: Keep free packages rather than weed out non-free ones
Date: Sat, 16 Jan 2021 16:01:13 -0500 (EST)

branch: externals/repology
commit afe973b703f3a702169b99389745241c26cb2c72
Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
Commit: Stefan Monnier <monnier@iro.umontreal.ca>

    * repology.el: Keep free packages rather than weed out non-free ones
    
    (repology-free-only-projects): Rename from
    `repology-ignore-non-free-projects`.
    (repology-non-free-licenses-regexps): Remove variable.
    (repology--request): Don't unhex the body.  Append properties rather
    than nesting them within a `status` property.
    (repology--get, repology-list-repositories): Simplify accordingly.
    (repology-lookup-project): Rename from `repology-project-lookup`.
    (repology-search-projects): Rename from `repology-projects-search`.
    Use `repology-free-p`.
    (repology-report-problems): Rename from `repology-repository-problems`.
    
    * repology-license.el: New file.
---
 repology-license.el | 359 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 repology.el         | 118 ++++++-----------
 2 files changed, 397 insertions(+), 80 deletions(-)

diff --git a/repology-license.el b/repology-license.el
new file mode 100644
index 0000000..5e76f63
--- /dev/null
+++ b/repology-license.el
@@ -0,0 +1,359 @@
+;;; repology-license.el --- Freedom check for Repology  -*- lexical-binding: 
t; -*-
+
+;; Copyright (C) 2021  Free Software Foundation, Inc.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library provides the `repology-free-p' function, which returns
+;; a non-nil value when a package or a project can be considered as
+;; free.
+
+;; The decision is made by polling a number of "Reference
+;; repositories", defined in `repology-license-reference-repositories'.
+;; If the ratio of "Free" votes is equal or above
+;; `repology-license-poll-threshold', the project is declared as free.
+
+;; In order to see the results of each vote, and possibly debug the
+;; process, you can set `repology-license-debug' to a non-nil value.
+
+
+;;; Constants
+(defconst repology-license-reference-repositories
+  '(("debian"    "main"     t)
+    ("debian"    "contrib"  t)
+    ("gnuguix"   nil        t)
+    ("hyperbola" nil        t)
+    ("parabola"  nil        t)
+    ("pureos"    nil        t)
+    ("trisquel"  nil        t)
+    ("gnu_elpa"  nil        t)
+    ("^fedora"   nil        repology--license-check:fedora)
+    ("^gentoo"   nil        repology--license-check:gentoo)
+    ("^opensuse" "/oss"     repology--license-check:opensuse-oss)
+    ("debian"    "non-free" nil)
+    ("^opensuse" "/non-oss" nil))
+  "List of repositories providing a reliable license information.
+
+This is a list of triplets (REPO SUBREPO PREDICATE) where:
+
+ REPO is a regexp matching the internal name of a repository;
+ SUBREPO is a regexp matching a sub-repository or nil;
+ PREDICATE is either a boolean or a function called with one string argument.
+
+When PREDICATE is a function, it must return a non-nil value if the argument
+is a free license according to the repository.  If PREDICATE is t, we trust
+the repository to provide only free software.  Conversely, PREDICATE is nil
+when the repository is known to reference only non-free software.
+
+A repository with a PREDICATE function is expected to have the following
+properties:
+- it audits carefully the licenses it reports;
+- it uses a consistent, and documented, license syntax;
+- Repology properly fetches the licenses of its packages.
+  See URL `https://repology.org/repositories/fields'.")
+
+(defconst repology-license-poll-threshold 0.5
+  "Ratio of votes above which a package is declared to be free.")
+
+
+;;; Tools
+(defun repology--license-interpret-vote (free votes)
+  "Return freedom vote result as a boolean.
+FREE is the number of \"Free\" votes.  VOTES is the total number of votes."
+  (and (> votes 0)
+       (>= (/ (float free) votes) repology-license-poll-threshold)))
+
+
+;;; Reference Repository: Fedora
+(defun repology--license-check:fedora (license)
+  "Return a non-nil value if LICENSE is free, according to Fedora.
+See URL \
+`https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/'"
+  (let ((case-fold-search t)
+        ;; Anything in Fedora is free, unless its license contains the
+        ;; following.
+        (non-free-license-re
+         (rx word-start "Redistributable, no modification permitted" 
word-end)))
+    (not (string-match non-free-license-re license))))
+
+
+;;; Reference Repository: Gentoo
+(defconst repology--license-identifiers:gentoo
+  (list
+   ;; GPL-COMPATIBLE
+   "AGPL-3" "AGPL-3+" "Apache-2.0" "Apache-2.0-with-LLVM-exceptions"
+   "Artistic-2" "Boost-1.0" "BSD" "BSD-2" "CC0-1.0" "CeCILL-2"
+   "Clarified-Artistic" "Clear-BSD"  "ECL-2.0" "FTL"
+   "gcc-runtime-library-exception-3.1" "GPL-1" "GPL-1+" "GPL-2" "GPL-2+" 
"GPL-3"
+   "GPL-3+" "GPL-2-with-classpath-exception" "GPL-2-with-exceptions"
+   "GPL-2-with-font-exception" "GPL-2-with-linking-exception"
+   "GPL-2-with-MySQL-FLOSS-exception" "GPL-2+-with-openssl-exception"
+   "GPL-3+-with-cuda-exception" "GPL-3+-with-cuda-openssl-exception"
+   "GPL-3-with-font-exception" "GPL-3+-with-opencl-exception"
+   "GPL-3+-with-opencl-openssl-exception" "GPL-3-with-openssl-exception"
+   "Transmission-OpenSSL-exception" "UPX-exception" "HPND" "IJG" "ISC" "LGPL-2"
+   "LGPL-2+" "LGPL-2.1" "LGPL-2.1+" "LGPL-3" "LGPL-3+"
+   "LGPL-2-with-linking-exception" "LGPL-2.1-with-linking-exception"
+   "LGPL-3-with-linking-exception" "Nokia-Qt-LGPL-Exception-1.1" "libgcc"
+   "libstdc++" "metapackage" "MIT" "MPL-2.0" "OPENLDAP" "PSF-2" "PSF-2.2"
+   "PSF-2.3" "PSF-2.4" "public-domain" "PYTHON" "qwt" "Ruby" "Ruby-BSD"
+   "SGI-B-2.0" "Sleepycat" "tanuki-community" "unicode" "Unlicense" "UoI-NCSA"
+   "vim" "W3C" "WTFPL-2" "wxWinLL-3.1" "ZLIB" "ZPL"
+   ;; FSF-APPROVED
+   "AFL-2.1" "AFL-3.0" "Apache-1.0" "Apache-1.1" "APSL-2" "BSD-4" "CDDL" "CNRI"
+   "CPAL-1.0" "CPL-1.0" "EPL-1.0" "EPL-2.0" "EUPL-1.1" "gnuplot" "IBM"
+   "LPPL-1.2" "MPL-1.0" "MPL-1.1" "Ms-PL" "NPL-1.1" "openssl" "OSL-1.1"
+   "OSL-2.0" "OSL-2.1" "PHP-3.01" "QPL" "QPL-1.0" "Zend-2.0"
+   ;; OSI-APPROVED
+   "AFL-3.0" "AGPL-3" "AGPL-3" "Apache-1.1" "Apache-2.0" "APL-1.0" "APSL-2"
+   "Artistic" "Artistic-2" "Boost-1.0" "BSD" "BSD-2" "CDDL" "CNRI" "CPAL-1.0"
+   "CPL-1.0" "ECL-2.0" "EPL-1.0" "EPL-2.0" "EUPL-1.1" "GPL-1" "GPL-2" "GPL-2"
+   "GPL-3" "GPL-3" "HPND" "IBM" "IPAfont" "ISC" "LGPL-2" "LGPL-2.1" "LGPL-2.1"
+   "LGPL-3" "LGPL-3" "LPPL-1.3c" "MIT" "MPL-1.0" "MPL-1.1" "MPL-2.0" "Ms-PL"
+   "nethack" "NOSA" "OFL-1.1"  "OSL-2.1" "PHP-3" "PHP-3.01" "POSTGRESQL" 
"PSF-2"
+   "QPL" "Sleepycat" "UoI-NCSA" "W3C" "Watcom-1.0" "wxWinLL-3" "ZLIB" "ZPL"
+   ;; MISC-FREE
+   "Allegro" "alternate" "AMPAS" "bea.ri.jsr173" "BEER-WARE" "boehm-gc" "BSD-1"
+   "BSD-with-attribution" "BSD-with-disclosure" "buddy" "bufexplorer.vim"
+   "BZIP2" "canfep" "CAOSL" "CDDL-Schily" "CeCILL-C" "CLX" "CMake" "CPL-0.5"
+   "CRACKLIB" "Crypt-IDEA" "DES" "docbook" "dom4j" "DUMB-0.9.3"
+   "eGenixPublic-1.1" "ElementTree" "Emacs" "ErlPL-1.1" "FastCGI" "feh"
+   "File-MMagic" "Flashpix" "FLEX" "flexmock" "FLTK" "freetts" "FVWM" "gd"
+   "gsm" "HTML-Tidy" "htmlc" "iASL" "icu" "IDPL" "imagemagick" "Info-ZIP"
+   "inner-net" "Interbase-1.0" "ipadic" "ipx-utils" "Ispell" "JasPer2.0" "JDOM"
+   "JNIC" "JOVE" "Khronos-CLHPP" "LambdaMOO" "LIBGLOSS" "libmng" "libpng"
+   "libpng2" "libtiff" "LLVM-Grant" "LPPL-1.3" "LPPL-1.3b" "lsof"
+   "Mail-Sendmail" "mapm-4.9.5" "matplotlib" "Mini-XML" "minpack"
+   "MIT-with-advertising" "mm" "mpich2" "NCSA-HDF" "netcat" "NEWLIB" "ngrep"
+   "Old-MIT" "openafs-krb5-a" "Openwall" "otter" "PCRE" "perforce" "photopc"
+   "PHP-2.02" "pngcrush" "pngnq" "Princeton" "psutils" "qmail-nelson" "rc"
+   "rdisc" "regexp-UofT" "repoze" "RSA" "rwpng" "scanlogd" "Sendmail"
+   "Sendmail-Open-Source" "shrimp" "SMAIL" "Snd" "SNIA" "SSLeay" "Subversion"
+   "SVFL" "symlinks" "tablelist" "tcltk" "tcp_wrappers_license" "TeX"
+   "TeX-other-free" "the-Click-license" "Time-Format" "Time-modules" "tm-align"
+   "torque-2.5" "totd" "Toyoda" "UCAR-Unidata" "URT" "VTK" "w3m" "x2x" "xbatt"
+   "xboing" "XC" "Xdebug" "xtrs" "xvt" "YaTeX" "yuuji" "ZSH"
+   ;; FSF-APPROVED-OTHER.
+   "Arphic" "CC-BY-2.0" "CC-BY-2.5" "CC-BY-3.0" "CC-BY-4.0" "CC-BY-SA-2.0"
+   "CC-BY-SA-2.5" "CC-BY-SA-3.0" "CC-BY-SA-4.0" "FDL-1.1" "FDL-1.1+" "FDL-1.2"
+   "FDL-1.2+" "FDL-1.3" "FDL-1.3+" "FreeArt" "GPL-1" "GPL-1+" "GPL-2" "GPL-2+"
+   "GPL-3" "GPL-3+" "IPAfont" "OFL" "OFL-1.1" "OPL"
+   ;; MISC-FREE-DOCS.
+   "BitstreamVera" "CC-PD" "CC-BY-SA-1.0" "CC-SA-1.0" "LDP-1" "LDP-1a"
+   "man-pages" "man-pages-posix" "man-pages-posix-2013" "MaxMind2" 
"mplus-fonts"
+   "myspell-en_CA-KevinAtkinson" "quake1-textures" "Texinfo-manual"
+   "UbuntuFontLicense-1.0" "Unicode_Fonts_for_Ancient_Scripts" "vlgothic"
+   "wxWinFDL-3")
+  "List of identifiers considered as free licenses by Gentoo
+See URL `https://wiki.gentoo.org/wiki/License_groups'.")
+
+(defun repology--license-gentoo:skip-whitespace ()
+  "Skip past the whitespace at point."
+  (skip-chars-forward " \t"))
+
+(defun repology--license-gentoo:skip-non-whitespace ()
+  "Skip past the whitespace at point."
+  (skip-chars-forward "^ \t"))
+
+(defun repology--license-gentoo:advance (&optional n)
+  "Advance N characters forward."
+  (forward-char n))
+
+(defun repology--license-gentoo:peek (&optional n)
+  "Advance N characters forward."
+  (following-char))
+
+(defun repology--license-gentoo:and ()
+  "Return license freedom for the \"and\" construct at point."
+  ;; Skip past "(" token.
+  (repology--license-gentoo:advance 1)
+  (repology--license-gentoo:skip-whitespace)
+  (let ((value t))
+    (while (/= (repology--license-gentoo:peek) ?\))
+      (repology--license-gentoo:skip-whitespace)
+      (unless (repology--license-gentoo:read-next)
+        (setq value nil)))
+    ;; Skip past ")" character, and to next token.
+    (repology--license-gentoo:advance 1)
+    (repology--license-gentoo:skip-whitespace)
+    value))
+
+(defun repology--license-gentoo:or ()
+  "Return license freedom for the \"or\" construct at point."
+  ;; Skip past "|| (" token.
+  (repology--license-gentoo:advance 4)
+  (repology--license-gentoo:skip-whitespace)
+  (let ((value nil))
+    (while (/= (repology--license-gentoo:peek) ?\))
+      (when (repology--license-gentoo:read-next)
+        (setq value t)))
+    ;; Skip past ")" character, and to next token.
+    (repology--license-gentoo:advance 1)
+    (repology--license-gentoo:skip-whitespace)
+    value))
+
+(defun repology--license-gentoo:identifier ()
+  "Return freedom of the license identifier at point."
+  (let ((origin (point)))
+    (repology--license-gentoo:skip-non-whitespace)
+    (let ((value (member-ignore-case (buffer-substring origin (point))
+                                     repology--license-identifiers:gentoo)))
+      (repology--license-gentoo:skip-whitespace)
+      value)))
+
+(defun repology--license-gentoo:parameter ()
+  "Assume parameter at point is set, and return license freedom accordingly."
+  ;; Skip past parameter.
+  (repology--license-gentoo:skip-non-whitespace)
+  (repology--license-gentoo:skip-whitespace)
+  (repology--license-gentoo:and))
+
+(defun repology--license-gentoo:read-next ()
+  "Return license freedom for next token, and move point past it."
+  (let ((parameter-re (rx (opt "!") (one-or-more (any alnum "-" "_")) "?")))
+    (pcase (repology--license-gentoo:peek)
+      (?\| (repology--license-gentoo:or))
+      (?\( (repology--license-gentoo:and))
+      ((guard (looking-at parameter-re))
+       (repology--license-gentoo:parameter))
+      (_
+       (repology--license-gentoo:identifier)))))
+
+(defun repology--license-check:gentoo (license)
+  "Return a non-nil value if LICENSE is free, according to Gentoo."
+  (with-temp-buffer
+    (insert license)
+    (goto-char 1)
+    (repology--license-gentoo:skip-whitespace)
+    (let ((value (not (eobp))))         ;blank string check
+      (while (and value (/= (repology--license-gentoo:peek) 0))
+        (unless (repology--license-gentoo:read-next)
+          (setq value nil)))
+      value)))
+
+
+;;; Reference Repository: OpenSUSE (OSS)
+(defun repology--license-check:opensuse-oss (license)
+  "Return a non-nil value if LICENSE is free, according to OpenSUSE (OSS).
+See URL `https://en.opensuse.org/openSUSE:Packaging_guidelines#Licensing'."
+  (let ((case-fold-search t)
+        ;; Anything in Fedora is free, unless its license contains the
+        ;; following.
+        (non-free-license-re
+         (rx word-start "SUSE-Firmware" word-end)))
+    (not (string-match non-free-license-re license))))
+
+
+;;; License Check Debugging
+(defvar repology-license-debug nil
+  "When non-nil, display explanations when a project declared non-free.
+Information is displayed in \"*Repology: License Debug*\" buffer.")
+
+(defun repology--license-debug-line (package free)
+  "Format license debug information for PACKAGE.
+When FREE is non-nil, declare PACKAGE was reported as free."
+  (let ((repo (repology-package-field package 'repo))
+        (subrepo (repology-package-field package 'subrepo))
+        (name (repology-package-field package 'visiblename)))
+    (format "%s (%s%s) => %s\n"
+            name
+            repo
+            (if subrepo (concat "/" subrepo) "")
+            (if free "Free" "Non-Free"))))
+
+(defun repology--license-debug-display (project reports free votes)
+  "Print license check output for non-free PROJECT.
+REPORTS is a list of strings, as returned by `repology--license-debug-line'.
+FREE is the number of free packages in PROJECT.  VOTES is the number of 
packages
+from reference repositories in PROJECT."
+  (with-current-buffer (get-buffer-create "*Repology: License Debug*")
+    (insert (format "=== Project %S: %s (ratio: %.2f) ===\n"
+                    (repology-project-name project)
+                    (if (repology--license-interpret-vote free votes)
+                        "FREE"
+                      "NON-FREE")
+                    (if (= votes 0)
+                        0
+                      (/ (float free) votes))))
+    (apply #'insert reports)
+    (insert "\n")))
+
+
+;;; Main Function
+(defun repology--license-find-reference-repository (package)
+  "Return the reference repository containing PACKAGE, or nil.
+Return value is a triplet per `repology-license-reference-repositories'."
+  (let ((repo (repology-package-field package 'repo))
+        (subrepo (repology-package-field package 'subrepo)))
+    (seq-find (pcase-lambda (`(,r ,s ,_))
+                (and (string-match r repo)
+                     (or (not s)
+                         (and subrepo (string-match s subrepo)))))
+              repology-license-reference-repositories)))
+
+(defun repology--license-free-p (package &optional repository)
+  "Return a non-nil value when PACKAGE is free.
+A package is free when any reference repository can attest it uses only free
+licenses.  When optional argument REPOSITORY is non-nil, use it as a 
reference."
+  (pcase (or repository (repology--license-find-reference-repository package))
+    ('nil nil)
+    (`(,_ ,_ ,(and (pred functionp) p))
+     (seq-every-p p (repology-package-field package 'licenses)))
+    (`(,_ ,_ ,boolean) boolean)
+    (other (error "Wrong repository definition: %S" other))))
+
+(defun repology-free-p (datum)
+  "Return a non-nil value when DATUM is free.
+
+DATUM is a project or a package.
+
+A package is free when any reference repository can attest it uses only free
+licenses.  See `repology-license-reference-repositories' for a list of such
+repositories.
+
+A project is free if the ratio of free packages among the packages from
+reference repositories is above `repology-license-poll-threshold'.
+A project without any package from these repositories is declared as non-free.
+
+Of course, it is not a legal statement, merely an indicator."
+  (pcase datum
+    ((pred repology-package-p) (repology--license-free-p datum))
+    ((pred repology-project-p)
+     (let ((votes 0)
+           (yes 0)
+           (reports nil)
+           (voters nil))
+       (dolist (package (repology-project-packages datum))
+         (pcase (repology--license-find-reference-repository package)
+           ('nil nil)
+           (repository
+            (unless (member repository voters)
+              (cl-incf votes)
+              (push repository voters)  ;a repository votes only once
+              (let ((free (repology--license-free-p package repository)))
+                (when free (cl-incf yes))
+                (when repology-license-debug
+                  (push (repology--license-debug-line package free)
+                        reports)))))))
+       ;; Maybe display vote reports as debugging information.
+       (when repology-license-debug
+         (repology--license-debug-display datum reports yes votes))
+       ;; Return value.
+       (repology--license-interpret-vote yes votes)))
+    (_ (user-error "Wrong argument type: %S" datum))))
+
+(provide 'repology-license)
+;;; repology-license.el ends here
diff --git a/repology.el b/repology.el
index 38c7033..1df64e4 100644
--- a/repology.el
+++ b/repology.el
@@ -6,7 +6,7 @@
 ;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
 ;; Keywords: web
 ;; Package-Requires: ((emacs "26.1"))
-;; Version: 0.10
+;; Version: 0
 
 ;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
@@ -29,14 +29,14 @@
 ;; The results of a query revolve around three types of objects:
 ;; projects, packages and problems.  Using this library, you can find
 ;; projects matching certain criteria, packages in a given project,
-;; and possible problems in some repository.  See `repology-projects-search',
-;; `repology-project-lookup', and `repology-repository-problems'.
+;; and possible problems in some repository.  See `repology-search-projects',
+;; `repology-lookup-project', and `repology-report-problems'.
 ;; Projects-related requests are limited to `repology-projects-limit'.
 ;; All requests are cached during `repology-cache-duration' seconds.
 ;;
 ;; By default, projects including packages with a known non-free license
 ;; are not included in the search results.  You can control this behavior
-;; with the variable `repology-ignore-non-free-projects'.
+;; with the variable `repology-free-only-projects'.
 
 ;; You can then access data from those various objects using dedicated
 ;; accessors.  See, for example, `repology-project-name',
@@ -61,7 +61,7 @@
 ;;     (seq-filter (lambda (project)
 ;;                   (not (member (repology-project-name project)
 ;;                                my-ignored-projects)))
-;;                 (repology-projects-search
+;;                 (repology-search-projects
 ;;                  :search "emacs" :inrepo "gnuguix" :outdated "on")))
 
 ;; Eventually, this library provides an interactive function with
@@ -84,6 +84,8 @@
 (require 'tabulated-list)
 (require 'url)
 
+(require 'repology-license)
+
 
 ;;; Macros
 ;; XXX: It is a macro because we need it to be available in defcustoms.
@@ -177,29 +179,14 @@ Repology claims to update its repository hourly.
 A value of 0 prevents any caching."
   :type 'integer)
 
-(defcustom repology-ignore-non-free-projects t
-  "When non-nil, ignore projects with a non-free license from searches.
-
-See `repology-non-free-licenses-regexps' for information about how a project
-is assumed to be non-free.
+(defcustom repology-free-only-projects t
+  "When non-nil, return only free projects from searches.
 
-Projects with missing or erroneous licensing information may still be 
displayed.
-Use your judgement!"
+Declaring a project as free the consequence of a very conservative process.
+Free projects with missing licensing information, or too confidential, may be
+ignored.  See `repology-free-p' for more information."
   :type 'boolean)
 
-(defcustom repology-non-free-licenses-regexps
-  '("commercial" "freeware" "google-chrome" "no modification permitted"
-    "microsoft" "nonfree" "proprietary" "restrictive" "skype" "unfree"
-    "valvesteamlicense")
-  "List of licenses field regexps known to match non-free licenses.
-
-Any project containing at least one package with a license matching one of 
these
-regexps is considered to be non-free.  Case is ignored.
-
-Feel free to contact the maintainer of this library to suggest additional
-default regexps."
-  :type '(repeat regexp))
-
 (defcustom repology-status-faces
   '(("incorrect" . error)
     ("newest" . highlight)
@@ -442,10 +429,8 @@ the request."
               (forward-line))
             (forward-line)
             (unless (eobp)
-              (setq body
-                    (url-unhex-string
-                     (buffer-substring (point) (point-max)))))
-            (list :status status :header (nreverse header) :body body)))
+              (setq body (buffer-substring (point) (point-max))))
+            (append status (list :header (nreverse header) :body body))))
       (kill-buffer process-buffer))))
 
 (defun repology--get (action value start)
@@ -460,7 +445,7 @@ Information is returned as parsed JSON."
         (let ((request (repology--request
                         (repology--build-url action value start)
                         '(("Content-Type" . "application/json")))))
-          (pcase (plist-get (plist-get request :status) :reason)
+          (pcase (plist-get request :reason)
             ("OK"
              (let ((body (repology--parse-json (plist-get request :body))))
                (repology--cache-put key body)
@@ -870,7 +855,7 @@ Return a list of strings.  When option argument FULL-NAME 
is non-nil, list
 the repositories with their full name instead of their internal name."
   (unless repology--repositories
     (let ((request (repology--request repology-statistics-url)))
-      (pcase (plist-get (plist-get request :status) :reason)
+      (pcase (plist-get request :reason)
         ("OK"
          (let ((body (plist-get request :body))
                (repositories nil)
@@ -953,37 +938,14 @@ See URL 
`https://github.com/repology/libversion/blob/master/doc/ALGORITHM.md'."
       ;; Strings S1 and S2 represent equal versions.
       nil)))
 
-(defun repology-non-free-p (datum)
-  "Return a non-nil value when DATUM is non-free.
-
-DATUM is a project or a package.  A package is non-free when one of its 
licenses
-is recognized as non-free.  A project is non-free when at least one of its
-packages is non-free.  See `repology-non-free-licenses-regexps' for a list of
-regexps known to match non-free licenses."
-  (let ((case-fold-search t))
-    ;; Non-nil whenever one of the packages in the list...
-    (seq-some (lambda (package)
-                ;; ... contains at least one license...
-                (seq-some (lambda (license)
-                            (message "License: %s" license)
-                            ;; ... matching a non-free license regexp.
-                            (seq-some (lambda (regexp)
-                                        (string-match regexp license))
-                                      repology-non-free-licenses-regexps))
-                          (repology-package-field package 'licenses)))
-              (pcase datum
-                ((pred repology-project-p) (repology-project-packages datum))
-                ((pred repology-package-p) (list datum))
-                (_ (user-error "Wrong argument type: %S" datum))))))
-
 
 ;;; Search functions
-(defun repology-project-lookup (name)
+(defun repology-lookup-project (name)
   "List packages for project NAME.
 NAME is a string.  Return a list of packages."
   (repology--get 'project name nil))
 
-(defun repology-projects-search (&rest filters)
+(defun repology-search-projects (&rest filters)
   "Retrieve results of an advanced search in Repology.
 
 FILTERS helps refining the search with the following keywords:
@@ -1036,18 +998,13 @@ FILTERS helps refining the search with the following 
keywords:
      return projects which have related ones (may require merging)
 
 Return a list of projects.  Projects with a known non-free license are removed
-from output, unless `repology-ignore-non-free-projects' is nil."
+from output, unless `repology-free-only-projects' is nil."
   (let ((result nil)
         (name nil))
     (catch :exit
       (while t
         (let ((request (repology--get 'projects filters name)))
-          ;; If we are resuming a previous search, drop the first
-          ;; match since it was also the last match in the previous
-          ;; search.
-          (setq result (if result
-                           (append result (cdr request))
-                         request))
+          (setq result (append result (cdr request)))
           (cond
            ;; Too many matches: drop those above limit and exit.
            ((<= repology-projects-limit (length result))
@@ -1056,20 +1013,21 @@ from output, unless `repology-ignore-non-free-projects' 
is nil."
            ;; Matches exhausted: exit and return result.
            ((> repology-projects-hard-limit (length request))
             (throw :exit result))
-           ;; Resume search starting from the last project found.
+           ;; Resume search starting from an imaginary project located
+           ;; right after the last project found, alphabetically.
            (t
             (setq name
                   (pcase (last request)
                     (`(,(and (pred repology-project-p) project))
-                     (repology-project-name project))
+                     (concat (repology-project-name project) "-"))
                     (other (error "Invalid request result: %S" other)))))))))
     ;; Trim non-free projects.
-    (if (not repology-ignore-non-free-projects)
+    (if (not repology-free-only-projects)
         result
-      (seq-filter (lambda (project) (not (repology-non-free-p project)))
+      (seq-filter (lambda (project) (repology-free-p project))
                   result))))
 
-(defun repology-repository-problems (repository)
+(defun repology-report-problems (repository)
   "List problems related to REPOSITORY.
 REPOSITORY is a string.  Return a list of problems."
   (unless (member repository (repology-list-repositories))
@@ -1116,7 +1074,7 @@ or nil.  This is the default value for 
`repology-display-projects-columns'."
 
 (defun repology-display-packages (packages)
   "Display PACKAGES as a tabulated list.
-PACKAGES is a list of packages, as returned by `repology-project-lookup'.
+PACKAGES is a list of packages, as returned by `repology-lookup-project'.
 Columns are displayed according to `repology-display-packages-columns'."
   (repology--make-display packages
                           "*Repology Packages*"
@@ -1126,7 +1084,7 @@ Columns are displayed according to 
`repology-display-packages-columns'."
 (defun repology-display-projects (projects &optional selected)
   "Display PROJECTS as a tabulated list.
 
-PROJECTS is a list of projects, as returned by `repology-projects-search'.
+PROJECTS is a list of projects, as returned by `repology-search-projects'.
 Optional argument SELECTED, when non-nil, is the name of a repository to which
 all projects are related.
 
@@ -1142,7 +1100,7 @@ Columns are displayed according to 
`repology-display-projects-columns'."
 
 (defun repology-display-problems (problems)
   "Display PROBLEMS as a tabulated list.
-PROBLEMS is a list of problems, as returned by `repology-repository-problems'.
+PROBLEMS is a list of problems, as returned by `repology-report-problems'.
 Columns are displayed according to `repology-display-problems-columns'."
   (repology--make-display problems
                           "*Repology Problems*"
@@ -1158,14 +1116,14 @@ Columns are displayed according to 
`repology-display-problems-columns'."
 This function interacts with Repology API in three ways.  You can:
 
 1. List all packages associated to a given project.  See function
-   `repology-project-lookup'.
+   `repology-lookup-project'.
 
 2. Find potential problems related to packages in a repository, using
-   `repology-repository-problems'.  The function provides the list of
+   `repology-report-problems'.  The function provides the list of
    repositories to choose from.
 
 3. Search for projects matching some criteria.  Here, you build incrementally
-   a filter by selecting properties from a list.  See 
`repology-projects-search'
+   a filter by selecting properties from a list.  See 
`repology-search-projects'
    for more information.  Select \"OK\" to actually send the request.
 
    During the filter creation, you may change the maximum number of projects
@@ -1173,14 +1131,14 @@ This function interacts with Repology API in three 
ways.  You can:
    value is `repology-projects-limit'."
   (interactive)
   (pcase (read-char "Action: [S]earch projects  [L]ookup project  \
-\[B]rowse repository problems")
-    ((or ?b ?B)
+\[R]eport repository problems")
+    ((or ?r ?R)
      (repology-display-problems
-      (repology-repository-problems
+      (repology-report-problems
        (repology--query-repository "Repository: " nil))))
     ((or ?l ?L)
      (repology-display-packages
-      (repology-project-lookup (read-string "Project: "))))
+      (repology-lookup-project (read-string "Project: "))))
     ((or ?s ?S)
      (let* ((query nil)
             (limit repology-projects-limit)
@@ -1215,10 +1173,10 @@ This function interacts with Repology API in three 
ways.  You can:
                   (setq query (plist-put query filter value))))))))
        ;; Eventually send complete request to Repology API.
        (repology-display-projects (let ((repology-projects-limit limit))
-                                    (apply #'repology-projects-search query))
+                                    (apply #'repology-search-projects query))
                                   ;; Selected repository, or nil.
                                   (plist-get query :inrepo))))
-    (c (user-error "Unknown answer: %c.  Aborting" c))))
+    (_ (user-error "Unknown answer.  Aborting"))))
 
 
 (provide 'repology)



reply via email to

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