aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChong Yidong2011-03-05 22:22:06 -0500
committerChong Yidong2011-03-05 22:22:06 -0500
commitf561e49a25cace5e6d3cf3b222d87fa483226f76 (patch)
treedac80a926beb01ee9465369e617944640cfdd79e
parentad7d6ecb162a8154cc865a4c3514f5753208c3d1 (diff)
downloademacs-f561e49a25cace5e6d3cf3b222d87fa483226f76.tar.gz
emacs-f561e49a25cace5e6d3cf3b222d87fa483226f76.zip
Allow specifying local ELPA mirrors in package-archives.
* emacs-lisp/package.el (package-archives): Accept either ordinary directory names, in addition to HTTP URLs. (package--with-work-buffer): New macro. Handle normal directories. (package-handle-response): Don't display the failing buffer. (package-download-single, package-download-tar) (package--download-one-archive): Use package--with-work-buffer. (package-archive-base): Rename from package-archive-url.
-rw-r--r--lisp/ChangeLog10
-rw-r--r--lisp/emacs-lisp/package.el124
2 files changed, 77 insertions, 57 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index a3646cc5a47..380d12443da 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,13 @@
12011-03-06 Chong Yidong <cyd@stupidchicken.com>
2
3 * emacs-lisp/package.el (package-archives): Accept either ordinary
4 directory names, in addition to HTTP URLs.
5 (package--with-work-buffer): New macro. Handle normal directories.
6 (package-handle-response): Don't display the failing buffer.
7 (package-download-single, package-download-tar)
8 (package--download-one-archive): Use package--with-work-buffer.
9 (package-archive-base): Rename from package-archive-url.
10
12011-03-06 Glenn Morris <rgm@gnu.org> 112011-03-06 Glenn Morris <rgm@gnu.org>
2 12
3 * generic-x.el (generic-unix-modes): Add xmodmap-generic-mode. 13 * generic-x.el (generic-unix-modes): Add xmodmap-generic-mode.
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index ab5ba1bea56..2552ad4eb68 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -220,10 +220,15 @@ If VERSION is nil, the package is not loaded (it is \"disabled\")."
220(defcustom package-archives '(("gnu" . "http://elpa.gnu.org/packages/")) 220(defcustom package-archives '(("gnu" . "http://elpa.gnu.org/packages/"))
221 "An alist of archives from which to fetch. 221 "An alist of archives from which to fetch.
222The default value points to the GNU Emacs package repository. 222The default value points to the GNU Emacs package repository.
223Each element has the form (ID . URL), where ID is an identifier 223
224string for an archive and URL is a http: URL (a string)." 224Each element has the form (ID . LOCATION).
225 ID is an archive name, as a string.
226 LOCATION specifies the base location for the archive.
227 If it starts with \"http:\", it is treated as a HTTP URL;
228 otherwise it should be an absolute directory name.
229 (Other types of URL are currently not supported.)"
225 :type '(alist :key-type (string :tag "Archive name") 230 :type '(alist :key-type (string :tag "Archive name")
226 :value-type (string :tag "Archive URL")) 231 :value-type (string :tag "URL or directory name"))
227 :risky t 232 :risky t
228 :group 'package 233 :group 'package
229 :version "24.1") 234 :version "24.1")
@@ -617,8 +622,36 @@ Otherwise it uses an external `tar' program.
617 (let ((load-path (cons pkg-dir load-path))) 622 (let ((load-path (cons pkg-dir load-path)))
618 (byte-recompile-directory pkg-dir 0 t))))) 623 (byte-recompile-directory pkg-dir 0 t)))))
619 624
625(defmacro package--with-work-buffer (location file &rest body)
626 "Run BODY in a buffer containing the contents of FILE at LOCATION.
627LOCATION is the base location of a package archive, and should be
628one of the URLs (or file names) specified in `package-archives'.
629FILE is the name of a file relative to that base location.
630
631This macro retrieves FILE from LOCATION into a temporary buffer,
632and evaluates BODY while that buffer is current. This work
633buffer is killed afterwards. Return the last value in BODY."
634 `(let* ((http (string-match "\\`http:" ,location))
635 (buffer
636 (if http
637 (url-retrieve-synchronously (concat ,location ,file))
638 (generate-new-buffer "*package work buffer*"))))
639 (prog1
640 (with-current-buffer buffer
641 (if http
642 (progn (package-handle-response)
643 (re-search-forward "^$" nil 'move)
644 (forward-char)
645 (delete-region (point-min) (point)))
646 (unless (file-name-absolute-p ,location)
647 (error "Archive location %s is not an absolute file name"
648 ,location))
649 (insert-file-contents (expand-file-name ,file ,location)))
650 ,@body)
651 (kill-buffer buffer))))
652
620(defun package-handle-response () 653(defun package-handle-response ()
621 "Handle the response from the server. 654 "Handle the response from a `url-retrieve-synchronously' call.
622Parse the HTTP response and throw if an error occurred. 655Parse the HTTP response and throw if an error occurred.
623The url package seems to require extra processing for this. 656The url package seems to require extra processing for this.
624This should be called in a `save-excursion', in the download buffer. 657This should be called in a `save-excursion', in the download buffer.
@@ -627,7 +660,6 @@ It will move point to somewhere in the headers."
627 (require 'url-http) 660 (require 'url-http)
628 (let ((response (url-http-parse-response))) 661 (let ((response (url-http-parse-response)))
629 (when (or (< response 200) (>= response 300)) 662 (when (or (< response 200) (>= response 300))
630 (display-buffer (current-buffer))
631 (error "Error during download request:%s" 663 (error "Error during download request:%s"
632 (buffer-substring-no-properties (point) (progn 664 (buffer-substring-no-properties (point) (progn
633 (end-of-line) 665 (end-of-line)
@@ -635,28 +667,17 @@ It will move point to somewhere in the headers."
635 667
636(defun package-download-single (name version desc requires) 668(defun package-download-single (name version desc requires)
637 "Download and install a single-file package." 669 "Download and install a single-file package."
638 (let ((buffer (url-retrieve-synchronously 670 (let ((location (package-archive-base name))
639 (concat (package-archive-url name) 671 (file (concat (symbol-name name) "-" version ".el")))
640 (symbol-name name) "-" version ".el")))) 672 (package--with-work-buffer location file
641 (with-current-buffer buffer 673 (package-unpack-single (symbol-name name) version desc requires))))
642 (package-handle-response)
643 (re-search-forward "^$" nil 'move)
644 (forward-char)
645 (delete-region (point-min) (point))
646 (package-unpack-single (symbol-name name) version desc requires)
647 (kill-buffer buffer))))
648 674
649(defun package-download-tar (name version) 675(defun package-download-tar (name version)
650 "Download and install a tar package." 676 "Download and install a tar package."
651 (let ((tar-buffer (url-retrieve-synchronously 677 (let ((location (package-archive-base name))
652 (concat (package-archive-url name) 678 (file (concat (symbol-name name) "-" version ".tar")))
653 (symbol-name name) "-" version ".tar")))) 679 (package--with-work-buffer location file
654 (with-current-buffer tar-buffer 680 (package-unpack name version))))
655 (package-handle-response)
656 (re-search-forward "^$" nil 'move)
657 (forward-char)
658 (package-unpack name version)
659 (kill-buffer tar-buffer))))
660 681
661(defun package-installed-p (package &optional min-version) 682(defun package-installed-p (package &optional min-version)
662 "Return true if PACKAGE, of VERSION or newer, is installed. 683 "Return true if PACKAGE, of VERSION or newer, is installed.
@@ -987,31 +1008,26 @@ The file can either be a tar file or an Emacs Lisp file."
987 (error "Package `%s-%s' is a system package, not deleting" 1008 (error "Package `%s-%s' is a system package, not deleting"
988 name version)))) 1009 name version))))
989 1010
990(defun package-archive-url (name) 1011(defun package-archive-base (name)
991 "Return the archive containing the package NAME." 1012 "Return the archive containing the package NAME."
992 (let ((desc (cdr (assq (intern-soft name) package-archive-contents)))) 1013 (let ((desc (cdr (assq (intern-soft name) package-archive-contents))))
993 (cdr (assoc (aref desc (- (length desc) 1)) package-archives)))) 1014 (cdr (assoc (aref desc (- (length desc) 1)) package-archives))))
994 1015
995(defun package--download-one-archive (archive file) 1016(defun package--download-one-archive (archive file)
996 "Download an archive file FILE from ARCHIVE, and cache it locally." 1017 "Retrieve an archive file FILE from ARCHIVE, and cache it.
997 (let* ((archive-name (car archive)) 1018ARCHIVE should be a cons cell of the form (NAME . LOCATION),
998 (archive-url (cdr archive)) 1019similar to an entry in `package-alist'. Save the cached copy to
999 (dir (expand-file-name "archives" package-user-dir)) 1020\"archives/NAME/archive-contents\" in `package-user-dir'."
1000 (dir (expand-file-name archive-name dir)) 1021 (let* ((dir (expand-file-name "archives" package-user-dir))
1001 (buffer (url-retrieve-synchronously (concat archive-url file)))) 1022 (dir (expand-file-name (car archive) dir)))
1002 (with-current-buffer buffer 1023 (package--with-work-buffer (cdr archive) file
1003 (package-handle-response)
1004 (re-search-forward "^$" nil 'move)
1005 (forward-char)
1006 (delete-region (point-min) (point))
1007 ;; Read the retrieved buffer to make sure it is valid (e.g. it 1024 ;; Read the retrieved buffer to make sure it is valid (e.g. it
1008 ;; may fetch a URL redirect page). 1025 ;; may fetch a URL redirect page).
1009 (when (listp (read buffer)) 1026 (when (listp (read buffer))
1010 (make-directory dir t) 1027 (make-directory dir t)
1011 (setq buffer-file-name (expand-file-name file dir)) 1028 (setq buffer-file-name (expand-file-name file dir))
1012 (let ((version-control 'never)) 1029 (let ((version-control 'never))
1013 (save-buffer)))) 1030 (save-buffer))))))
1014 (kill-buffer buffer)))
1015 1031
1016(defun package-refresh-contents () 1032(defun package-refresh-contents ()
1017 "Download the ELPA archive description if needed. 1033 "Download the ELPA archive description if needed.
@@ -1176,27 +1192,21 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages."
1176 (while (re-search-forward "^\\(;+ ?\\)" nil t) 1192 (while (re-search-forward "^\\(;+ ?\\)" nil t)
1177 (replace-match "")))) 1193 (replace-match ""))))
1178 (let ((readme (expand-file-name (concat package-name "-readme.txt") 1194 (let ((readme (expand-file-name (concat package-name "-readme.txt")
1179 package-user-dir))) 1195 package-user-dir))
1196 readme-string)
1180 ;; For elpa packages, try downloading the commentary. If that 1197 ;; For elpa packages, try downloading the commentary. If that
1181 ;; fails, try an existing readme file in `package-user-dir'. 1198 ;; fails, try an existing readme file in `package-user-dir'.
1182 (cond ((let ((buffer (ignore-errors 1199 (cond ((condition-case nil
1183 (url-retrieve-synchronously 1200 (package--with-work-buffer (package-archive-base package)
1184 (concat (package-archive-url package) 1201 (concat package-name "-readme.txt")
1185 package-name "-readme.txt")))) 1202 (setq buffer-file-name
1186 response) 1203 (expand-file-name readme package-user-dir))
1187 (when buffer 1204 (let ((version-control 'never))
1188 (with-current-buffer buffer 1205 (save-buffer))
1189 (setq response (url-http-parse-response)) 1206 (setq readme-string (buffer-string))
1190 (if (or (< response 200) (>= response 300)) 1207 t)
1191 (setq response nil) 1208 (error nil))
1192 (setq buffer-file-name 1209 (insert readme-string))
1193 (expand-file-name readme package-user-dir))
1194 (delete-region (point-min) (1+ url-http-end-of-headers))
1195 (save-buffer)))
1196 (when response
1197 (insert-buffer-substring buffer)
1198 (kill-buffer buffer)
1199 t))))
1200 ((file-readable-p readme) 1210 ((file-readable-p readme)
1201 (insert-file-contents readme) 1211 (insert-file-contents readme)
1202 (goto-char (point-max)))))))) 1212 (goto-char (point-max))))))))