From bca288822a9ec076b397d9c1e5f69e126b6b63ad Mon Sep 17 00:00:00 2001 From: Ralph Ronnquist Date: Sun, 9 Jan 2022 10:52:25 +1100 Subject: [PATCH] slight restructuring --- autorecommended.lsp | 116 ++++++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 52 deletions(-) diff --git a/autorecommended.lsp b/autorecommended.lsp index 1028a5e..7551236 100755 --- a/autorecommended.lsp +++ b/autorecommended.lsp @@ -1,85 +1,97 @@ #!/usr/bin/newlisp -; Strip away arch tail if any -(define (noarch X) (if (find ":" X) (0 $it X) X)) +; Strip away the arch tail if any of a package +(define (noarch P) (if (find ":" P) (0 $it P) P)) -; Strip away all version specs from a dependency line -(define (noversions X) - (replace " \\([^)]*\\)" (copy X) "" 0)) - -; Return list of "manually installed" -(define (manual) (map noarch (exec "apt-mark showmanual"))) - -; Return list of "all installed" -(define (installed) (map noarch (exec "apt-mark showinstall"))) +; Determine the list of "all installed" +(setf INSTALLED (map noarch (exec "apt-mark showinstall"))) +(write-line 2 (format "There are %d installed packages" (length INSTALLED))) -; Return the provided package, if any, of a given package, or nil -(define (provides P) - (if (exec (format "dpkg-query -W -f '${Provides}' %s" P)) ($it 0) nil)) - -; Return the "raw dependency line" for a package -(define (raw-depends P) - (exec (format "dpkg-query -W -f '${Pre-Depends} ${Depends}' %s" P))) +; Determine the list of "manually installed" +(setf MANUAL (map noarch (exec "apt-mark showmanual"))) +(write-line 2 (format "There are %d manual packages" (length MANUAL))) ; Set up hash table of provided packages by currently installed. This ; is needed for following up dependencies, which for an option ; dependency only automatically resolves the first of options. +(write 2 "Initializing 'provided-by' ") +(setf PROVFMT "dpkg-query -W -f '${Provides}' %s") (define PROV:PROV nil) -(write 2 "Initializing ") -(dolist (P (installed)) - (let ((PV (provides P))) - (if (= (% (inc COUNT) 100)) (write 2 ".")) - (if (PROV P) (push P (PROV P)) (PROV P (list P))) - (if (PROV PV) (push P (PROV PV)) (PROV PV (list P))))) -(dolist (P (PROV)) - (PROV (P 0) (sort (unique (P 1))))) +(dolist (P INSTALLED) + (if (= (% (inc COUNT) 100)) (write 2 ".")) + (if (PROV P) (push P (PROV P)) (PROV P (list P))) + (let (PV (if (exec (format PROVFMT P)) ($it 0))) + (when PV (if (PROV PV) (push P (PROV PV)) (PROV PV (list P)))))) +(dolist (P (PROV)) (PROV (P 0) (sort (unique (P 1))))) (write-line 2 " done") -; Look up the list of packages that providing the P package -(define (provided P) (PROV P)) +; set up a hashtable of recommenders +(write 2 "Initializing 'recommended-by' ") +(setf COUNT 0) +(setf RECFMT "dpkg-query -W -f '${Recommends}' %s") +(define REC:REC nil) +(dolist (P INSTALLED) + (if (= (% (inc COUNT) 100)) (write 2 ".")) + (dolist (R (exec (format RECFMT P))) + (if (REC R) (push P (REC R)) (REC R (list P))))) +(dolist (P (REC)) (REC (P 0) (sort (unique (P 1))))) +(write-line 2 " done") -; Return the "depends choice" of autmatically dependent package -; considering the options of providing that package as currently -; installed. Only the first of providers is an automatic dependency. -; Thus, return a) the depedent package itself if it's the first of its -; providers, or b) that first of providers if the dependent package is -; not among the providers (a fully virtual package), or c) nil if the -; depedent package is a provider but not the first. +; ======================================== +; Set up hashtable for dependencies without those not installed or +; shadowed by non-default choice + +; Returns the "depends choice" of an automatically dependent package +; as supported by currently installed packages. Only the first of +; providers is an automatic dependency. Thus, it returns either a) the +; depedent package itself if it's the first of its providers, or b) +; that first of providers if the dependent package is not among the +; providers (a fully virtual package), or c) nil if the depedent +; package is a provider but not the first. (define (depends-choice P) (let ((Y (if (PROV P) (first $it) nil))) (if (null? Y) nil (member P (PROV P)) (and (= P Y) P) Y))) -; Resolve a depedency item with respect to package provisions, where -; an option depedency only automatically pulls in its first option. -; May return null +; Strip away all version specs from a dependency line +(define (noversions X) (replace " \\([^)]*\\)" (copy X) "" 0)) + +; Resolves a depedency list with respect to installed package +; provisions, where in particular an option depedency only +; automatically pulls in its first option. This may return nil, which +; is for a choice dependency with installed non-default provisioning. (define (depends-choices X) (depends-choice (trim (first (parse (noversions X) "|"))))) -; Fix up a dependency line into list of packages, after cleanup +; Returns the fixed up a dependency line as list of packages. (define (depends-fix X) (clean null? (map depends-choices (clean empty? (map trim (parse X ",")))))) -; Return dependencies of a package, with caching. +(write 2 "Initializing actual 'depends' ") +(setf COUNT 0) +(setf DEPFMT "dpkg-query -W -f '${Pre-Depends} ${Depends}' %s") (define DEP:DEP nil) -(define (depends X) - (if (DEP X) $it (DEP X (flat (map depends-fix (raw-depends X)))))) +(dolist (P INSTALLED) + (if (= (% (inc COUNT) 100)) (write 2 ".")) + (DEP P (flat (map depends-fix (exec (format DEPFMT P)))))) +(write-line 2 " done") + +; Return the dependencies for installed package of empty list otherwise +(define (depends P) (or (DEP P) '())) -; Expand a list of packages to include the closure of dependencies +; Expands a list of packages to include the closure of its dependencies (define (closure L) - (let ((X (sort L))) - (write-line 2 (format "checking %d manual packages" (length X))) - (while (!= X (setf L (sort (union X (apply union (map depends X)))))) - (setf X L) - (write-line 2 (format " %d manual+dependent packages so far" (length X))) + (let ((P (sort L))) + (write-line 2 (format "checking %d manual packages" (length P))) + (while (!= P (setf L (sort (union P (apply union (map depends P)))))) + (setf P L) + (write-line 2 (format " %d with dependencies" (length P))) ) - X)) + P)) ## main: report the set difference between "all installed" and the ## dependency closure of "manually installed" -(let ((X (installed)) (Y nil)) - (write-line 2 (format "There are %d installed packages" (length X))) - (setf Y (difference (installed) (closure (manual)))) +(let ((Y (difference INSTALLED (closure MANUAL)))) (write-line 2 (format "=> %d automatic recommended packages" (length Y))) (map println Y)) -- 2.39.2