diff options
author | Artur Malabarba <bruce.connor.am@gmail.com> | 2015-04-05 15:43:59 +0100 |
---|---|---|
committer | Artur Malabarba <bruce.connor.am@gmail.com> | 2015-04-06 11:19:04 +0100 |
commit | 7436b68132daa1a941bfbc73a16ce43f5e72a746 (patch) | |
tree | b615074c3cc34930ceb6a6fbb2ffd890c84dba2a /lisp/emacs-lisp/package.el | |
parent | b884ff380dc341ca8dc8fcfe4357110e191216ce (diff) | |
download | emacs-7436b68132daa1a941bfbc73a16ce43f5e72a746.tar.gz emacs-7436b68132daa1a941bfbc73a16ce43f5e72a746.tar.bz2 emacs-7436b68132daa1a941bfbc73a16ce43f5e72a746.zip |
emacs-lisp/package.el: Async support in download-transaction
Diffstat (limited to 'lisp/emacs-lisp/package.el')
-rw-r--r-- | lisp/emacs-lisp/package.el | 93 |
1 files changed, 59 insertions, 34 deletions
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 18802701a0a..2e6ad99d705 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -1658,43 +1658,56 @@ if all the in-between dependencies are also in PACKAGE-LIST." "Return the archive containing the package NAME." (cdr (assoc (package-desc-archive desc) package-archives))) -(defun package-install-from-archive (pkg-desc) - "Download and install a tar package." +(defun package-install-from-archive (pkg-desc &optional async callback) + "Download and install a tar package. +If ASYNC is non-nil, perform the download asynchronously. +If CALLBACK is non-nil, call it with no arguments once the +operation is done." ;; This won't happen, unless the archive is doing something wrong. (when (eq (package-desc-kind pkg-desc) 'dir) (error "Can't install directory package from archive")) (let* ((location (package-archive-base pkg-desc)) (file (concat (package-desc-full-name pkg-desc) - (package-desc-suffix pkg-desc))) - (sig-file (concat file ".sig")) - good-signatures pkg-descs) - (package--with-work-buffer location file - (if (and package-check-signature - (not (member (package-desc-archive pkg-desc) - package-unsigned-archives))) - (if (package--archive-file-exists-p location sig-file) - (setq good-signatures (package--check-signature location file)) - (unless (eq package-check-signature 'allow-unsigned) - (error "Unsigned package: `%s'" - (package-desc-name pkg-desc))))) - (package-unpack pkg-desc)) - ;; Here the package has been installed successfully, mark it as - ;; signed if appropriate. - (when good-signatures - ;; Write out good signatures into NAME-VERSION.signed file. - (write-region (mapconcat #'epg-signature-to-string good-signatures "\n") - nil - (expand-file-name - (concat (package-desc-full-name pkg-desc) - ".signed") - package-user-dir) - nil 'silent) - ;; Update the old pkg-desc which will be shown on the description buffer. - (setf (package-desc-signed pkg-desc) t) - ;; Update the new (activated) pkg-desc as well. - (setq pkg-descs (cdr (assq (package-desc-name pkg-desc) package-alist))) - (if pkg-descs - (setf (package-desc-signed (car pkg-descs)) t))))) + (package-desc-suffix pkg-desc)))) + (package--with-work-buffer-async location file async + (if (or (not package-check-signature) + (member (package-desc-archive pkg-desc) + package-unsigned-archives)) + ;; If we don't care about the signature, unpack and we're + ;; done. + (progn (package-unpack pkg-desc) + (funcall callback)) + ;; If we care, check it and *then* write the file. + (let ((content (buffer-string))) + (package--check-signature + location file content async + ;; This function will be called after signature checking. + (lambda (&optional good-sigs) + (unless (or good-sigs (eq package-check-signature 'allow-unsigned)) + ;; Even if the sig fails, this download is done, so + ;; remove it from the in-progress list. + (error "Unsigned package: `%s'" + (package-desc-name pkg-desc))) + ;; Signature checked, unpack now. + (with-temp-buffer (insert content) + (package-unpack pkg-desc)) + ;; Here the package has been installed successfully, mark it as + ;; signed if appropriate. + (when good-sigs + ;; Write out good signatures into NAME-VERSION.signed file. + (write-region (mapconcat #'epg-signature-to-string good-sigs "\n") + nil + (expand-file-name + (concat (package-desc-full-name pkg-desc) ".signed") + package-user-dir) + nil 'silent) + ;; Update the old pkg-desc which will be shown on the description buffer. + (setf (package-desc-signed pkg-desc) t) + ;; Update the new (activated) pkg-desc as well. + (when-let ((pkg-descs (cdr (assq (package-desc-name pkg-desc) package-alist)))) + (setf (package-desc-signed (car pkg-descs)) t))) + (when (functionp callback) + (funcall callback))))))))) (defun package-installed-p (package &optional min-version) "Return true if PACKAGE, of MIN-VERSION or newer, is installed. @@ -1715,13 +1728,25 @@ If PACKAGE is a package-desc object, MIN-VERSION is ignored." ;; Also check built-in packages. (package-built-in-p package min-version)))) -(defun package-download-transaction (packages) +(defun package-download-transaction (packages &optional async callback) "Download and install all the packages in PACKAGES. PACKAGES should be a list of package-desc. +If ASYNC is non-nil, perform the downloads asynchronously. +If CALLBACK is non-nil, call it with no arguments once the +entire operation is done. + This function assumes that all package requirements in PACKAGES are satisfied, i.e. that PACKAGES is computed using `package-compute-transaction'." - (mapc #'package-install-from-archive packages)) + (cond + (packages (package-install-from-archive + (car packages) + async + (lambda () + (package-download-transaction (cdr packages)) + (when (functionp callback) + (funcall callback))))) + (callback (funcall callback)))) (defun package--ensure-init-file () "Ensure that the user's init file calls `package-initialize'." |