summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/package.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/package.el')
-rw-r--r--lisp/emacs-lisp/package.el177
1 files changed, 102 insertions, 75 deletions
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 2552ad4eb68..5dc2938fe08 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -319,20 +319,39 @@ Like `package-alist', but maps package name to a second alist.
The inner alist is keyed by version.")
(put 'package-obsolete-alist 'risky-local-variable t)
-(defconst package-subdirectory-regexp
- "^\\([^.].*\\)-\\([0-9]+\\(?:[.][0-9]+\\)*\\)$"
- "Regular expression matching the name of a package subdirectory.
-The first subexpression is the package name.
-The second subexpression is the version string.")
-
-(defun package-version-join (l)
- "Turn a list of version numbers into a version string."
- (mapconcat 'int-to-string l "."))
+(defun package-version-join (vlist)
+ "Return the version string corresponding to the list VLIST.
+This is, approximately, the inverse of `version-to-list'.
+\(Actually, it returns only one of the possible inverses, since
+`version-to-list' is a many-to-one operation.)"
+ (if (null vlist)
+ ""
+ (let ((str-list (list "." (int-to-string (car vlist)))))
+ (dolist (num (cdr vlist))
+ (cond
+ ((>= num 0)
+ (push (int-to-string num) str-list)
+ (push "." str-list))
+ ((< num -3)
+ (error "Invalid version list `%s'" vlist))
+ (t
+ ;; pre, or beta, or alpha
+ (cond ((equal "." (car str-list))
+ (pop str-list))
+ ((not (string-match "[0-9]+" (car str-list)))
+ (error "Invalid version list `%s'" vlist)))
+ (push (cond ((= num -1) "pre")
+ ((= num -2) "beta")
+ ((= num -3) "alpha"))
+ str-list))))
+ (if (equal "." (car str-list))
+ (pop str-list))
+ (apply 'concat (nreverse str-list)))))
(defun package-strip-version (dirname)
"Strip the version from a combined package name and version.
E.g., if given \"quux-23.0\", will return \"quux\""
- (if (string-match package-subdirectory-regexp dirname)
+ (if (string-match (concat "\\`" package-subdirectory-regexp "\\'") dirname)
(match-string 1 dirname)))
(defun package-load-descriptor (dir package)
@@ -357,12 +376,13 @@ In each valid package subdirectory, this function loads the
description file containing a call to `define-package', which
updates `package-alist' and `package-obsolete-alist'."
(let ((all (memq 'all package-load-list))
+ (regexp (concat "\\`" package-subdirectory-regexp "\\'"))
name version force)
(dolist (dir (cons package-user-dir package-directory-list))
(when (file-directory-p dir)
(dolist (subdir (directory-files dir))
(when (and (file-directory-p (expand-file-name subdir dir))
- (string-match package-subdirectory-regexp subdir))
+ (string-match regexp subdir))
(setq name (intern (match-string 1 subdir))
version (match-string 2 subdir)
force (assq name package-load-list))
@@ -554,30 +574,29 @@ EXTRA-PROPERTIES is currently unused."
(package-autoload-ensure-default-file generated-autoload-file))
(update-directory-autoloads pkg-dir)))
-(defun package-untar-buffer ()
+(defvar tar-parse-info)
+(declare-function tar-untar-buffer "tar-mode" ())
+
+(defun package-untar-buffer (dir)
"Untar the current buffer.
-This uses `tar-untar-buffer' if it is available.
-Otherwise it uses an external `tar' program.
-`default-directory' should be set by the caller."
+This uses `tar-untar-buffer' from Tar mode. All files should
+untar into a directory named DIR; otherwise, signal an error."
(require 'tar-mode)
- (if (fboundp 'tar-untar-buffer)
- (progn
- ;; tar-mode messes with narrowing, so we just let it have the
- ;; whole buffer to play with.
- (delete-region (point-min) (point))
- (tar-mode)
- (tar-untar-buffer))
- ;; FIXME: check the result.
- (call-process-region (point) (point-max) "tar" nil '(nil nil) nil
- "xf" "-")))
+ (tar-mode)
+ ;; Make sure everything extracts into DIR.
+ (let ((regexp (concat "\\`" (regexp-quote dir) "/")))
+ (dolist (tar-data tar-parse-info)
+ (unless (string-match regexp (aref tar-data 2))
+ (error "Package does not untar cleanly into directory %s/" dir))))
+ (tar-untar-buffer))
(defun package-unpack (name version)
- (let ((pkg-dir (expand-file-name (concat (symbol-name name) "-" version)
- package-user-dir)))
+ (let* ((dirname (concat (symbol-name name) "-" version))
+ (pkg-dir (expand-file-name dirname package-user-dir)))
(make-directory package-user-dir t)
;; FIXME: should we delete PKG-DIR if it exists?
(let* ((default-directory (file-name-as-directory package-user-dir)))
- (package-untar-buffer)
+ (package-untar-buffer dirname)
(package-generate-autoloads (symbol-name name) pkg-dir)
(let ((load-path (cons pkg-dir load-path)))
(byte-recompile-directory pkg-dir 0 t)))))
@@ -592,7 +611,9 @@ Otherwise it uses an external `tar' program.
(if (string= file-name "package")
(package--write-file-no-coding
(expand-file-name (concat file-name ".el") package-user-dir))
- (let* ((pkg-dir (expand-file-name (concat file-name "-" version)
+ (let* ((pkg-dir (expand-file-name (concat file-name "-"
+ (package-version-join
+ (version-to-list version)))
package-user-dir))
(el-file (expand-file-name (concat file-name ".el") pkg-dir))
(pkg-file (expand-file-name (concat file-name "-pkg.el") pkg-dir)))
@@ -848,15 +869,17 @@ The package is found on one of the archives in `package-archives'."
;; Try to activate it.
(package-initialize))
-(defun package-strip-rcs-id (v-str)
- "Strip RCS version ID from the version string.
+(defun package-strip-rcs-id (str)
+ "Strip RCS version ID from the version string STR.
If the result looks like a dotted numeric version, return it.
Otherwise return nil."
- (if v-str
- (if (string-match "^[ \t]*[$]Revision:[ \t]\([0-9.]+\)[ \t]*[$]$" v-str)
- (match-string 1 v-str)
- (if (string-match "^[0-9.]*$" v-str)
- v-str))))
+ (when str
+ (when (string-match "\\`[ \t]*[$]Revision:[ \t]+" str)
+ (setq str (substring str (match-end 0))))
+ (condition-case nil
+ (if (version-to-list str)
+ str)
+ (error nil))))
(defun package-buffer-info ()
"Return a vector describing the package in the current buffer.
@@ -911,43 +934,47 @@ boundaries."
"Find package information for a tar file.
FILE is the name of the tar file to examine.
The return result is a vector like `package-buffer-info'."
- (unless (string-match "^\\(.+\\)-\\([0-9.]+\\)\\.tar$" file)
- (error "Invalid package name `%s'" file))
- (let* ((pkg-name (file-name-nondirectory (match-string-no-properties 1 file)))
- (pkg-version (match-string-no-properties 2 file))
- ;; Extract the package descriptor.
- (pkg-def-contents (shell-command-to-string
- ;; Requires GNU tar.
- (concat "tar -xOf " file " "
- pkg-name "-" pkg-version "/"
- pkg-name "-pkg.el")))
- (pkg-def-parsed (package-read-from-string pkg-def-contents)))
- (unless (eq (car pkg-def-parsed) 'define-package)
- (error "No `define-package' sexp is present in `%s-pkg.el'" pkg-name))
- (let ((name-str (nth 1 pkg-def-parsed))
- (version-string (nth 2 pkg-def-parsed))
- (docstring (nth 3 pkg-def-parsed))
- (requires (nth 4 pkg-def-parsed))
- (readme (shell-command-to-string
- ;; Requires GNU tar.
- (concat "tar -xOf " file " "
- pkg-name "-" pkg-version "/README"))))
- (unless (equal pkg-version version-string)
- (error "Package has inconsistent versions"))
- (unless (equal pkg-name name-str)
- (error "Package has inconsistent names"))
- ;; Kind of a hack.
- (if (string-match ": Not found in archive" readme)
- (setq readme nil))
- ;; Turn string version numbers into list form.
- (if (eq (car requires) 'quote)
- (setq requires (car (cdr requires))))
- (setq requires
- (mapcar (lambda (elt)
- (list (car elt)
- (version-to-list (cadr elt))))
- requires))
- (vector pkg-name requires docstring version-string readme))))
+ (let ((default-directory (file-name-directory file))
+ (file (file-name-nondirectory file)))
+ (unless (string-match (concat "\\`" package-subdirectory-regexp "\\.tar\\'")
+ file)
+ (error "Invalid package name `%s'" file))
+ (let* ((pkg-name (match-string-no-properties 1 file))
+ (pkg-version (match-string-no-properties 2 file))
+ ;; Extract the package descriptor.
+ (pkg-def-contents (shell-command-to-string
+ ;; Requires GNU tar.
+ (concat "tar -xOf " file " "
+
+ pkg-name "-" pkg-version "/"
+ pkg-name "-pkg.el")))
+ (pkg-def-parsed (package-read-from-string pkg-def-contents)))
+ (unless (eq (car pkg-def-parsed) 'define-package)
+ (error "No `define-package' sexp is present in `%s-pkg.el'" pkg-name))
+ (let ((name-str (nth 1 pkg-def-parsed))
+ (version-string (nth 2 pkg-def-parsed))
+ (docstring (nth 3 pkg-def-parsed))
+ (requires (nth 4 pkg-def-parsed))
+ (readme (shell-command-to-string
+ ;; Requires GNU tar.
+ (concat "tar -xOf " file " "
+ pkg-name "-" pkg-version "/README"))))
+ (unless (equal pkg-version version-string)
+ (error "Package has inconsistent versions"))
+ (unless (equal pkg-name name-str)
+ (error "Package has inconsistent names"))
+ ;; Kind of a hack.
+ (if (string-match ": Not found in archive" readme)
+ (setq readme nil))
+ ;; Turn string version numbers into list form.
+ (if (eq (car requires) 'quote)
+ (setq requires (car (cdr requires))))
+ (setq requires
+ (mapcar (lambda (elt)
+ (list (car elt)
+ (version-to-list (cadr elt))))
+ requires))
+ (vector pkg-name requires docstring version-string readme)))))
;;;###autoload
(defun package-install-from-buffer (pkg-info type)
@@ -1037,7 +1064,7 @@ makes them available for download."
(unless (file-exists-p package-user-dir)
(make-directory package-user-dir t))
(dolist (archive package-archives)
- (condition-case nil
+ (condition-case-no-debug nil
(package--download-one-archive archive "archive-contents")
(error (message "Failed to download `%s' archive."
(car archive)))))
@@ -1465,7 +1492,7 @@ packages marked for deletion are removed."
delete-list
", "))))
(dolist (elt delete-list)
- (condition-case err
+ (condition-case-no-debug err
(package-delete (car elt) (cdr elt))
(error (message (cadr err)))))
(error "Aborted")))