]> git.eshelyaron.com Git - emacs.git/commitdiff
emacs-lisp/package.el (package-menu-execute): Delete packages in order.
authorArtur Malabarba <bruce.connor.am@gmail.com>
Thu, 5 Feb 2015 21:36:59 +0000 (19:36 -0200)
committerArtur Malabarba <bruce.connor.am@gmail.com>
Thu, 5 Feb 2015 22:12:47 +0000 (20:12 -0200)
lisp/ChangeLog
lisp/emacs-lisp/package.el

index f9b56421297c0bfeeaf4cd5ba0190d083505baab..be03e569e582e6b2b8b50911b5d1122fba78124b 100644 (file)
@@ -1,3 +1,10 @@
+2015-02-05  Artur Malabarba  <bruce.connor.am@gmail.com>
+
+       * emacs-lisp/package.el (package--sort-by-dependence): New
+       function.  Return PACKAGE-LIST sorted by dependencies.
+       (package-menu-execute): Use it to delete packages in order.
+       (package--sort-deps-in-alist): New function.
+
 2015-02-05  Stefan Monnier  <monnier@iro.umontreal.ca>
 
        * textmodes/css-mode.el (scss-smie--not-interpolation-p): Vars can be
index 67cd44d675818b149a44dff1b9e898dc9c6a3141..2932efa75354a6ecd5e840ec206de3ca0187fee4 100644 (file)
@@ -2351,6 +2351,40 @@ call will upgrade the package."
                (length upgrades)
                (if (= (length upgrades) 1) "" "s")))))
 
+(defun package--sort-deps-in-alist (package only)
+  "Return a list of dependencies for PACKAGE sorted by dependency.
+PACKAGE is included as the first element of the returned list.
+ONLY is an alist associating package names to package objects.
+Only these packages will be in the return value an their cdrs are
+destructively set to nil in ONLY."
+  (let ((out))
+    (dolist (dep (package-desc-reqs package))
+      (when-let ((cell (assq (car dep) only))
+                 (dep-package (cdr-safe cell)))
+        (setcdr cell nil)
+        (setq out (append (package--sort-deps-in-alist dep-package only)
+                          out))))
+    (cons package out)))
+
+(defun package--sort-by-dependence (package-list)
+  "Return PACKAGE-LIST sorted by dependence.
+That is, any element of the returned list is guaranteed to not
+directly depend on any elements that come before it.
+
+PACKAGE-LIST is a list of package-desc objects.
+Indirect dependencies are guaranteed to be returned in order only
+if all the in-between dependencies are also in PACKAGE-LIST."
+  (let ((alist (mapcar (lambda (p) (cons (package-desc-name p) p)) package-list))
+        out-list)
+    (dolist (cell alist out-list)
+      ;; `package--sort-deps-in-alist' destructively changes alist, so
+      ;; some cells might already be empty.  We check this here.
+      (when-let ((pkg-desc (cdr cell)))
+        (setcdr cell nil)
+        (setq out-list
+              (append (package--sort-deps-in-alist pkg-desc alist)
+                      out-list))))))
+
 (defun package-menu-execute (&optional noquery)
   "Perform marked Package Menu actions.
 Packages marked for installation are downloaded and installed;
@@ -2398,7 +2432,7 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm."
                      (length delete-list)
                      (mapconcat #'package-desc-full-name
                                 delete-list ", ")))))
-          (dolist (elt delete-list)
+          (dolist (elt (package--sort-by-dependence delete-list))
             (condition-case-unless-debug err
                 (package-delete elt)
               (error (message (cadr err)))))
@@ -2412,7 +2446,8 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm."
                       (format "These %d packages are no longer needed, delete them (%s)? "
                               (length removable)
                               (mapconcat #'symbol-name removable ", "))))
-            (mapc (lambda (p) (package-delete (cadr (assq p package-alist))))
+            ;; We know these are removable, so we can use force instead of sorting them.
+            (mapc (lambda (p) (package-delete (cadr (assq p package-alist)) 'force 'nosave))
                   removable))))
       (package-menu--generate t t))))