Mercurial > emacs
comparison lisp/emacs-lisp/package.el @ 111394:72d2a83a2641
* emacs-lisp/package.el (package-unpack): Remove no-op.
(package--builtins, package--dir): Doc fix.
(package-activate-1, package-activate, package-install)
(package-compute-transaction): Fix error message.
(package-delete): Use delete-directory. Omit system packages.
(package-initialize): Set package-alist to nil first.
(package-menu-mark-delete, package-menu-mark-install): Don't add
symbols that are inconsistent with the package state.
(package-menu-execute): Perform deletions and installations as
single batch operations.
author | Chong Yidong <cyd@stupidchicken.com> |
---|---|
date | Wed, 03 Nov 2010 19:21:51 -0400 |
parents | 27839df805b0 |
children | 59101ed2e4c6 |
comparison
equal
deleted
inserted
replaced
111393:230a50b33a46 | 111394:72d2a83a2641 |
---|---|
75 ;; available to the user. | 75 ;; available to the user. |
76 ;; * Load. Actually load the package and run some code from it. | 76 ;; * Load. Actually load the package and run some code from it. |
77 | 77 |
78 ;; Other external functions you may want to use: | 78 ;; Other external functions you may want to use: |
79 ;; | 79 ;; |
80 ;; M-x package-list-packages | 80 ;; M-x list-packages |
81 ;; Enters a mode similar to buffer-menu which lets you manage | 81 ;; Enters a mode similar to buffer-menu which lets you manage |
82 ;; packages. You can choose packages for install (mark with "i", | 82 ;; packages. You can choose packages for install (mark with "i", |
83 ;; then "x" to execute) or deletion (not implemented yet), and you | 83 ;; then "x" to execute) or deletion (not implemented yet), and you |
84 ;; can see what packages are available. This will automatically | 84 ;; can see what packages are available. This will automatically |
85 ;; fetch the latest list of packages from ELPA. | 85 ;; fetch the latest list of packages from ELPA. |
213 (defvar Info-directory-list) | 213 (defvar Info-directory-list) |
214 (declare-function info-initialize "info" ()) | 214 (declare-function info-initialize "info" ()) |
215 (declare-function url-http-parse-response "url-http" ()) | 215 (declare-function url-http-parse-response "url-http" ()) |
216 (declare-function lm-header "lisp-mnt" (header)) | 216 (declare-function lm-header "lisp-mnt" (header)) |
217 (declare-function lm-commentary "lisp-mnt" (&optional file)) | 217 (declare-function lm-commentary "lisp-mnt" (&optional file)) |
218 (declare-function dired-delete-file "dired" (file &optional recursive trash)) | |
219 (defvar url-http-end-of-headers) | 218 (defvar url-http-end-of-headers) |
220 | 219 |
221 (defcustom package-archives '(("gnu" . "http://elpa.gnu.org/packages/")) | 220 (defcustom package-archives '(("gnu" . "http://elpa.gnu.org/packages/")) |
222 "An alist of archives from which to fetch. | 221 "An alist of archives from which to fetch. |
223 The default value points to the GNU Emacs package repository. | 222 The default value points to the GNU Emacs package repository. |
276 | 275 |
277 ;; The value is precomputed in finder-inf.el, but don't load that | 276 ;; The value is precomputed in finder-inf.el, but don't load that |
278 ;; until it's needed (i.e. when `package-intialize' is called). | 277 ;; until it's needed (i.e. when `package-intialize' is called). |
279 (defvar package--builtins nil | 278 (defvar package--builtins nil |
280 "Alist of built-in packages. | 279 "Alist of built-in packages. |
280 The actual value is initialized by loading the library | |
281 `finder-inf'; this is not done until it is needed, e.g. by the | |
282 function `package-built-in-p'. | |
283 | |
281 Each element has the form (PKG . DESC), where PKG is a package | 284 Each element has the form (PKG . DESC), where PKG is a package |
282 name (a symbol) and DESC is a vector that describes the package. | 285 name (a symbol) and DESC is a vector that describes the package. |
283 | |
284 The vector DESC has the form [VERSION REQS DOCSTRING]. | 286 The vector DESC has the form [VERSION REQS DOCSTRING]. |
285 VERSION is a version list. | 287 VERSION is a version list. |
286 REQS is a list of packages (symbols) required by the package. | 288 REQS is a list of packages (symbols) required by the package. |
287 DOCSTRING is a brief description of the package.") | 289 DOCSTRING is a brief description of the package.") |
288 (put 'package--builtins 'risky-local-variable t) | 290 (put 'package--builtins 'risky-local-variable t) |
387 | 389 |
388 (defsubst package-desc-kind (desc) | 390 (defsubst package-desc-kind (desc) |
389 "Extract the kind of download from an archive package description vector." | 391 "Extract the kind of download from an archive package description vector." |
390 (aref desc 3)) | 392 (aref desc 3)) |
391 | 393 |
392 (defun package--dir (name version-string) | 394 (defun package--dir (name version) |
393 (let* ((subdir (concat name "-" version-string)) | 395 "Return the directory where a package is installed, or nil if none. |
396 NAME and VERSION are both strings." | |
397 (let* ((subdir (concat name "-" version)) | |
394 (dir-list (cons package-user-dir package-directory-list)) | 398 (dir-list (cons package-user-dir package-directory-list)) |
395 pkg-dir) | 399 pkg-dir) |
396 (while dir-list | 400 (while dir-list |
397 (let ((subdir-full (expand-file-name subdir (car dir-list)))) | 401 (let ((subdir-full (expand-file-name subdir (car dir-list)))) |
398 (if (file-directory-p subdir-full) | 402 (if (file-directory-p subdir-full) |
404 (defun package-activate-1 (package pkg-vec) | 408 (defun package-activate-1 (package pkg-vec) |
405 (let* ((name (symbol-name package)) | 409 (let* ((name (symbol-name package)) |
406 (version-str (package-version-join (package-desc-vers pkg-vec))) | 410 (version-str (package-version-join (package-desc-vers pkg-vec))) |
407 (pkg-dir (package--dir name version-str))) | 411 (pkg-dir (package--dir name version-str))) |
408 (unless pkg-dir | 412 (unless pkg-dir |
409 (error "Internal error: could not find directory for %s-%s" | 413 (error "Internal error: unable to find directory for `%s-%s'" |
410 name version-str)) | 414 name version-str)) |
411 ;; Add info node. | 415 ;; Add info node. |
412 (when (file-exists-p (expand-file-name "dir" pkg-dir)) | 416 (when (file-exists-p (expand-file-name "dir" pkg-dir)) |
413 ;; FIXME: not the friendliest, but simple. | 417 ;; FIXME: not the friendliest, but simple. |
414 (require 'info) | 418 (require 'info) |
455 (dolist (req (package-desc-reqs pkg-vec)) | 459 (dolist (req (package-desc-reqs pkg-vec)) |
456 (unless (package-activate (car req) (cadr req)) | 460 (unless (package-activate (car req) (cadr req)) |
457 (throw 'dep-failure req)))))) | 461 (throw 'dep-failure req)))))) |
458 (if fail | 462 (if fail |
459 (warn "Unable to activate package `%s'. | 463 (warn "Unable to activate package `%s'. |
460 Required package `%s', version %s, is unavailable" | 464 Required package `%s-%s' is unavailable" |
461 package (car fail) (package-version-join (cadr fail))) | 465 package (car fail) (package-version-join (cadr fail))) |
462 ;; If all goes well, activate the package itself. | 466 ;; If all goes well, activate the package itself. |
463 (package-activate-1 package pkg-vec))))))) | 467 (package-activate-1 package pkg-vec))))))) |
464 | 468 |
465 (defun package-mark-obsolete (package pkg-vec) | 469 (defun package-mark-obsolete (package pkg-vec) |
563 "xf" "-"))) | 567 "xf" "-"))) |
564 | 568 |
565 (defun package-unpack (name version) | 569 (defun package-unpack (name version) |
566 (let ((pkg-dir (expand-file-name (concat (symbol-name name) "-" version) | 570 (let ((pkg-dir (expand-file-name (concat (symbol-name name) "-" version) |
567 package-user-dir))) | 571 package-user-dir))) |
568 ;; Be careful!! | |
569 (make-directory package-user-dir t) | 572 (make-directory package-user-dir t) |
570 (if (file-directory-p pkg-dir) | 573 ;; FIXME: should we delete PKG-DIR if it exists? |
571 (mapc (lambda (file) nil) ; 'delete-file -- FIXME: when we're | |
572 ; more confident | |
573 (directory-files pkg-dir t "^[^.]"))) | |
574 (let* ((default-directory (file-name-as-directory package-user-dir))) | 574 (let* ((default-directory (file-name-as-directory package-user-dir))) |
575 (package-untar-buffer) | 575 (package-untar-buffer) |
576 (package-generate-autoloads (symbol-name name) pkg-dir) | 576 (package-generate-autoloads (symbol-name name) pkg-dir) |
577 (let ((load-path (cons pkg-dir load-path))) | 577 (let ((load-path (cons pkg-dir load-path))) |
578 (byte-recompile-directory pkg-dir 0 t))))) | 578 (byte-recompile-directory pkg-dir 0 t))))) |
606 (list 'quote | 606 (list 'quote |
607 ;; Turn version lists into string form. | 607 ;; Turn version lists into string form. |
608 (mapcar | 608 (mapcar |
609 (lambda (elt) | 609 (lambda (elt) |
610 (list (car elt) | 610 (list (car elt) |
611 (package-version-join (car (cdr elt))))) | 611 (package-version-join (cadr elt)))) |
612 requires)))) | 612 requires)))) |
613 "\n") | 613 "\n") |
614 nil | 614 nil |
615 pkg-file | 615 pkg-file |
616 nil nil nil 'excl)) | 616 nil nil nil 'excl)) |
696 (error "Required package '%s' is disabled" | 696 (error "Required package '%s' is disabled" |
697 (symbol-name next-pkg))) | 697 (symbol-name next-pkg))) |
698 ((null (stringp hold)) | 698 ((null (stringp hold)) |
699 (error "Invalid element in `package-load-list'")) | 699 (error "Invalid element in `package-load-list'")) |
700 ((version-list-< (version-to-list hold) next-version) | 700 ((version-list-< (version-to-list hold) next-version) |
701 (error "Package '%s' held at version %s, \ | 701 (error "Package `%s' held at version %s, \ |
702 but version %s required" | 702 but version %s required" |
703 (symbol-name next-pkg) hold | 703 (symbol-name next-pkg) hold |
704 (package-version-join next-version))))) | 704 (package-version-join next-version))))) |
705 (unless pkg-desc | 705 (unless pkg-desc |
706 (error "Package '%s', version %s, unavailable for installation" | 706 (error "Package `%s-%s' is unavailable" |
707 (symbol-name next-pkg) | 707 (symbol-name next-pkg) |
708 (package-version-join next-version))) | 708 (package-version-join next-version))) |
709 (unless (version-list-<= next-version | 709 (unless (version-list-<= next-version |
710 (package-desc-vers (cdr pkg-desc))) | 710 (package-desc-vers (cdr pkg-desc))) |
711 (error | 711 (error |
712 "Need package '%s' with version %s, but only %s is available" | 712 "Need package `%s-%s', but only %s is available" |
713 (symbol-name next-pkg) (package-version-join next-version) | 713 (symbol-name next-pkg) (package-version-join next-version) |
714 (package-version-join (package-desc-vers (cdr pkg-desc))))) | 714 (package-version-join (package-desc-vers (cdr pkg-desc))))) |
715 ;; Only add to the transaction if we don't already have it. | 715 ;; Only add to the transaction if we don't already have it. |
716 (unless (memq next-pkg package-list) | 716 (unless (memq next-pkg package-list) |
717 (push next-pkg package-list)) | 717 (push next-pkg package-list)) |
817 nil)) | 817 nil)) |
818 package-archive-contents) | 818 package-archive-contents) |
819 nil t)))) | 819 nil t)))) |
820 (let ((pkg-desc (assq name package-archive-contents))) | 820 (let ((pkg-desc (assq name package-archive-contents))) |
821 (unless pkg-desc | 821 (unless pkg-desc |
822 (error "Package '%s' is not available for installation" | 822 (error "Package `%s' is not available for installation" |
823 (symbol-name name))) | 823 (symbol-name name))) |
824 (package-download-transaction | 824 (package-download-transaction |
825 (package-compute-transaction (list name) | 825 (package-compute-transaction (list name) |
826 (package-desc-reqs (cdr pkg-desc))))) | 826 (package-desc-reqs (cdr pkg-desc))))) |
827 ;; Try to activate it. | 827 ;; Try to activate it. |
974 ((string-match "\\.tar$" file) | 974 ((string-match "\\.tar$" file) |
975 (package-install-from-buffer (package-tar-file-info file) 'tar)) | 975 (package-install-from-buffer (package-tar-file-info file) 'tar)) |
976 (t (error "Unrecognized extension `%s'" (file-name-extension file)))))) | 976 (t (error "Unrecognized extension `%s'" (file-name-extension file)))))) |
977 | 977 |
978 (defun package-delete (name version) | 978 (defun package-delete (name version) |
979 (require 'dired) ; for dired-delete-file | 979 (let ((dir (package--dir name version))) |
980 (dired-delete-file (expand-file-name (concat name "-" version) | 980 (if (string-equal (file-name-directory dir) |
981 package-user-dir) | 981 (file-name-as-directory |
982 ;; FIXME: query user? | 982 (expand-file-name package-user-dir))) |
983 'always)) | 983 (progn |
984 (delete-directory dir t t) | |
985 (message "Package `%s-%s' deleted." name version)) | |
986 ;; Don't delete "system" packages | |
987 (error "Package `%s-%s' is a system package, not deleting" | |
988 name version)))) | |
984 | 989 |
985 (defun package-archive-url (name) | 990 (defun package-archive-url (name) |
986 "Return the archive containing the package NAME." | 991 "Return the archive containing the package NAME." |
987 (let ((desc (cdr (assq (intern-soft name) package-archive-contents)))) | 992 (let ((desc (cdr (assq (intern-soft name) package-archive-contents)))) |
988 (cdr (assoc (aref desc (- (length desc) 1)) package-archives)))) | 993 (cdr (assoc (aref desc (- (length desc) 1)) package-archives)))) |
1028 (defun package-initialize (&optional no-activate) | 1033 (defun package-initialize (&optional no-activate) |
1029 "Load Emacs Lisp packages, and activate them. | 1034 "Load Emacs Lisp packages, and activate them. |
1030 The variable `package-load-list' controls which packages to load. | 1035 The variable `package-load-list' controls which packages to load. |
1031 If optional arg NO-ACTIVATE is non-nil, don't activate packages." | 1036 If optional arg NO-ACTIVATE is non-nil, don't activate packages." |
1032 (interactive) | 1037 (interactive) |
1033 (setq package-obsolete-alist nil) | 1038 (setq package-alist nil |
1039 package-obsolete-alist nil) | |
1034 (package-load-all-descriptors) | 1040 (package-load-all-descriptors) |
1035 (package-read-all-archive-contents) | 1041 (package-read-all-archive-contents) |
1036 (unless no-activate | 1042 (unless no-activate |
1037 (dolist (elt package-alist) | 1043 (dolist (elt package-alist) |
1038 (package-activate (car elt) (package-desc-vers (cdr elt))))) | 1044 (package-activate (car elt) (package-desc-vers (cdr elt))))) |
1359 | 1365 |
1360 ;; fixme numeric argument | 1366 ;; fixme numeric argument |
1361 (defun package-menu-mark-delete (num) | 1367 (defun package-menu-mark-delete (num) |
1362 "Mark a package for deletion and move to the next line." | 1368 "Mark a package for deletion and move to the next line." |
1363 (interactive "p") | 1369 (interactive "p") |
1364 (package-menu-mark-internal "D")) | 1370 (if (string-equal (package-menu-get-status) "installed") |
1371 (package-menu-mark-internal "D") | |
1372 (forward-line))) | |
1365 | 1373 |
1366 (defun package-menu-mark-install (num) | 1374 (defun package-menu-mark-install (num) |
1367 "Mark a package for installation and move to the next line." | 1375 "Mark a package for installation and move to the next line." |
1368 (interactive "p") | 1376 (interactive "p") |
1369 (package-menu-mark-internal "I")) | 1377 (if (string-equal (package-menu-get-status) "available") |
1378 (package-menu-mark-internal "I") | |
1379 (forward-line))) | |
1370 | 1380 |
1371 (defun package-menu-mark-unmark (num) | 1381 (defun package-menu-mark-unmark (num) |
1372 "Clear any marks on a package and move to the next line." | 1382 "Clear any marks on a package and move to the next line." |
1373 (interactive "p") | 1383 (interactive "p") |
1374 (package-menu-mark-internal " ")) | 1384 (package-menu-mark-internal " ")) |
1418 (if (looking-at ". [^ \t]*[ \t]*[^ \t]*[ \t]*\\([^ \t]*\\)") | 1428 (if (looking-at ". [^ \t]*[ \t]*[^ \t]*[ \t]*\\([^ \t]*\\)") |
1419 (match-string 1) | 1429 (match-string 1) |
1420 ""))) | 1430 ""))) |
1421 | 1431 |
1422 (defun package-menu-execute () | 1432 (defun package-menu-execute () |
1423 "Perform all the marked actions. | 1433 "Perform marked Package Menu actions. |
1424 Packages marked for installation will be downloaded and | 1434 Packages marked for installation are downloaded and installed; |
1425 installed. Packages marked for deletion will be removed. | 1435 packages marked for deletion are removed." |
1426 Note that after installing packages you will want to restart | |
1427 Emacs." | |
1428 (interactive) | 1436 (interactive) |
1429 (goto-char (point-min)) | 1437 (let (install-list delete-list cmd) |
1430 (while (not (eobp)) | 1438 (save-excursion |
1431 (let ((cmd (char-after)) | 1439 (goto-char (point-min)) |
1432 (pkg-name (package-menu-get-package)) | 1440 (while (not (eobp)) |
1433 (pkg-vers (package-menu-get-version)) | 1441 (setq cmd (char-after)) |
1434 (pkg-status (package-menu-get-status))) | 1442 (cond |
1435 (cond | 1443 ((eq cmd ?\s) t) |
1436 ((eq cmd ?D) | 1444 ((eq cmd ?D) |
1437 (when (and (string= pkg-status "installed") | 1445 (push (cons (package-menu-get-package) |
1438 (string= pkg-name "package")) | 1446 (package-menu-get-version)) |
1439 ;; FIXME: actually, we could be tricky and remove all info. | 1447 delete-list)) |
1440 ;; But that is drastic and the user can do that instead. | 1448 ((eq cmd ?I) |
1441 (error "Can't delete most recent version of `package'")) | 1449 (push (package-menu-get-package) install-list))) |
1442 ;; Ask for confirmation here? Maybe if package status is ""? | 1450 (forward-line))) |
1443 ;; Or if any lisp from package is actually loaded? | 1451 ;; Delete packages, prompting if necessary. |
1444 (message "Deleting %s-%s..." pkg-name pkg-vers) | 1452 (when delete-list |
1445 (package-delete pkg-name pkg-vers) | 1453 (if (yes-or-no-p |
1446 (message "Deleting %s-%s... done" pkg-name pkg-vers)) | 1454 (if (= (length delete-list) 1) |
1447 ((eq cmd ?I) | 1455 (format "Delete package `%s-%s'? " |
1448 (package-install (intern pkg-name))))) | 1456 (caar delete-list) |
1449 (forward-line)) | 1457 (cdr (car delete-list))) |
1450 (package-menu-revert)) | 1458 (format "Delete these %d packages (%s)? " |
1459 (length delete-list) | |
1460 (mapconcat (lambda (elt) | |
1461 (concat (car elt) "-" (cdr elt))) | |
1462 delete-list | |
1463 ", ")))) | |
1464 (dolist (elt delete-list) | |
1465 (condition-case err | |
1466 (package-delete (car elt) (cdr elt)) | |
1467 (error (message (cadr err))))) | |
1468 (error "Aborted"))) | |
1469 (when install-list | |
1470 (if (yes-or-no-p | |
1471 (if (= (length install-list) 1) | |
1472 (format "Install package `%s'? " (car install-list)) | |
1473 (format "Install these %d packages (%s)? " | |
1474 (length install-list) | |
1475 (mapconcat 'identity install-list ", ")))) | |
1476 (dolist (elt install-list) | |
1477 (package-install (intern elt))))) | |
1478 ;; If we deleted anything, regenerate `package-alist'. This is done | |
1479 ;; automatically if we installed a package. | |
1480 (and delete-list (null install-list) | |
1481 (package-initialize)) | |
1482 (if (or delete-list install-list) | |
1483 (package-menu-revert) | |
1484 (message "No operations specified.")))) | |
1451 | 1485 |
1452 (defun package-print-package (package version key desc) | 1486 (defun package-print-package (package version key desc) |
1453 (let ((face | 1487 (let ((face |
1454 (cond ((string= key "built-in") 'font-lock-builtin-face) | 1488 (cond ((string= key "built-in") 'font-lock-builtin-face) |
1455 ((string= key "available") 'default) | 1489 ((string= key "available") 'default) |