aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Malabarba2015-11-14 15:44:44 +0000
committerArtur Malabarba2015-11-14 16:06:01 +0000
commite7f2c91bd112306c96643cd9e57b53527742a8db (patch)
tree6d45d754f8ad52b899b69af3f43d3dacc7f1a56e
parentca947054e25fbc11bf8783166153567dcafdbe6c (diff)
downloademacs-e7f2c91bd112306c96643cd9e57b53527742a8db.tar.gz
emacs-e7f2c91bd112306c96643cd9e57b53527742a8db.zip
Backport: * lisp/emacs-lisp/package.el: Refactor -with-work-buffer-async.
(package--with-work-buffer-async): Reimplement as `package--with-response-buffer'. (package--with-work-buffer): Mark obsolete. (package--with-response-buffer): New macro. This is a more self contained and less contrived version of `package--with-work-buffer-async'. It uses keyword arguments, doesn't have async on the name, doesn't fallback on `package--with-work-buffer', and has _much_ simpler error handling. On master, this macro will soon be part of another library (either standalone or inside url.el), which is why this commit is not to be merged back. (package--check-signature, package--download-one-archive) (package-install-from-archive, describe-package-1): Use it. (package--download-and-read-archives): Let `package--download-one-archive' take care of calling `package--update-downloads-in-progress'.
-rw-r--r--lisp/emacs-lisp/package.el158
1 files changed, 76 insertions, 82 deletions
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 2962da5a917..fba07a6801e 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -1124,7 +1124,8 @@ FILE is the name of a file relative to that base location.
1124This macro retrieves FILE from LOCATION into a temporary buffer, 1124This macro retrieves FILE from LOCATION into a temporary buffer,
1125and evaluates BODY while that buffer is current. This work 1125and evaluates BODY while that buffer is current. This work
1126buffer is killed afterwards. Return the last value in BODY." 1126buffer is killed afterwards. Return the last value in BODY."
1127 (declare (indent 2) (debug t)) 1127 (declare (indent 2) (debug t)
1128 (obsolete package--with-response-buffer "25.1"))
1128 `(with-temp-buffer 1129 `(with-temp-buffer
1129 (if (string-match-p "\\`https?:" ,location) 1130 (if (string-match-p "\\`https?:" ,location)
1130 (url-insert-file-contents (concat ,location ,file)) 1131 (url-insert-file-contents (concat ,location ,file))
@@ -1134,47 +1135,52 @@ buffer is killed afterwards. Return the last value in BODY."
1134 (insert-file-contents (expand-file-name ,file ,location))) 1135 (insert-file-contents (expand-file-name ,file ,location)))
1135 ,@body)) 1136 ,@body))
1136 1137
1137(defmacro package--with-work-buffer-async (location file async &rest body) 1138(cl-defmacro package--with-response-buffer (url &rest body &key async file error-form noerror &allow-other-keys)
1138 "Run BODY in a buffer containing the contents of FILE at LOCATION. 1139 "Access URL and run BODY in a buffer containing the response.
1139If ASYNC is non-nil, and if it is possible, run BODY 1140Point is after the headers when BODY runs.
1140asynchronously. If an error is encountered and ASYNC is a 1141FILE, if provided, is added to URL.
1141function, call it with no arguments (instead of executing BODY). 1142URL can be a local file name, which must be absolute.
1142If it returns non-nil, or if it wasn't a function, propagate the 1143ASYNC, if non-nil, runs the request asynchronously.
1143error. 1144ERROR-FORM is run only if an error occurs. If NOERROR is
1144 1145non-nil, don't propagate errors caused by the connection or by
1145For a description of the other arguments see 1146BODY (does not apply to errors signaled by ERROR-FORM).
1146`package--with-work-buffer'." 1147
1147 (declare (indent 3) (debug t)) 1148\(fn URL &key ASYNC FILE ERROR-FORM NOERROR &rest BODY)"
1148 (macroexp-let2* macroexp-copyable-p 1149 (declare (indent defun) (debug t))
1149 ((async-1 async) 1150 (while (keywordp (car body))
1150 (file-1 file) 1151 (setq body (cdr (cdr body))))
1151 (location-1 location)) 1152 (macroexp-let2* nil ((url-1 url))
1152 `(if (or (not ,async-1) 1153 `(cl-macrolet ((wrap-errors (&rest bodyforms)
1153 (not (string-match-p "\\`https?:" ,location-1))) 1154 (let ((err (make-symbol "err")))
1154 (package--with-work-buffer ,location-1 ,file-1 ,@body) 1155 `(condition-case ,err
1155 ;; This `condition-case' is to catch connection errors. 1156 ,(macroexp-progn bodyforms)
1156 (condition-case error-signal 1157 ,(list 'error ',error-form
1157 (url-retrieve (concat ,location-1 ,file-1) 1158 (list 'unless ',noerror
1158 ;; This is to catch execution errors. 1159 `(signal (car ,err) (cdr ,err))))))))
1159 (lambda (status) 1160 (if (string-match-p "\\`https?:" ,url-1)
1160 (condition-case error-signal 1161 (let* ((url (concat ,url-1 ,file))
1161 (progn 1162 (callback (lambda (status)
1162 (when-let ((er (plist-get status :error))) 1163 (let ((b (current-buffer)))
1163 (error "Error retrieving: %s %S" (concat ,location-1 ,file-1) er)) 1164 (unwind-protect (wrap-errors
1164 (goto-char (point-min)) 1165 (when-let ((er (plist-get status :error)))
1165 (unless (search-forward "\n\n" nil 'noerror) 1166 (error "Error retrieving: %s %S" url er))
1166 (error "Invalid url response in buffer %s" 1167 (unless (search-forward-regexp "^\r?\n\r?" nil 'noerror)
1167 (current-buffer))) 1168 (rest-error 'rest-unintelligible-result))
1168 (delete-region (point-min) (point)) 1169 (delete-region (point-min) (point))
1169 ,@body 1170 ,@body)
1170 (kill-buffer (current-buffer))) 1171 (when (buffer-live-p b)
1171 (error (when (if (functionp ,async-1) (funcall ,async-1) t) 1172 (kill-buffer b)))))))
1172 (signal (car error-signal) (cdr error-signal)))))) 1173 (if ,async
1173 nil 1174 (wrap-errors (url-retrieve url callback nil 'silent))
1174 'silent) 1175 (let ((buffer (wrap-errors (url-retrieve-synchronously url 'silent))))
1175 (error (when (if (functionp ,async-1) (funcall ,async-1) t) 1176 (with-current-buffer buffer
1176 (message "Error contacting: %s" (concat ,location-1 ,file-1)) 1177 (funcall callback nil)))))
1177 (signal (car error-signal) (cdr error-signal)))))))) 1178 (wrap-errors (with-temp-buffer
1179 (let ((url (expand-file-name ,file ,url-1)))
1180 (unless (file-name-absolute-p url)
1181 (error "Location %s is not a url nor an absolute file name" url))
1182 (insert-file-contents url))
1183 ,@body))))))
1178 1184
1179(defun package--check-signature-content (content string &optional sig-file) 1185(defun package--check-signature-content (content string &optional sig-file)
1180 "Check signature CONTENT against STRING. 1186 "Check signature CONTENT against STRING.
@@ -1220,15 +1226,12 @@ list can be empty). If the signatures file is not found,
1220CALLBACK is called with no arguments." 1226CALLBACK is called with no arguments."
1221 (let ((sig-file (concat file ".sig")) 1227 (let ((sig-file (concat file ".sig"))
1222 (string (or string (buffer-string)))) 1228 (string (or string (buffer-string))))
1223 (condition-case nil 1229 (package--with-response-buffer location :file sig-file
1224 (package--with-work-buffer-async 1230 :async async :noerror t
1225 location sig-file (when async (or callback t)) 1231 :error-form (when callback (funcall callback nil))
1226 (let ((sig (package--check-signature-content 1232 (let ((sig (package--check-signature-content (buffer-substring (point) (point-max)) string sig-file)))
1227 (buffer-string) string sig-file))) 1233 (when callback (funcall callback sig))
1228 (when callback (funcall callback sig)) 1234 sig))))
1229 sig))
1230 (file-error (funcall callback)))))
1231
1232 1235
1233;;; Packages on Archives 1236;;; Packages on Archives
1234;; The following variables store information about packages available 1237;; The following variables store information about packages available
@@ -1470,7 +1473,9 @@ Once it's empty, run `package--post-download-archives-hook'."
1470ARCHIVE should be a cons cell of the form (NAME . LOCATION), 1473ARCHIVE should be a cons cell of the form (NAME . LOCATION),
1471similar to an entry in `package-alist'. Save the cached copy to 1474similar to an entry in `package-alist'. Save the cached copy to
1472\"archives/NAME/FILE\" in `package-user-dir'." 1475\"archives/NAME/FILE\" in `package-user-dir'."
1473 (package--with-work-buffer-async (cdr archive) file async 1476 (package--with-response-buffer (cdr archive) :file file
1477 :async async
1478 :error-form (package--update-downloads-in-progress archive)
1474 (let* ((location (cdr archive)) 1479 (let* ((location (cdr archive))
1475 (name (car archive)) 1480 (name (car archive))
1476 (content (buffer-string)) 1481 (content (buffer-string))
@@ -1494,17 +1499,14 @@ similar to an entry in `package-alist'. Save the cached copy to
1494 ;; remove it from the in-progress list. 1499 ;; remove it from the in-progress list.
1495 (package--update-downloads-in-progress archive) 1500 (package--update-downloads-in-progress archive)
1496 (error "Unsigned archive `%s'" name)) 1501 (error "Unsigned archive `%s'" name))
1502 ;; Either everything worked or we don't mind not signing.
1497 ;; Write out the archives file. 1503 ;; Write out the archives file.
1498 (write-region content nil local-file nil 'silent) 1504 (write-region content nil local-file nil 'silent)
1499 ;; Write out good signatures into archive-contents.signed file. 1505 ;; Write out good signatures into archive-contents.signed file.
1500 (when good-sigs 1506 (when good-sigs
1501 (write-region (mapconcat #'epg-signature-to-string good-sigs "\n") 1507 (write-region (mapconcat #'epg-signature-to-string good-sigs "\n")
1502 nil (concat local-file ".signed") nil 'silent)) 1508 nil (concat local-file ".signed") nil 'silent))
1503 (package--update-downloads-in-progress archive) 1509 (package--update-downloads-in-progress archive))))))))
1504 ;; If we got this far, either everything worked or we don't mind
1505 ;; not signing, so tell `package--with-work-buffer-async' to not
1506 ;; propagate errors.
1507 nil)))))))
1508 1510
1509(defun package--download-and-read-archives (&optional async) 1511(defun package--download-and-read-archives (&optional async)
1510 "Download descriptions of all `package-archives' and read them. 1512 "Download descriptions of all `package-archives' and read them.
@@ -1517,12 +1519,7 @@ perform the downloads asynchronously."
1517 :test #'equal)) 1519 :test #'equal))
1518 (dolist (archive package-archives) 1520 (dolist (archive package-archives)
1519 (condition-case-unless-debug nil 1521 (condition-case-unless-debug nil
1520 (package--download-one-archive 1522 (package--download-one-archive archive "archive-contents" async)
1521 archive "archive-contents"
1522 ;; Called if the async download fails
1523 (when async
1524 ;; The t at the end means to propagate connection errors.
1525 (lambda () (package--update-downloads-in-progress archive) t)))
1526 (error (message "Failed to download `%s' archive." 1523 (error (message "Failed to download `%s' archive."
1527 (car archive)))))) 1524 (car archive))))))
1528 1525
@@ -1777,7 +1774,7 @@ if all the in-between dependencies are also in PACKAGE-LIST."
1777 (let* ((location (package-archive-base pkg-desc)) 1774 (let* ((location (package-archive-base pkg-desc))
1778 (file (concat (package-desc-full-name pkg-desc) 1775 (file (concat (package-desc-full-name pkg-desc)
1779 (package-desc-suffix pkg-desc)))) 1776 (package-desc-suffix pkg-desc))))
1780 (package--with-work-buffer location file 1777 (package--with-response-buffer location :file file
1781 (if (or (not package-check-signature) 1778 (if (or (not package-check-signature)
1782 (member (package-desc-archive pkg-desc) 1779 (member (package-desc-archive pkg-desc)
1783 package-unsigned-archives)) 1780 package-unsigned-archives))
@@ -2368,26 +2365,23 @@ Otherwise no newline is inserted."
2368 (replace-match "")) 2365 (replace-match ""))
2369 (while (re-search-forward "^\\(;+ ?\\)" nil t) 2366 (while (re-search-forward "^\\(;+ ?\\)" nil t)
2370 (replace-match "")))) 2367 (replace-match ""))))
2371 (let ((readme (expand-file-name (format "%s-readme.txt" name) 2368 (let* ((basename (format "%s-readme.txt" name))
2372 package-user-dir)) 2369 (readme (expand-file-name basename package-user-dir))
2373 readme-string) 2370 readme-string)
2374 ;; For elpa packages, try downloading the commentary. If that 2371 ;; For elpa packages, try downloading the commentary. If that
2375 ;; fails, try an existing readme file in `package-user-dir'. 2372 ;; fails, try an existing readme file in `package-user-dir'.
2376 (cond ((condition-case nil 2373 (cond ((and (package-desc-archive desc)
2377 (save-excursion 2374 (package--with-response-buffer (package-archive-base desc)
2378 (package--with-work-buffer 2375 :file basename :noerror t
2379 (package-archive-base desc) 2376 (save-excursion
2380 (format "%s-readme.txt" name) 2377 (goto-char (point-max))
2381 (save-excursion 2378 (unless (bolp)
2382 (goto-char (point-max)) 2379 (insert ?\n)))
2383 (unless (bolp) 2380 (write-region nil nil
2384 (insert ?\n))) 2381 (expand-file-name readme package-user-dir)
2385 (write-region nil nil 2382 nil 'silent)
2386 (expand-file-name readme package-user-dir) 2383 (setq readme-string (buffer-string))
2387 nil 'silent) 2384 t))
2388 (setq readme-string (buffer-string))
2389 t))
2390 (error nil))
2391 (insert readme-string)) 2385 (insert readme-string))
2392 ((file-readable-p readme) 2386 ((file-readable-p readme)
2393 (insert-file-contents readme) 2387 (insert-file-contents readme)