aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2013-06-13 23:20:18 -0400
committerStefan Monnier2013-06-13 23:20:18 -0400
commit1b8dff239bf8091a75572064ff8fb085f3c073d6 (patch)
treed3f518d514fef3fc8eb54e36cccd25c083d32bd1
parent0b31660d3c10a0f8e243dd67bd0ecaf2c847d1e6 (diff)
downloademacs-1b8dff239bf8091a75572064ff8fb085f3c073d6.tar.gz
emacs-1b8dff239bf8091a75572064ff8fb085f3c073d6.zip
* lisp/emacs-lisp/package.el: Don't recompute dir. Use pkg-descs more.
(package-desc): Add `dir' field. (package-desc-full-name): New function. (package-load-descriptor): Combine the two arguments. Don't use `load'. (package-maybe-load-descriptor): Remove. (package-load-all-descriptors): Just call package-load-descriptor. (package--disabled-p): New function. (package-desc-vers, package-desc-doc): Remove aliases. (package--dir): Remove function. (package-activate): Check if a package is disabled. (package-process-define-package): New function, extracted from define-package. (define-package): Turn into a place holder. (package-unpack-single, package-tar-file-info): Use package--description-file. (package-compute-transaction): Use package--disabled-p. (package-download-transaction): Don't call package-maybe-load-descriptor since they're all loaded anyway. (package-install): Change argument to be a pkg-desc. (package-delete): Use a single pkg-desc argument. (describe-package-1): Use package-desc-dir instead of package--dir. Use package-desc property instead of package-symbol. (package-install-button-action): Adjust accordingly. (package--push): Rewrite. (package-menu--print-info): Adjust accordingly. Change the ID format to be a pkg-desc. (package-menu-describe-package, package-menu-get-status) (package-menu--find-upgrades, package-menu-mark-upgrades) (package-menu-execute, package-menu--name-predicate): Adjust accordingly. * lisp/startup.el (package--description-file): New function. (command-line): Use it. * lisp/emacs-lisp/package-x.el (package-upload-buffer-internal): Use package-desc-version.
-rw-r--r--lisp/ChangeLog35
-rw-r--r--lisp/emacs-lisp/package-x.el2
-rw-r--r--lisp/emacs-lisp/package.el417
-rw-r--r--lisp/startup.el15
4 files changed, 243 insertions, 226 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 875a361f57b..67e361cc320 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,40 @@
12013-06-14 Stefan Monnier <monnier@iro.umontreal.ca> 12013-06-14 Stefan Monnier <monnier@iro.umontreal.ca>
2 2
3 * emacs-lisp/package.el: Don't recompute dir. Use pkg-descs more.
4 (package-desc): Add `dir' field.
5 (package-desc-full-name): New function.
6 (package-load-descriptor): Combine the two arguments. Don't use `load'.
7 (package-maybe-load-descriptor): Remove.
8 (package-load-all-descriptors): Just call package-load-descriptor.
9 (package--disabled-p): New function.
10 (package-desc-vers, package-desc-doc): Remove aliases.
11 (package--dir): Remove function.
12 (package-activate): Check if a package is disabled.
13 (package-process-define-package): New function, extracted from
14 define-package.
15 (define-package): Turn into a place holder.
16 (package-unpack-single, package-tar-file-info):
17 Use package--description-file.
18 (package-compute-transaction): Use package--disabled-p.
19 (package-download-transaction): Don't call
20 package-maybe-load-descriptor since they're all loaded anyway.
21 (package-install): Change argument to be a pkg-desc.
22 (package-delete): Use a single pkg-desc argument.
23 (describe-package-1): Use package-desc-dir instead of package--dir.
24 Use package-desc property instead of package-symbol.
25 (package-install-button-action): Adjust accordingly.
26 (package--push): Rewrite.
27 (package-menu--print-info): Adjust accordingly. Change the ID format
28 to be a pkg-desc.
29 (package-menu-describe-package, package-menu-get-status)
30 (package-menu--find-upgrades, package-menu-mark-upgrades)
31 (package-menu-execute, package-menu--name-predicate):
32 Adjust accordingly.
33 * startup.el (package--description-file): New function.
34 (command-line): Use it.
35 * emacs-lisp/package-x.el (package-upload-buffer-internal):
36 Use package-desc-version.
37
3 * emacs-lisp/bytecomp.el (byte-compile-force-lexical-warnings): New var. 38 * emacs-lisp/bytecomp.el (byte-compile-force-lexical-warnings): New var.
4 (byte-compile-preprocess): Use it. 39 (byte-compile-preprocess): Use it.
5 (byte-compile-file-form-defalias): Try a bit harder to use macros we 40 (byte-compile-file-form-defalias): Try a bit harder to use macros we
diff --git a/lisp/emacs-lisp/package-x.el b/lisp/emacs-lisp/package-x.el
index 17919d9bbeb..3300e89ec1e 100644
--- a/lisp/emacs-lisp/package-x.el
+++ b/lisp/emacs-lisp/package-x.el
@@ -224,7 +224,7 @@ if it exists."
224 (let ((elt (assq pkg-name (cdr contents)))) 224 (let ((elt (assq pkg-name (cdr contents))))
225 (if elt 225 (if elt
226 (if (version-list-<= split-version 226 (if (version-list-<= split-version
227 (package-desc-vers (cdr elt))) 227 (package-desc-version (cdr elt)))
228 (error "New package has smaller version: %s" pkg-version) 228 (error "New package has smaller version: %s" pkg-version)
229 (setcdr elt new-desc)) 229 (setcdr elt new-desc))
230 (setq contents (cons (car contents) 230 (setq contents (cons (car contents)
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index d5176abded0..6d34c229733 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -336,13 +336,22 @@ required version.
336either `single' or `tar'. 336either `single' or `tar'.
337 337
338`archive' The name of the archive (as a string) whence this 338`archive' The name of the archive (as a string) whence this
339package came." 339package came.
340
341`dir' The directory where the package is installed (if installed)."
340 name 342 name
341 version 343 version
342 (summary package--default-summary) 344 (summary package--default-summary)
343 reqs 345 reqs
344 kind 346 kind
345 archive) 347 archive
348 dir)
349
350;; Pseudo fields.
351(defsubst package-desc-full-name (pkg-desc)
352 (format "%s-%s"
353 (package-desc-name pkg-desc)
354 (package-version-join (package-desc-version pkg-desc))))
346 355
347;; Package descriptor format used in finder-inf.el and package--builtins. 356;; Package descriptor format used in finder-inf.el and package--builtins.
348(cl-defstruct (package--bi-desc 357(cl-defstruct (package--bi-desc
@@ -422,17 +431,18 @@ E.g., if given \"quux-23.0\", will return \"quux\""
422 (if (string-match (concat "\\`" package-subdirectory-regexp "\\'") dirname) 431 (if (string-match (concat "\\`" package-subdirectory-regexp "\\'") dirname)
423 (match-string 1 dirname))) 432 (match-string 1 dirname)))
424 433
425(defun package-load-descriptor (dir package) 434(defun package-load-descriptor (pkg-dir)
426 "Load the description file in directory DIR for package PACKAGE. 435 "Load the description file in directory PKG-DIR."
427Here, PACKAGE is a string of the form NAME-VERSION, where NAME is 436 (let ((pkg-file (expand-file-name (package--description-file pkg-dir)
428the package name and VERSION is its version." 437 pkg-dir)))
429 (let* ((pkg-dir (expand-file-name package dir)) 438 (when (file-exists-p pkg-file)
430 (pkg-file (expand-file-name 439 (with-temp-buffer
431 (concat (package-strip-version package) "-pkg") 440 (insert-file-contents pkg-file)
432 pkg-dir))) 441 (emacs-lisp-mode)
433 (when (and (file-directory-p pkg-dir) 442 (goto-char (point-min))
434 (file-exists-p (concat pkg-file ".el"))) 443 (let ((pkg-desc (package-process-define-package
435 (load pkg-file nil t)))) 444 (read (current-buffer)) pkg-file)))
445 (setf (package-desc-dir pkg-desc) pkg-dir))))))
436 446
437(defun package-load-all-descriptors () 447(defun package-load-all-descriptors ()
438 "Load descriptors for installed Emacs Lisp packages. 448 "Load descriptors for installed Emacs Lisp packages.
@@ -443,65 +453,34 @@ controls which package subdirectories may be loaded.
443In each valid package subdirectory, this function loads the 453In each valid package subdirectory, this function loads the
444description file containing a call to `define-package', which 454description file containing a call to `define-package', which
445updates `package-alist' and `package-obsolete-alist'." 455updates `package-alist' and `package-obsolete-alist'."
446 (let ((regexp (concat "\\`" package-subdirectory-regexp "\\'"))) 456 (dolist (dir (cons package-user-dir package-directory-list))
447 (dolist (dir (cons package-user-dir package-directory-list)) 457 (when (file-directory-p dir)
448 (when (file-directory-p dir) 458 (dolist (subdir (directory-files dir))
449 (dolist (subdir (directory-files dir)) 459 (let ((pkg-dir (expand-file-name subdir dir)))
450 (when (string-match regexp subdir) 460 (when (file-directory-p pkg-dir)
451 (package-maybe-load-descriptor (match-string 1 subdir) 461 (package-load-descriptor pkg-dir)))))))
452 (match-string 2 subdir) 462
453 dir))))))) 463(defun package-disabled-p (pkg-name version)
454 464 "Return whether PKG-NAME at VERSION can be activated.
455(defun package-maybe-load-descriptor (name version dir) 465The decision is made according to `package-load-list'.
456 "Maybe load a specific package from directory DIR. 466Return nil if the package can be activated.
457NAME and VERSION are the package's name and version strings. 467Return t if the package is completely disabled.
458This function checks `package-load-list', before actually loading 468Return the max version (as a string) if the package is held at a lower version."
459the package by calling `package-load-descriptor'." 469 (let ((force (assq pkg-name package-load-list)))
460 (let ((force (assq (intern name) package-load-list)) 470 (cond ((null force) (not (memq 'all package-load-list)))
461 (subdir (concat name "-" version))) 471 ((null (setq force (cadr force))) t) ; disabled
462 (and (file-directory-p (expand-file-name subdir dir)) 472 ((eq force t) nil)
463 ;; Check `package-load-list': 473 ((stringp force) ; held
464 (cond ((null force) 474 (unless (version-list-= version (version-to-list force))
465 (memq 'all package-load-list)) 475 force))
466 ((null (setq force (cadr force))) 476 (t (error "Invalid element in `package-load-list'")))))
467 nil) ; disabled
468 ((eq force t)
469 t)
470 ((stringp force) ; held
471 (version-list-= (version-to-list version)
472 (version-to-list force)))
473 (t
474 (error "Invalid element in `package-load-list'")))
475 ;; Actually load the descriptor:
476 (package-load-descriptor dir subdir))))
477
478(define-obsolete-function-alias 'package-desc-vers 'package-desc-version "24.4")
479
480(define-obsolete-function-alias 'package-desc-doc 'package-desc-summary "24.4")
481
482
483(defun package--dir (name version)
484 ;; FIXME: Keep this as a field in the package-desc.
485 "Return the directory where a package is installed, or nil if none.
486NAME is a symbol and VERSION is a string."
487 (let* ((subdir (format "%s-%s" name version))
488 (dir-list (cons package-user-dir package-directory-list))
489 pkg-dir)
490 (while dir-list
491 (let ((subdir-full (expand-file-name subdir (car dir-list))))
492 (if (file-directory-p subdir-full)
493 (setq pkg-dir subdir-full
494 dir-list nil)
495 (setq dir-list (cdr dir-list)))))
496 pkg-dir))
497 477
498(defun package-activate-1 (pkg-desc) 478(defun package-activate-1 (pkg-desc)
499 (let* ((name (package-desc-name pkg-desc)) 479 (let* ((name (package-desc-name pkg-desc))
500 (version-str (package-version-join (package-desc-version pkg-desc))) 480 (pkg-dir (package-desc-dir pkg-desc)))
501 (pkg-dir (package--dir name version-str)))
502 (unless pkg-dir 481 (unless pkg-dir
503 (error "Internal error: unable to find directory for `%s-%s'" 482 (error "Internal error: unable to find directory for `%s'"
504 name version-str)) 483 (package-desc-full-name pkg-desc)))
505 ;; Add info node. 484 ;; Add info node.
506 (when (file-exists-p (expand-file-name "dir" pkg-dir)) 485 (when (file-exists-p (expand-file-name "dir" pkg-dir))
507 ;; FIXME: not the friendliest, but simple. 486 ;; FIXME: not the friendliest, but simple.
@@ -553,6 +532,8 @@ Return nil if the package could not be activated."
553 ;; If the package is already activated, just return t. 532 ;; If the package is already activated, just return t.
554 ((memq package package-activated-list) 533 ((memq package package-activated-list)
555 t) 534 t)
535 ;; If it's disabled, then just skip it.
536 ((package-disabled-p package available-version) nil)
556 ;; Otherwise, proceed with activation. 537 ;; Otherwise, proceed with activation.
557 (t 538 (t
558 (let ((fail (catch 'dep-failure 539 (let ((fail (catch 'dep-failure
@@ -593,29 +574,32 @@ REQUIREMENTS is a list of dependencies on other packages.
593 where OTHER-VERSION is a string. 574 where OTHER-VERSION is a string.
594 575
595EXTRA-PROPERTIES is currently unused." 576EXTRA-PROPERTIES is currently unused."
596 (let* ((name (intern name-string)) 577 ;; FIXME: Placeholder! Should we keep it?
597 (version (version-to-list version-string)) 578 (error "Don't call me!"))
598 (new-pkg-desc (cons name 579
599 (package-desc-from-define name-string 580(defun package-process-define-package (exp origin)
600 version-string 581 (unless (eq (car-safe exp) 'define-package)
601 docstring 582 (error "Can't find define-package in %s" origin))
602 requirements))) 583 (let* ((new-pkg-desc (apply #'package-desc-from-define (cdr exp)))
603 (old-pkg (assq name package-alist))) 584 (name (package-desc-name new-pkg-desc))
585 (version (package-desc-version new-pkg-desc))
586 (old-pkg (assq name package-alist)))
604 (cond 587 (cond
605 ;; If there's no old package, just add this to `package-alist'. 588 ;; If there's no old package, just add this to `package-alist'.
606 ((null old-pkg) 589 ((null old-pkg)
607 (push new-pkg-desc package-alist)) 590 (push (cons name new-pkg-desc) package-alist))
608 ((version-list-< (package-desc-version (cdr old-pkg)) version) 591 ((version-list-< (package-desc-version (cdr old-pkg)) version)
609 ;; Remove the old package and declare it obsolete. 592 ;; Remove the old package and declare it obsolete.
610 (package-mark-obsolete name (cdr old-pkg)) 593 (package-mark-obsolete name (cdr old-pkg))
611 (setq package-alist (cons new-pkg-desc 594 (setq package-alist (cons (cons name new-pkg-desc)
612 (delq old-pkg package-alist)))) 595 (delq old-pkg package-alist))))
613 ;; You can have two packages with the same version, e.g. one in 596 ;; You can have two packages with the same version, e.g. one in
614 ;; the system package directory and one in your private 597 ;; the system package directory and one in your private
615 ;; directory. We just let the first one win. 598 ;; directory. We just let the first one win.
616 ((not (version-list-= (package-desc-version (cdr old-pkg)) version)) 599 ((not (version-list-= (package-desc-version (cdr old-pkg)) version))
617 ;; The package is born obsolete. 600 ;; The package is born obsolete.
618 (package-mark-obsolete name (cdr new-pkg-desc)))))) 601 (package-mark-obsolete name new-pkg-desc)))
602 new-pkg-desc))
619 603
620;; From Emacs 22. 604;; From Emacs 22.
621(defun package-autoload-ensure-default-file (file) 605(defun package-autoload-ensure-default-file (file)
@@ -711,7 +695,8 @@ PKG-DIR is the name of the package directory."
711 (version-to-list version))) 695 (version-to-list version)))
712 package-user-dir)) 696 package-user-dir))
713 (el-file (expand-file-name (format "%s.el" name) pkg-dir)) 697 (el-file (expand-file-name (format "%s.el" name) pkg-dir))
714 (pkg-file (expand-file-name (format "%s-pkg.el" name) pkg-dir))) 698 (pkg-file (expand-file-name (package--description-file pkg-dir)
699 pkg-dir)))
715 (make-directory pkg-dir t) 700 (make-directory pkg-dir t)
716 (package--write-file-no-coding el-file) 701 (package--write-file-no-coding el-file)
717 (let ((print-level nil) 702 (let ((print-level nil)
@@ -828,20 +813,15 @@ not included in this list."
828 ;; A package is required, but not installed. It might also be 813 ;; A package is required, but not installed. It might also be
829 ;; blocked via `package-load-list'. 814 ;; blocked via `package-load-list'.
830 (let ((pkg-desc (cdr (assq next-pkg package-archive-contents))) 815 (let ((pkg-desc (cdr (assq next-pkg package-archive-contents)))
831 hold) 816 (disabled (package-disabled-p next-pkg next-version)))
832 (when (setq hold (assq next-pkg package-load-list)) 817 (when disabled
833 (setq hold (cadr hold)) 818 (if (stringp disabled)
834 (cond ((eq hold t)) 819 (error "Package `%s' held at version %s, \
835 ((eq hold nil)
836 (error "Required package '%s' is disabled"
837 (symbol-name next-pkg)))
838 ((null (stringp hold))
839 (error "Invalid element in `package-load-list'"))
840 ((version-list-< (version-to-list hold) next-version)
841 (error "Package `%s' held at version %s, \
842but version %s required" 820but version %s required"
843 (symbol-name next-pkg) hold 821 (symbol-name next-pkg) disabled
844 (package-version-join next-version))))) 822 (package-version-join next-version))
823 (error "Required package '%s' is disabled"
824 (symbol-name next-pkg))))
845 (unless pkg-desc 825 (unless pkg-desc
846 (error "Package `%s-%s' is unavailable" 826 (error "Package `%s-%s' is unavailable"
847 (symbol-name next-pkg) 827 (symbol-name next-pkg)
@@ -954,6 +934,7 @@ PACKAGE-LIST should be a list of package names (symbols).
954This function assumes that all package requirements in 934This function assumes that all package requirements in
955PACKAGE-LIST are satisfied, i.e. that PACKAGE-LIST is computed 935PACKAGE-LIST are satisfied, i.e. that PACKAGE-LIST is computed
956using `package-compute-transaction'." 936using `package-compute-transaction'."
937 ;; FIXME: make package-list a list of pkg-desc.
957 (dolist (elt package-list) 938 (dolist (elt package-list)
958 (let* ((desc (cdr (assq elt package-archive-contents))) 939 (let* ((desc (cdr (assq elt package-archive-contents)))
959 ;; As an exception, if package is "held" in 940 ;; As an exception, if package is "held" in
@@ -974,15 +955,13 @@ using `package-compute-transaction'."
974 ;; If package A depends on package B, then A may `require' B 955 ;; If package A depends on package B, then A may `require' B
975 ;; during byte compilation. So we need to activate B before 956 ;; during byte compilation. So we need to activate B before
976 ;; unpacking A. 957 ;; unpacking A.
977 (package-maybe-load-descriptor (symbol-name elt) v-string
978 package-user-dir)
979 (package-activate elt (version-to-list v-string))))) 958 (package-activate elt (version-to-list v-string)))))
980 959
981;;;###autoload 960;;;###autoload
982(defun package-install (name) 961(defun package-install (pkg-desc)
983 "Install the package named NAME. 962 "Install the package PKG-DESC.
984NAME should be the name of one of the available packages in an 963PKG-DESC should be one of the available packages in an
985archive in `package-archives'. Interactively, prompt for NAME." 964archive in `package-archives'. Interactively, prompt for its name."
986 (interactive 965 (interactive
987 (progn 966 (progn
988 ;; Initialize the package system to get the list of package 967 ;; Initialize the package system to get the list of package
@@ -991,20 +970,22 @@ archive in `package-archives'. Interactively, prompt for NAME."
991 (package-initialize t)) 970 (package-initialize t))
992 (unless package-archive-contents 971 (unless package-archive-contents
993 (package-refresh-contents)) 972 (package-refresh-contents))
994 (list (intern (completing-read 973 (let* ((name (intern (completing-read
995 "Install package: " 974 "Install package: "
996 (mapcar (lambda (elt) 975 (mapcar (lambda (elt)
997 (cons (symbol-name (car elt)) 976 (cons (symbol-name (car elt))
998 nil)) 977 nil))
999 package-archive-contents) 978 package-archive-contents)
1000 nil t))))) 979 nil t)))
1001 (let ((pkg-desc (assq name package-archive-contents))) 980 (pkg-desc (cdr (assq name package-archive-contents))))
1002 (unless pkg-desc 981 (unless pkg-desc
1003 (error "Package `%s' is not available for installation" 982 (error "Package `%s' is not available for installation"
1004 (symbol-name name))) 983 name))
1005 (package-download-transaction 984 (list pkg-desc))))
1006 (package-compute-transaction (list name) 985 (package-download-transaction
1007 (package-desc-reqs (cdr pkg-desc)))))) 986 ;; FIXME: Use (list pkg-desc) instead of just the name.
987 (package-compute-transaction (list (package-desc-name pkg-desc))
988 (package-desc-reqs pkg-desc))))
1008 989
1009(defun package-strip-rcs-id (str) 990(defun package-strip-rcs-id (str)
1010 "Strip RCS version ID from the version string STR. 991 "Strip RCS version ID from the version string STR.
@@ -1055,31 +1036,28 @@ boundaries."
1055 "Find package information for a tar file. 1036 "Find package information for a tar file.
1056FILE is the name of the tar file to examine. 1037FILE is the name of the tar file to examine.
1057The return result is a vector like `package-buffer-info'." 1038The return result is a vector like `package-buffer-info'."
1058 (let ((default-directory (file-name-directory file)) 1039 (let* ((default-directory (file-name-directory file))
1059 (file (file-name-nondirectory file))) 1040 (file (file-name-nondirectory file))
1060 (unless (string-match (concat "\\`" package-subdirectory-regexp "\\.tar\\'") 1041 (dir-name
1061 file) 1042 (if (string-match "\\.tar\\'" file)
1062 (error "Invalid package name `%s'" file)) 1043 (substring file 0 (match-beginning 0))
1063 (let* ((pkg-name (match-string-no-properties 1 file)) 1044 (error "Invalid package name `%s'" file)))
1064 (pkg-version (match-string-no-properties 2 file)) 1045 (desc-file (package--description-file dir-name))
1065 ;; Extract the package descriptor. 1046 ;; Extract the package descriptor.
1066 (pkg-def-contents (shell-command-to-string 1047 (pkg-def-contents (shell-command-to-string
1067 ;; Requires GNU tar. 1048 ;; Requires GNU tar.
1068 (concat "tar -xOf " file " " 1049 (concat "tar -xOf " file " "
1069 pkg-name "-" pkg-version "/" 1050 dir-name "/" desc-file)))
1070 pkg-name "-pkg.el"))) 1051 (pkg-def-parsed (package-read-from-string pkg-def-contents)))
1071 (pkg-def-parsed (package-read-from-string pkg-def-contents))) 1052 (unless (eq (car pkg-def-parsed) 'define-package)
1072 (unless (eq (car pkg-def-parsed) 'define-package) 1053 (error "Can't find define-package in %s" desc-file))
1073 (error "No `define-package' sexp is present in `%s-pkg.el'" pkg-name)) 1054 (let ((pkg-desc
1074 (let ((pkg-desc 1055 (apply #'package-desc-from-define (append (cdr pkg-def-parsed)
1075 (apply #'package-desc-from-define (append (cdr pkg-def-parsed) 1056 '(:kind tar)))))
1076 '(:kind tar))))) 1057 (unless (equal dir-name (package-desc-full-name pkg-desc))
1077 (unless (equal pkg-version 1058 ;; FIXME: Shouldn't this just be a message/warning?
1078 (package-version-join (package-desc-version pkg-desc))) 1059 (error "Package has inconsistent name"))
1079 (error "Package has inconsistent versions")) 1060 pkg-desc)))
1080 (unless (equal pkg-name (symbol-name (package-desc-name pkg-desc)))
1081 (error "Package has inconsistent names"))
1082 pkg-desc))))
1083 1061
1084 1062
1085;;;###autoload 1063;;;###autoload
@@ -1123,17 +1101,17 @@ The file can either be a tar file or an Emacs Lisp file."
1123 (package-install-from-buffer (package-tar-file-info file))) 1101 (package-install-from-buffer (package-tar-file-info file)))
1124 (t (error "Unrecognized extension `%s'" (file-name-extension file)))))) 1102 (t (error "Unrecognized extension `%s'" (file-name-extension file))))))
1125 1103
1126(defun package-delete (name version) 1104(defun package-delete (pkg-desc)
1127 (let ((dir (package--dir name version))) 1105 (let ((dir (package-desc-dir pkg-desc)))
1128 (if (string-equal (file-name-directory dir) 1106 (if (string-equal (file-name-directory dir)
1129 (file-name-as-directory 1107 (file-name-as-directory
1130 (expand-file-name package-user-dir))) 1108 (expand-file-name package-user-dir)))
1131 (progn 1109 (progn
1132 (delete-directory dir t t) 1110 (delete-directory dir t t)
1133 (message "Package `%s-%s' deleted." name version)) 1111 (message "Package `%s' deleted." (package-desc-full-name pkg-desc)))
1134 ;; Don't delete "system" packages 1112 ;; Don't delete "system" packages
1135 (error "Package `%s-%s' is a system package, not deleting" 1113 (error "Package `%s' is a system package, not deleting"
1136 name version)))) 1114 (package-desc-full-name pkg-desc)))))
1137 1115
1138(defun package-archive-base (name) 1116(defun package-archive-base (name)
1139 "Return the archive containing the package NAME." 1117 "Return the archive containing the package NAME."
@@ -1212,7 +1190,7 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages."
1212 "Describe package: ") 1190 "Describe package: ")
1213 packages nil t nil nil guess)) 1191 packages nil t nil nil guess))
1214 (list (if (equal val "") guess (intern val))))) 1192 (list (if (equal val "") guess (intern val)))))
1215 (if (or (null package) (not (symbolp package))) 1193 (if (not (and package (symbolp package)))
1216 (message "No package specified") 1194 (message "No package specified")
1217 (help-setup-xref (list #'describe-package package) 1195 (help-setup-xref (list #'describe-package package)
1218 (called-interactively-p 'interactive)) 1196 (called-interactively-p 'interactive))
@@ -1231,7 +1209,7 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages."
1231 ;; Loaded packages are in `package-alist'. 1209 ;; Loaded packages are in `package-alist'.
1232 ((setq desc (cdr (assq package package-alist))) 1210 ((setq desc (cdr (assq package package-alist)))
1233 (setq version (package-version-join (package-desc-version desc))) 1211 (setq version (package-version-join (package-desc-version desc)))
1234 (if (setq pkg-dir (package--dir package-name version)) 1212 (if (setq pkg-dir (package-desc-dir desc))
1235 (insert "an installed package.\n\n") 1213 (insert "an installed package.\n\n")
1236 ;; This normally does not happen. 1214 ;; This normally does not happen.
1237 (insert "a deleted package.\n\n"))) 1215 (insert "a deleted package.\n\n")))
@@ -1279,7 +1257,7 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages."
1279 :foreground "black") 1257 :foreground "black")
1280 'link))) 1258 'link)))
1281 (insert-text-button button-text 'face button-face 'follow-link t 1259 (insert-text-button button-text 'face button-face 'follow-link t
1282 'package-symbol package 1260 'package-desc desc
1283 'action 'package-install-button-action))) 1261 'action 'package-install-button-action)))
1284 (built-in 1262 (built-in
1285 (insert (propertize "Built-in." 1263 (insert (propertize "Built-in."
@@ -1343,9 +1321,10 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages."
1343 (goto-char (point-max)))))))) 1321 (goto-char (point-max))))))))
1344 1322
1345(defun package-install-button-action (button) 1323(defun package-install-button-action (button)
1346 (let ((package (button-get button 'package-symbol))) 1324 (let ((pkg-desc (button-get button 'package-desc)))
1347 (when (y-or-n-p (format "Install package `%s'? " package)) 1325 (when (y-or-n-p (format "Install package `%s'? "
1348 (package-install package) 1326 (package-desc-full-name pkg-desc)))
1327 (package-install pkg-desc)
1349 (revert-buffer nil t) 1328 (revert-buffer nil t)
1350 (goto-char (point-min))))) 1329 (goto-char (point-min)))))
1351 1330
@@ -1434,29 +1413,26 @@ Letters do not insert themselves; instead, they are commands.
1434 (setq tabulated-list-sort-key (cons "Status" nil)) 1413 (setq tabulated-list-sort-key (cons "Status" nil))
1435 (tabulated-list-init-header)) 1414 (tabulated-list-init-header))
1436 1415
1437(defmacro package--push (package desc status listname) 1416(defmacro package--push (pkg-desc status listname)
1438 "Convenience macro for `package-menu--generate'. 1417 "Convenience macro for `package-menu--generate'.
1439If the alist stored in the symbol LISTNAME lacks an entry for a 1418If the alist stored in the symbol LISTNAME lacks an entry for a
1440package PACKAGE with descriptor DESC, add one. The alist is 1419package PKG-DESC, add one. The alist is keyed with PKG-DESC."
1441keyed with cons cells (PACKAGE . VERSION-LIST), where PACKAGE is 1420 `(unless (assoc ,pkg-desc ,listname)
1442a symbol and VERSION-LIST is a version list." 1421 ;; FIXME: Should we move status into pkg-desc?
1443 `(let* ((version (package-desc-version ,desc)) 1422 (push (cons ,pkg-desc ,status) ,listname)))
1444 (key (cons ,package version)))
1445 (unless (assoc key ,listname)
1446 (push (list key ,status (package-desc-summary ,desc)) ,listname))))
1447 1423
1448(defun package-menu--generate (remember-pos packages) 1424(defun package-menu--generate (remember-pos packages)
1449 "Populate the Package Menu. 1425 "Populate the Package Menu.
1450If REMEMBER-POS is non-nil, keep point on the same entry. 1426If REMEMBER-POS is non-nil, keep point on the same entry.
1451PACKAGES should be t, which means to display all known packages, 1427PACKAGES should be t, which means to display all known packages,
1452or a list of package names (symbols) to display." 1428or a list of package names (symbols) to display."
1453 ;; Construct list of ((PACKAGE . VERSION) STATUS DESCRIPTION). 1429 ;; Construct list of (PKG-DESC . STATUS).
1454 (let (info-list name) 1430 (let (info-list name)
1455 ;; Installed packages: 1431 ;; Installed packages:
1456 (dolist (elt package-alist) 1432 (dolist (elt package-alist)
1457 (setq name (car elt)) 1433 (setq name (car elt))
1458 (when (or (eq packages t) (memq name packages)) 1434 (when (or (eq packages t) (memq name packages))
1459 (package--push name (cdr elt) 1435 (package--push (cdr elt)
1460 (if (stringp (cadr (assq name package-load-list))) 1436 (if (stringp (cadr (assq name package-load-list)))
1461 "held" "installed") 1437 "held" "installed")
1462 info-list))) 1438 info-list)))
@@ -1466,14 +1442,14 @@ or a list of package names (symbols) to display."
1466 (setq name (car elt)) 1442 (setq name (car elt))
1467 (when (and (not (eq name 'emacs)) ; Hide the `emacs' package. 1443 (when (and (not (eq name 'emacs)) ; Hide the `emacs' package.
1468 (or (eq packages t) (memq name packages))) 1444 (or (eq packages t) (memq name packages)))
1469 (package--push name (package--from-builtin elt) "built-in" info-list))) 1445 (package--push (package--from-builtin elt) "built-in" info-list)))
1470 1446
1471 ;; Available and disabled packages: 1447 ;; Available and disabled packages:
1472 (dolist (elt package-archive-contents) 1448 (dolist (elt package-archive-contents)
1473 (setq name (car elt)) 1449 (setq name (car elt))
1474 (when (or (eq packages t) (memq name packages)) 1450 (when (or (eq packages t) (memq name packages))
1475 (let ((hold (assq name package-load-list))) 1451 (let ((hold (assq name package-load-list)))
1476 (package--push name (cdr elt) 1452 (package--push (cdr elt)
1477 (cond 1453 (cond
1478 ((and hold (null (cadr hold))) "disabled") 1454 ((and hold (null (cadr hold))) "disabled")
1479 ((memq name package-menu--new-package-list) "new") 1455 ((memq name package-menu--new-package-list) "new")
@@ -1484,7 +1460,7 @@ or a list of package names (symbols) to display."
1484 (dolist (elt package-obsolete-alist) 1460 (dolist (elt package-obsolete-alist)
1485 (dolist (inner-elt (cdr elt)) 1461 (dolist (inner-elt (cdr elt))
1486 (when (or (eq packages t) (memq (car elt) packages)) 1462 (when (or (eq packages t) (memq (car elt) packages))
1487 (package--push (car elt) (cdr inner-elt) "obsolete" info-list)))) 1463 (package--push (cdr inner-elt) "obsolete" info-list))))
1488 1464
1489 ;; Print the result. 1465 ;; Print the result.
1490 (setq tabulated-list-entries (mapcar 'package-menu--print-info info-list)) 1466 (setq tabulated-list-entries (mapcar 'package-menu--print-info info-list))
@@ -1492,31 +1468,30 @@ or a list of package names (symbols) to display."
1492 1468
1493(defun package-menu--print-info (pkg) 1469(defun package-menu--print-info (pkg)
1494 "Return a package entry suitable for `tabulated-list-entries'. 1470 "Return a package entry suitable for `tabulated-list-entries'.
1495PKG has the form ((PACKAGE . VERSION) STATUS DOC). 1471PKG has the form (PKG-DESC . STATUS).
1496Return (KEY [NAME VERSION STATUS DOC]), where KEY is the 1472Return (PKG-DESC [NAME VERSION STATUS DOC])."
1497identifier (NAME . VERSION-LIST)." 1473 (let* ((pkg-desc (car pkg))
1498 (let* ((package (caar pkg)) 1474 (status (cdr pkg))
1499 (version (cdr (car pkg))) 1475 (face (pcase status
1500 (status (nth 1 pkg)) 1476 (`"built-in" 'font-lock-builtin-face)
1501 (doc (or (nth 2 pkg) "")) 1477 (`"available" 'default)
1502 (face (cond 1478 (`"new" 'bold)
1503 ((string= status "built-in") 'font-lock-builtin-face) 1479 (`"held" 'font-lock-constant-face)
1504 ((string= status "available") 'default) 1480 (`"disabled" 'font-lock-warning-face)
1505 ((string= status "new") 'bold) 1481 (`"installed" 'font-lock-comment-face)
1506 ((string= status "held") 'font-lock-constant-face) 1482 (_ 'font-lock-warning-face)))) ; obsolete.
1507 ((string= status "disabled") 'font-lock-warning-face) 1483 (list pkg-desc
1508 ((string= status "installed") 'font-lock-comment-face) 1484 (vector (list (symbol-name (package-desc-name pkg-desc))
1509 (t 'font-lock-warning-face)))) ; obsolete.
1510 (list (cons package version)
1511 (vector (list (symbol-name package)
1512 'face 'link 1485 'face 'link
1513 'follow-link t 1486 'follow-link t
1514 'package-symbol package 1487 'package-desc pkg-desc
1515 'action 'package-menu-describe-package) 1488 'action 'package-menu-describe-package)
1516 (propertize (package-version-join version) 1489 (propertize (package-version-join
1490 (package-desc-version pkg-desc))
1517 'font-lock-face face) 1491 'font-lock-face face)
1518 (propertize status 'font-lock-face face) 1492 (propertize status 'font-lock-face face)
1519 (propertize doc 'font-lock-face face))))) 1493 (propertize (package-desc-summary pkg-desc)
1494 'font-lock-face face)))))
1520 1495
1521(defun package-menu-refresh () 1496(defun package-menu-refresh ()
1522 "Download the Emacs Lisp package archive. 1497 "Download the Emacs Lisp package archive.
@@ -1532,10 +1507,11 @@ This fetches the contents of each archive specified in
1532 "Describe the current package. 1507 "Describe the current package.
1533If optional arg BUTTON is non-nil, describe its associated package." 1508If optional arg BUTTON is non-nil, describe its associated package."
1534 (interactive) 1509 (interactive)
1535 (let ((package (if button (button-get button 'package-symbol) 1510 (let ((pkg-desc (if button (button-get button 'package-desc)
1536 (car (tabulated-list-get-id))))) 1511 (car (tabulated-list-get-id)))))
1537 (if package 1512 (if pkg-desc
1538 (describe-package package)))) 1513 ;; FIXME: We could actually describe this particular pkg-desc.
1514 (describe-package (package-desc-name pkg-desc)))))
1539 1515
1540;; fixme numeric argument 1516;; fixme numeric argument
1541(defun package-menu-mark-delete (&optional _num) 1517(defun package-menu-mark-delete (&optional _num)
@@ -1582,8 +1558,8 @@ If optional arg BUTTON is non-nil, describe its associated package."
1582 'package-menu-view-commentary 'package-menu-describe-package "24.1") 1558 'package-menu-view-commentary 'package-menu-describe-package "24.1")
1583 1559
1584(defun package-menu-get-status () 1560(defun package-menu-get-status ()
1585 (let* ((pkg (tabulated-list-get-id)) 1561 (let* ((id (tabulated-list-get-id))
1586 (entry (and pkg (assq pkg tabulated-list-entries)))) 1562 (entry (and id (assq id tabulated-list-entries))))
1587 (if entry 1563 (if entry
1588 (aref (cadr entry) 2) 1564 (aref (cadr entry) 2)
1589 ""))) 1565 "")))
@@ -1592,18 +1568,20 @@ If optional arg BUTTON is non-nil, describe its associated package."
1592 (let (installed available upgrades) 1568 (let (installed available upgrades)
1593 ;; Build list of installed/available packages in this buffer. 1569 ;; Build list of installed/available packages in this buffer.
1594 (dolist (entry tabulated-list-entries) 1570 (dolist (entry tabulated-list-entries)
1595 ;; ENTRY is ((NAME . VERSION) [NAME VERSION STATUS DOC]) 1571 ;; ENTRY is (PKG-DESC [NAME VERSION STATUS DOC])
1596 (let ((pkg (car entry)) 1572 (let ((pkg-desc (car entry))
1597 (status (aref (cadr entry) 2))) 1573 (status (aref (cadr entry) 2)))
1598 (cond ((equal status "installed") 1574 (cond ((equal status "installed")
1599 (push pkg installed)) 1575 (push pkg-desc installed))
1600 ((member status '("available" "new")) 1576 ((member status '("available" "new"))
1601 (push pkg available))))) 1577 (push (cons (package-desc-name pkg-desc) pkg-desc)
1602 ;; Loop through list of installed packages, finding upgrades 1578 available)))))
1603 (dolist (pkg installed) 1579 ;; Loop through list of installed packages, finding upgrades.
1604 (let ((avail-pkg (assq (car pkg) available))) 1580 (dolist (pkg-desc installed)
1581 (let ((avail-pkg (assq (package-desc-name pkg-desc) available)))
1605 (and avail-pkg 1582 (and avail-pkg
1606 (version-list-< (cdr pkg) (cdr avail-pkg)) 1583 (version-list-< (package-desc-version pkg-desc)
1584 (package-desc-version (cdr avail-pkg)))
1607 (push avail-pkg upgrades)))) 1585 (push avail-pkg upgrades))))
1608 upgrades)) 1586 upgrades))
1609 1587
@@ -1623,11 +1601,11 @@ call will upgrade the package."
1623 (save-excursion 1601 (save-excursion
1624 (goto-char (point-min)) 1602 (goto-char (point-min))
1625 (while (not (eobp)) 1603 (while (not (eobp))
1626 (let* ((pkg (tabulated-list-get-id)) 1604 (let* ((pkg-desc (tabulated-list-get-id))
1627 (upgrade (assq (car pkg) upgrades))) 1605 (upgrade (cdr (assq (package-desc-name pkg-desc) upgrades))))
1628 (cond ((null upgrade) 1606 (cond ((null upgrade)
1629 (forward-line 1)) 1607 (forward-line 1))
1630 ((equal pkg upgrade) 1608 ((equal pkg-desc upgrade)
1631 (package-menu-mark-install)) 1609 (package-menu-mark-install))
1632 (t 1610 (t
1633 (package-menu-mark-delete)))))) 1611 (package-menu-mark-delete))))))
@@ -1643,30 +1621,30 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm."
1643 (interactive) 1621 (interactive)
1644 (unless (derived-mode-p 'package-menu-mode) 1622 (unless (derived-mode-p 'package-menu-mode)
1645 (error "The current buffer is not in Package Menu mode")) 1623 (error "The current buffer is not in Package Menu mode"))
1646 (let (install-list delete-list cmd id) 1624 (let (install-list delete-list cmd pkg-desc)
1647 (save-excursion 1625 (save-excursion
1648 (goto-char (point-min)) 1626 (goto-char (point-min))
1649 (while (not (eobp)) 1627 (while (not (eobp))
1650 (setq cmd (char-after)) 1628 (setq cmd (char-after))
1651 (unless (eq cmd ?\s) 1629 (unless (eq cmd ?\s)
1652 ;; This is the key (PACKAGE . VERSION-LIST). 1630 ;; This is the key PKG-DESC.
1653 (setq id (tabulated-list-get-id)) 1631 (setq pkg-desc (tabulated-list-get-id))
1654 (cond ((eq cmd ?D) 1632 (cond ((eq cmd ?D)
1655 (push (cons (symbol-name (car id)) 1633 (push pkg-desc delete-list))
1656 (package-version-join (cdr id)))
1657 delete-list))
1658 ((eq cmd ?I) 1634 ((eq cmd ?I)
1659 (push (car id) install-list)))) 1635 (push pkg-desc install-list))))
1660 (forward-line))) 1636 (forward-line)))
1661 (when install-list 1637 (when install-list
1662 (if (or 1638 (if (or
1663 noquery 1639 noquery
1664 (yes-or-no-p 1640 (yes-or-no-p
1665 (if (= (length install-list) 1) 1641 (if (= (length install-list) 1)
1666 (format "Install package `%s'? " (car install-list)) 1642 (format "Install package `%s'? "
1667 (format "Install these %d packages (%s)? " 1643 (package-desc-full-name (car install-list)))
1668 (length install-list) 1644 (format "Install these %d packages (%s)? "
1669 (mapconcat 'symbol-name install-list ", "))))) 1645 (length install-list)
1646 (mapconcat #'package-desc-full-name
1647 install-list ", ")))))
1670 (mapc 'package-install install-list))) 1648 (mapc 'package-install install-list)))
1671 ;; Delete packages, prompting if necessary. 1649 ;; Delete packages, prompting if necessary.
1672 (when delete-list 1650 (when delete-list
@@ -1674,18 +1652,15 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm."
1674 noquery 1652 noquery
1675 (yes-or-no-p 1653 (yes-or-no-p
1676 (if (= (length delete-list) 1) 1654 (if (= (length delete-list) 1)
1677 (format "Delete package `%s-%s'? " 1655 (format "Delete package `%s'? "
1678 (caar delete-list) 1656 (package-desc-full-name (car delete-list)))
1679 (cdr (car delete-list)))
1680 (format "Delete these %d packages (%s)? " 1657 (format "Delete these %d packages (%s)? "
1681 (length delete-list) 1658 (length delete-list)
1682 (mapconcat (lambda (elt) 1659 (mapconcat #'package-desc-full-name
1683 (concat (car elt) "-" (cdr elt))) 1660 delete-list ", ")))))
1684 delete-list
1685 ", ")))))
1686 (dolist (elt delete-list) 1661 (dolist (elt delete-list)
1687 (condition-case-unless-debug err 1662 (condition-case-unless-debug err
1688 (package-delete (car elt) (cdr elt)) 1663 (package-delete elt)
1689 (error (message (cadr err))))) 1664 (error (message (cadr err)))))
1690 (error "Aborted"))) 1665 (error "Aborted")))
1691 ;; If we deleted anything, regenerate `package-alist'. This is done 1666 ;; If we deleted anything, regenerate `package-alist'. This is done
@@ -1730,8 +1705,8 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm."
1730 (string< dA dB)))) 1705 (string< dA dB))))
1731 1706
1732(defun package-menu--name-predicate (A B) 1707(defun package-menu--name-predicate (A B)
1733 (string< (symbol-name (caar A)) 1708 (string< (symbol-name (package-desc-name (car A)))
1734 (symbol-name (caar B)))) 1709 (symbol-name (package-desc-name (car B)))))
1735 1710
1736;;;###autoload 1711;;;###autoload
1737(defun list-packages (&optional no-fetch) 1712(defun list-packages (&optional no-fetch)
diff --git a/lisp/startup.el b/lisp/startup.el
index f21e8c4aa11..bd1e0db03e6 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -422,6 +422,13 @@ The second subexpression is the version string.
422The regexp should not contain a starting \"\\`\" or a trailing 422The regexp should not contain a starting \"\\`\" or a trailing
423 \"\\'\"; those are added automatically by callers.") 423 \"\\'\"; those are added automatically by callers.")
424 424
425(defun package--description-file (dir)
426 (concat (let ((subdir (file-name-nondirectory
427 (directory-file-name dir))))
428 (if (string-match package-subdirectory-regexp subdir)
429 (match-string 1 subdir) subdir))
430 "-pkg.el"))
431
425(defun normal-top-level-add-subdirs-to-load-path () 432(defun normal-top-level-add-subdirs-to-load-path ()
426 "Add all subdirectories of `default-directory' to `load-path'. 433 "Add all subdirectories of `default-directory' to `load-path'.
427More precisely, this uses only the subdirectories whose names 434More precisely, this uses only the subdirectories whose names
@@ -1194,10 +1201,10 @@ the `--debug-init' option to view a complete error backtrace."
1194 (dolist (dir dirs) 1201 (dolist (dir dirs)
1195 (when (file-directory-p dir) 1202 (when (file-directory-p dir)
1196 (dolist (subdir (directory-files dir)) 1203 (dolist (subdir (directory-files dir))
1197 (when (and (file-directory-p (expand-file-name subdir dir)) 1204 (when (let ((subdir (expand-file-name subdir dir)))
1198 (string-match 1205 (and (file-directory-p subdir)
1199 (concat "\\`" package-subdirectory-regexp "\\'") 1206 (file-exists-p
1200 subdir)) 1207 (package--description-file subdir))))
1201 (throw 'package-dir-found t))))))) 1208 (throw 'package-dir-found t)))))))
1202 (package-initialize)) 1209 (package-initialize))
1203 1210