aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Malabarba2015-04-05 23:39:43 +0100
committerArtur Malabarba2015-04-06 11:19:04 +0100
commit7471fc47b4bc78ed1a55e045ddb2d0b3eba19305 (patch)
tree4f0e502a8ce8eadc5959f301057c656de55fb5b4
parent6701726b98261f862e4708aadb6d518b886cf8e2 (diff)
downloademacs-7471fc47b4bc78ed1a55e045ddb2d0b3eba19305.tar.gz
emacs-7471fc47b4bc78ed1a55e045ddb2d0b3eba19305.zip
emacs-lisp/package.el (package-menu-execute): Add async support
Most install/delete logic is now in `package-menu--perform-transaction', and this function is called asynchronously if `package-menu-async' is non-nil.
-rw-r--r--lisp/ChangeLog2
-rw-r--r--lisp/emacs-lisp/package.el67
2 files changed, 40 insertions, 29 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 07e95429375..2fa005484a8 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -88,6 +88,8 @@
88 (package-menu-execute): Use it to prompt the user about operations 88 (package-menu-execute): Use it to prompt the user about operations
89 to be executed. 89 to be executed.
90 (package-install): Add ASYNC and CALLBACK arguments. 90 (package-install): Add ASYNC and CALLBACK arguments.
91 (package-menu--perform-transaction): New function.
92 (package-menu-execute): Use it to install and delete packages.
91 93
922015-04-05 Pete Williamson <petewil@chromium.org> (tiny-change) 942015-04-05 Pete Williamson <petewil@chromium.org> (tiny-change)
93 95
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 6d5d46c14bb..acfab92e7eb 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -1368,8 +1368,8 @@ Once it's empty, run `package--post-download-archives-hook'."
1368 (remove entry package--downloads-in-progress)) 1368 (remove entry package--downloads-in-progress))
1369 ;; If this was the last download, run the hook. 1369 ;; If this was the last download, run the hook.
1370 (unless package--downloads-in-progress 1370 (unless package--downloads-in-progress
1371 (package--build-compatibility-table)
1372 (package-read-all-archive-contents) 1371 (package-read-all-archive-contents)
1372 (package--build-compatibility-table)
1373 ;; We message before running the hook, so the hook can give 1373 ;; We message before running the hook, so the hook can give
1374 ;; messages as well. 1374 ;; messages as well.
1375 (message "Package refresh done") 1375 (message "Package refresh done")
@@ -2724,6 +2724,36 @@ not both."
2724 (mapconcat #'package-desc-full-name del ", "))))) 2724 (mapconcat #'package-desc-full-name del ", ")))))
2725 "? "))) 2725 "? ")))
2726 2726
2727(defun package-menu--perform-transaction (install-list delete-list &optional async)
2728 "Install packages in INSTALL-LIST and delete DELETE-LIST.
2729If ASYNC is non-nil, perform the installation downloads
2730asynchronously."
2731 ;; While there are packages to install, call `package-install' on
2732 ;; the next one and defer deletion to the callback function.
2733 (if install-list
2734 (let* ((pkg (car install-list))
2735 (rest (cdr install-list))
2736 ;; Don't mark as selected if it's a new version of an
2737 ;; installed package.
2738 (dont-mark (and (not (package-installed-p pkg))
2739 (package-installed-p
2740 (package-desc-name pkg)))))
2741 (package-install
2742 pkg dont-mark async
2743 (lambda () (package-menu--perform-transaction rest delete-list async))))
2744 ;; Once there are no more packages to install, proceed to
2745 ;; deletion.
2746 (dolist (elt (package--sort-by-dependence delete-list))
2747 (condition-case-unless-debug err
2748 (package-delete elt)
2749 (error (message (cadr err)))))
2750 (when package-selected-packages
2751 (when-let ((removable (package--removable-packages)))
2752 (message "These %d packages are no longer needed, type `M-x package-autoremove' to remove them (%s)"
2753 (length removable)
2754 (mapconcat #'symbol-name removable ", "))))
2755 (package-menu--post-refresh)))
2756
2727(defun package-menu-execute (&optional noquery) 2757(defun package-menu-execute (&optional noquery)
2728 "Perform marked Package Menu actions. 2758 "Perform marked Package Menu actions.
2729Packages marked for installation are downloaded and installed; 2759Packages marked for installation are downloaded and installed;
@@ -2749,28 +2779,9 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm."
2749 (user-error "No operations specified")) 2779 (user-error "No operations specified"))
2750 (when (or noquery 2780 (when (or noquery
2751 (package-menu--prompt-transaction-p install-list delete-list)) 2781 (package-menu--prompt-transaction-p install-list delete-list))
2752 ;; Don't mark as selected if it's a new version of an installed 2782 ;; This calls `package-menu--generate' after everything's done.
2753 ;; package. 2783 (package-menu--perform-transaction
2754 (mapc (lambda (p) (package-install p (and (not (package-installed-p p)) 2784 install-list delete-list package-menu-async))))
2755 (package-installed-p
2756 (package-desc-name p)))))
2757 install-list)
2758 ;; Delete packages.
2759 (dolist (elt (package--sort-by-dependence delete-list))
2760 (condition-case-unless-debug err
2761 (package-delete elt)
2762 (error (message (cadr err)))))
2763 (when package-selected-packages
2764 (let ((removable (package--removable-packages)))
2765 (when (and removable
2766 (y-or-n-p
2767 (format "These %d packages are no longer needed, delete them (%s)? "
2768 (length removable)
2769 (mapconcat #'symbol-name removable ", "))))
2770 ;; We know these are removable, so we can use force instead of sorting them.
2771 (mapc (lambda (p) (package-delete (cadr (assq p package-alist)) 'force 'nosave))
2772 removable)))))
2773 (package-menu--generate t t)))
2774 2785
2775(defun package-menu--version-predicate (A B) 2786(defun package-menu--version-predicate (A B)
2776 (let ((vA (or (aref (cadr A) 1) '(0))) 2787 (let ((vA (or (aref (cadr A) 1) '(0)))
@@ -2843,9 +2854,8 @@ Store this list in `package-menu--new-package-list'."
2843 2854
2844(defun package-menu--post-refresh () 2855(defun package-menu--post-refresh ()
2845 "Check for new packages, revert the *Packages* buffer, and check for upgrades. 2856 "Check for new packages, revert the *Packages* buffer, and check for upgrades.
2846This function is called after `package-refresh-contents' is done. 2857This function is called after `package-refresh-contents' and
2847It goes in `package--post-download-archives-hook', so that it 2858after `package-menu--perform-transaction'."
2848works with async refresh as well."
2849 (package-menu--populate-new-package-list) 2859 (package-menu--populate-new-package-list)
2850 (let ((buf (get-buffer "*Packages*"))) 2860 (let ((buf (get-buffer "*Packages*")))
2851 (when (buffer-live-p buf) 2861 (when (buffer-live-p buf)
@@ -2855,9 +2865,8 @@ works with async refresh as well."
2855 2865
2856(defcustom package-menu-async t 2866(defcustom package-menu-async t
2857 "If non-nil, package-menu will use async operations when possible. 2867 "If non-nil, package-menu will use async operations when possible.
2858Currently, only the refreshing of archive contents supports 2868This includes refreshing archive contents as well as installing
2859asynchronous operations. Package transactions are still done 2869packages."
2860synchronously."
2861 :type 'boolean 2870 :type 'boolean
2862 :group 'package) 2871 :group 'package)
2863 2872