diff options
| -rw-r--r-- | lisp/emacs-lisp/package.el | 158 |
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. | |||
| 1124 | This macro retrieves FILE from LOCATION into a temporary buffer, | 1124 | This macro retrieves FILE from LOCATION into a temporary buffer, |
| 1125 | and evaluates BODY while that buffer is current. This work | 1125 | and evaluates BODY while that buffer is current. This work |
| 1126 | buffer is killed afterwards. Return the last value in BODY." | 1126 | buffer 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. |
| 1139 | If ASYNC is non-nil, and if it is possible, run BODY | 1140 | Point is after the headers when BODY runs. |
| 1140 | asynchronously. If an error is encountered and ASYNC is a | 1141 | FILE, if provided, is added to URL. |
| 1141 | function, call it with no arguments (instead of executing BODY). | 1142 | URL can be a local file name, which must be absolute. |
| 1142 | If it returns non-nil, or if it wasn't a function, propagate the | 1143 | ASYNC, if non-nil, runs the request asynchronously. |
| 1143 | error. | 1144 | ERROR-FORM is run only if an error occurs. If NOERROR is |
| 1144 | 1145 | non-nil, don't propagate errors caused by the connection or by | |
| 1145 | For a description of the other arguments see | 1146 | BODY (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, | |||
| 1220 | CALLBACK is called with no arguments." | 1226 | CALLBACK 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'." | |||
| 1470 | ARCHIVE should be a cons cell of the form (NAME . LOCATION), | 1473 | ARCHIVE should be a cons cell of the form (NAME . LOCATION), |
| 1471 | similar to an entry in `package-alist'. Save the cached copy to | 1474 | similar 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) |