* lisp/emacs-lisp/package.el (package-activate-1): Don't add unnecessarily
[bpt/emacs.git] / lisp / emacs-lisp / package.el
CommitLineData
12059709 1;;; package.el --- Simple package system for Emacs -*- lexical-binding:t -*-
44198b6e 2
ab422c4d 3;; Copyright (C) 2007-2013 Free Software Foundation, Inc.
44198b6e
CY
4
5;; Author: Tom Tromey <tromey@redhat.com>
a49ff80c 6;; Daniel Hackney <dan@haxney.org>
44198b6e 7;; Created: 10 Mar 2007
397703b4 8;; Version: 1.0.1
44198b6e 9;; Keywords: tools
469bfed9 10;; Package-Requires: ((tabulated-list "1.0"))
44198b6e
CY
11
12;; This file is part of GNU Emacs.
13
267b82ff 14;; GNU Emacs is free software: you can redistribute it and/or modify
44198b6e 15;; it under the terms of the GNU General Public License as published by
267b82ff
GM
16;; the Free Software Foundation, either version 3 of the License, or
17;; (at your option) any later version.
44198b6e
CY
18
19;; GNU Emacs is distributed in the hope that it will be useful,
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
23
24;; You should have received a copy of the GNU General Public License
267b82ff 25;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
44198b6e
CY
26
27;;; Change Log:
28
29;; 2 Apr 2007 - now using ChangeLog file
30;; 15 Mar 2007 - updated documentation
31;; 14 Mar 2007 - Changed how obsolete packages are handled
32;; 13 Mar 2007 - Wrote package-install-from-buffer
33;; 12 Mar 2007 - Wrote package-menu mode
34
35;;; Commentary:
36
37;; The idea behind package.el is to be able to download packages and
38;; install them. Packages are versioned and have versioned
39;; dependencies. Furthermore, this supports built-in packages which
40;; may or may not be newer than user-specified packages. This makes
41;; it possible to upgrade Emacs and automatically disable packages
42;; which have moved from external to core. (Note though that we don't
43;; currently register any of these, so this feature does not actually
44;; work.)
45
44198b6e
CY
46;; A package is described by its name and version. The distribution
47;; format is either a tar file or a single .el file.
48
49;; A tar file should be named "NAME-VERSION.tar". The tar file must
50;; unpack into a directory named after the package and version:
51;; "NAME-VERSION". It must contain a file named "PACKAGE-pkg.el"
52;; which consists of a call to define-package. It may also contain a
53;; "dir" file and the info files it references.
54
bc44bef7 55;; A .el file is named "NAME-VERSION.el" in the remote archive, but is
44198b6e
CY
56;; installed as simply "NAME.el" in a directory named "NAME-VERSION".
57
bc44bef7
PH
58;; The downloader downloads all dependent packages. By default,
59;; packages come from the official GNU sources, but others may be
60;; added by customizing the `package-archives' alist. Packages get
61;; byte-compiled at install time.
44198b6e
CY
62
63;; At activation time we will set up the load-path and the info path,
64;; and we will load the package's autoloads. If a package's
65;; dependencies are not available, we will not activate that package.
66
67;; Conceptually a package has multiple state transitions:
68;;
69;; * Download. Fetching the package from ELPA.
70;; * Install. Untar the package, or write the .el file, into
71;; ~/.emacs.d/elpa/ directory.
72;; * Byte compile. Currently this phase is done during install,
73;; but we may change this.
74;; * Activate. Evaluate the autoloads for the package to make it
75;; available to the user.
76;; * Load. Actually load the package and run some code from it.
77
78;; Other external functions you may want to use:
79;;
015eea59 80;; M-x list-packages
44198b6e
CY
81;; Enters a mode similar to buffer-menu which lets you manage
82;; packages. You can choose packages for install (mark with "i",
83;; then "x" to execute) or deletion (not implemented yet), and you
84;; can see what packages are available. This will automatically
85;; fetch the latest list of packages from ELPA.
86;;
44198b6e
CY
87;; M-x package-install-from-buffer
88;; Install a package consisting of a single .el file that appears
89;; in the current buffer. This only works for packages which
90;; define a Version header properly; package.el also supports the
91;; extension headers Package-Version (in case Version is an RCS id
92;; or similar), and Package-Requires (if the package requires other
93;; packages).
94;;
95;; M-x package-install-file
96;; Install a package from the indicated file. The package can be
97;; either a tar file or a .el file. A tar file must contain an
98;; appropriately-named "-pkg.el" file; a .el file must be properly
99;; formatted as with package-install-from-buffer.
100
101;;; Thanks:
102;;; (sorted by sort-lines):
103
104;; Jim Blandy <jimb@red-bean.com>
105;; Karl Fogel <kfogel@red-bean.com>
106;; Kevin Ryde <user42@zip.com.au>
107;; Lawrence Mitchell
108;; Michael Olson <mwolson@member.fsf.org>
109;; Sebastian Tennant <sebyte@smolny.plus.com>
110;; Stefan Monnier <monnier@iro.umontreal.ca>
111;; Vinicius Jose Latorre <viniciusjl@ig.com.br>
112;; Phil Hagelberg <phil@hagelb.org>
113
114;;; ToDo:
115
5580f89d
GM
116;; - a trust mechanism, since compiling a package can run arbitrary code.
117;; For example, download package signatures and check that they match.
44198b6e
CY
118;; - putting info dirs at the start of the info path means
119;; users see a weird ordering of categories. OTOH we want to
120;; override later entries. maybe emacs needs to enforce
121;; the standard layout?
122;; - put bytecode in a separate directory tree
123;; - perhaps give users a way to recompile their bytecode
124;; or do it automatically when emacs changes
125;; - give users a way to know whether a package is installed ok
126;; - give users a way to view a package's documentation when it
127;; only appears in the .el
128;; - use/extend checkdoc so people can tell if their package will work
129;; - "installed" instead of a blank in the status column
130;; - tramp needs its files to be compiled in a certain order.
131;; how to handle this? fix tramp?
132;; - on emacs 21 we don't kill the -autoloads.el buffer. what about 22?
133;; - maybe we need separate .elc directories for various emacs versions
134;; and also emacs-vs-xemacs. That way conditional compilation can
135;; work. But would this break anything?
136;; - should store the package's keywords in archive-contents, then
137;; let the users filter the package-menu by keyword. See
138;; finder-by-keyword. (We could also let people view the
139;; Commentary, but it isn't clear how useful this is.)
140;; - William Xu suggests being able to open a package file without
141;; installing it
142;; - Interface with desktop.el so that restarting after an install
143;; works properly
44198b6e
CY
144;; - Use hierarchical layout. PKG/etc PKG/lisp PKG/info
145;; ... except maybe lisp?
146;; - It may be nice to have a macro that expands to the package's
147;; private data dir, aka ".../etc". Or, maybe data-directory
148;; needs to be a list (though this would be less nice)
149;; a few packages want this, eg sokoban
150;; - package menu needs:
151;; ability to know which packages are built-in & thus not deletable
152;; it can sometimes print odd results, like 0.3 available but 0.4 active
153;; why is that?
154;; - Allow multiple versions on the server...?
155;; [ why bother? ]
156;; - Don't install a package which will invalidate dependencies overall
157;; - Allow something like (or (>= emacs 21.0) (>= xemacs 21.5))
158;; [ currently thinking, why bother.. KISS ]
159;; - Allow optional package dependencies
160;; then if we require 'bbdb', bbdb-specific lisp in lisp/bbdb
161;; and just don't compile to add to load path ...?
44198b6e 162;; - Our treatment of the info path is somewhat bogus
44198b6e
CY
163
164;;; Code:
165
f56be016
SM
166(eval-when-compile (require 'cl-lib))
167
e91a96fe
CY
168(require 'tabulated-list)
169
44198b6e
CY
170(defgroup package nil
171 "Manager for Emacs Lisp packages."
172 :group 'applications
173 :version "24.1")
174
175;;;###autoload
176(defcustom package-enable-at-startup t
177 "Whether to activate installed packages when Emacs starts.
178If non-nil, packages are activated after reading the init file
179and before `after-init-hook'. Activation is not done if
180`user-init-file' is nil (e.g. Emacs was started with \"-q\").
181
182Even if the value is nil, you can type \\[package-initialize] to
183activate the package system at any time."
184 :type 'boolean
185 :group 'package
186 :version "24.1")
187
188(defcustom package-load-list '(all)
189 "List of packages for `package-initialize' to load.
190Each element in this list should be a list (NAME VERSION), or the
191symbol `all'. The symbol `all' says to load the latest installed
192versions of all packages not specified by other elements.
193
194For an element (NAME VERSION), NAME is a package name (a symbol).
195VERSION should be t, a string, or nil.
a7d2d465 196If VERSION is t, the most recent version is activated.
44198b6e
CY
197If VERSION is a string, only that version is ever loaded.
198 Any other version, even if newer, is silently ignored.
199 Hence, the package is \"held\" at that version.
200If VERSION is nil, the package is not loaded (it is \"disabled\")."
201 :type '(repeat symbol)
bc44bef7 202 :risky t
44198b6e
CY
203 :group 'package
204 :version "24.1")
205
206(defvar Info-directory-list)
44198b6e
CY
207(declare-function info-initialize "info" ())
208(declare-function url-http-parse-response "url-http" ())
209(declare-function lm-header "lisp-mnt" (header))
210(declare-function lm-commentary "lisp-mnt" (&optional file))
cb6c4991 211(defvar url-http-end-of-headers)
44198b6e 212
bc44bef7
PH
213(defcustom package-archives '(("gnu" . "http://elpa.gnu.org/packages/"))
214 "An alist of archives from which to fetch.
215The default value points to the GNU Emacs package repository.
f561e49a
CY
216
217Each element has the form (ID . LOCATION).
218 ID is an archive name, as a string.
219 LOCATION specifies the base location for the archive.
220 If it starts with \"http:\", it is treated as a HTTP URL;
221 otherwise it should be an absolute directory name.
5580f89d
GM
222 (Other types of URL are currently not supported.)
223
224Only add locations that you trust, since fetching and installing
225a package can run arbitrary code."
bc44bef7 226 :type '(alist :key-type (string :tag "Archive name")
f561e49a 227 :value-type (string :tag "URL or directory name"))
bc44bef7
PH
228 :risky t
229 :group 'package
230 :version "24.1")
44198b6e 231
397703b4
YH
232(defcustom package-pinned-packages nil
233 "An alist of packages that are pinned to a specific archive
234
235Each element has the form (SYM . ID).
236 SYM is a package, as a symbol.
5b165ade 237 ID is an archive name. This should correspond to an
397703b4
YH
238 entry in `package-archives'.
239
240If the archive of name ID does not contain the package SYM, no
241other location will be considered, which will make the
242package unavailable."
243 :type '(alist :key-type (symbol :tag "Package")
244 :value-type (string :tag "Archive name"))
245 :risky t
246 :group 'package
247 :version "24.4")
248
44198b6e
CY
249(defconst package-archive-version 1
250 "Version number of the package archive understood by this file.
251Lower version numbers than this will probably be understood as well.")
252
44198b6e
CY
253;; We don't prime the cache since it tends to get out of date.
254(defvar package-archive-contents nil
255 "Cache of the contents of the Emacs Lisp Package Archive.
f56be016 256This is an alist mapping package names (symbols) to
12059709 257non-empty lists of `package-desc' structures.")
bc44bef7 258(put 'package-archive-contents 'risky-local-variable t)
44198b6e
CY
259
260(defcustom package-user-dir (locate-user-emacs-file "elpa")
261 "Directory containing the user's Emacs Lisp packages.
262The directory name should be absolute.
263Apart from this directory, Emacs also looks for system-wide
264packages in `package-directory-list'."
265 :type 'directory
bc44bef7 266 :risky t
44198b6e
CY
267 :group 'package
268 :version "24.1")
269
270(defcustom package-directory-list
271 ;; Defaults are subdirs named "elpa" in the site-lisp dirs.
272 (let (result)
273 (dolist (f load-path)
0be01d2c
CY
274 (and (stringp f)
275 (equal (file-name-nondirectory f) "site-lisp")
276 (push (expand-file-name "elpa" f) result)))
44198b6e
CY
277 (nreverse result))
278 "List of additional directories containing Emacs Lisp packages.
279Each directory name should be absolute.
280
281These directories contain packages intended for system-wide; in
282contrast, `package-user-dir' contains packages for personal use."
283 :type '(repeat directory)
bc44bef7 284 :risky t
44198b6e
CY
285 :group 'package
286 :version "24.1")
287
f56be016
SM
288(defvar package--default-summary "No description available.")
289
290(cl-defstruct (package-desc
291 ;; Rename the default constructor from `make-package-desc'.
292 (:constructor package-desc-create)
293 ;; Has the same interface as the old `define-package',
294 ;; which is still used in the "foo-pkg.el" files. Extra
295 ;; options can be supported by adding additional keys.
296 (:constructor
297 package-desc-from-define
298 (name-string version-string &optional summary requirements
9c959872 299 &key kind archive &allow-other-keys
f56be016
SM
300 &aux
301 (name (intern name-string))
302 (version (version-to-list version-string))
303 (reqs (mapcar #'(lambda (elt)
304 (list (car elt)
305 (version-to-list (cadr elt))))
306 (if (eq 'quote (car requirements))
307 (nth 1 requirements)
308 requirements))))))
309 "Structure containing information about an individual package.
f56be016
SM
310Slots:
311
12059709 312`name' Name of the package, as a symbol.
f56be016
SM
313
314`version' Version of the package, as a version list.
315
316`summary' Short description of the package, typically taken from
12059709 317 the first line of the file.
f56be016 318
12059709
SM
319`reqs' Requirements of the package. A list of (PACKAGE
320 VERSION-LIST) naming the dependent package and the minimum
321 required version.
f56be016 322
12059709
SM
323`kind' The distribution format of the package. Currently, it is
324 either `single' or `tar'.
f56be016
SM
325
326`archive' The name of the archive (as a string) whence this
12059709 327 package came.
1b8dff23 328
12059709
SM
329`dir' The directory where the package is installed (if installed),
330 `builtin' if it is built-in, or nil otherwise."
f56be016
SM
331 name
332 version
333 (summary package--default-summary)
334 reqs
335 kind
1b8dff23
SM
336 archive
337 dir)
338
339;; Pseudo fields.
fd846ab4 340(defun package-desc-full-name (pkg-desc)
1b8dff23
SM
341 (format "%s-%s"
342 (package-desc-name pkg-desc)
343 (package-version-join (package-desc-version pkg-desc))))
f56be016 344
fd846ab4
SM
345(defun package-desc-suffix (pkg-desc)
346 (pcase (package-desc-kind pkg-desc)
347 (`single ".el")
348 (`tar ".tar")
349 (kind (error "Unknown package kind: %s" kind))))
350
f56be016
SM
351;; Package descriptor format used in finder-inf.el and package--builtins.
352(cl-defstruct (package--bi-desc
353 (:constructor package-make-builtin (version summary))
354 (:type vector))
355 version
356 reqs
357 summary)
358
96ae4c8f
CY
359(defvar package--builtins nil
360 "Alist of built-in packages.
015eea59
CY
361The actual value is initialized by loading the library
362`finder-inf'; this is not done until it is needed, e.g. by the
363function `package-built-in-p'.
364
f56be016
SM
365Each element has the form (PKG . PACKAGE-BI-DESC), where PKG is a package
366name (a symbol) and DESC is a `package--bi-desc' structure.")
bc44bef7 367(put 'package--builtins 'risky-local-variable t)
44198b6e 368
96ae4c8f 369(defvar package-alist nil
44198b6e 370 "Alist of all packages available for activation.
a7d2d465
SM
371Each element has the form (PKG . DESCS), where PKG is a package
372name (a symbol) and DESCS is a non-empty list of `package-desc' structure,
373sorted by decreasing versions.
96ae4c8f
CY
374
375This variable is set automatically by `package-load-descriptor',
376called via `package-initialize'. To change which packages are
377loaded and/or activated, customize `package-load-list'.")
25322144 378(put 'package-alist 'risky-local-variable t)
44198b6e 379
96ae4c8f 380(defvar package-activated-list nil
66bd25ab 381 ;; FIXME: This should implicitly include all builtin packages.
44198b6e 382 "List of the names of currently activated packages.")
bc44bef7 383(put 'package-activated-list 'risky-local-variable t)
44198b6e 384
ba08b241
CY
385(defun package-version-join (vlist)
386 "Return the version string corresponding to the list VLIST.
387This is, approximately, the inverse of `version-to-list'.
388\(Actually, it returns only one of the possible inverses, since
389`version-to-list' is a many-to-one operation.)"
390 (if (null vlist)
391 ""
392 (let ((str-list (list "." (int-to-string (car vlist)))))
393 (dolist (num (cdr vlist))
394 (cond
395 ((>= num 0)
396 (push (int-to-string num) str-list)
397 (push "." str-list))
398 ((< num -3)
399 (error "Invalid version list `%s'" vlist))
400 (t
401 ;; pre, or beta, or alpha
402 (cond ((equal "." (car str-list))
403 (pop str-list))
404 ((not (string-match "[0-9]+" (car str-list)))
405 (error "Invalid version list `%s'" vlist)))
406 (push (cond ((= num -1) "pre")
407 ((= num -2) "beta")
408 ((= num -3) "alpha"))
409 str-list))))
410 (if (equal "." (car str-list))
411 (pop str-list))
412 (apply 'concat (nreverse str-list)))))
44198b6e 413
1b8dff23
SM
414(defun package-load-descriptor (pkg-dir)
415 "Load the description file in directory PKG-DIR."
416 (let ((pkg-file (expand-file-name (package--description-file pkg-dir)
417 pkg-dir)))
418 (when (file-exists-p pkg-file)
419 (with-temp-buffer
420 (insert-file-contents pkg-file)
1b8dff23 421 (goto-char (point-min))
b5bcaee5
DG
422 (let ((pkg-desc (package-process-define-package
423 (read (current-buffer)) pkg-file)))
fd846ab4
SM
424 (setf (package-desc-dir pkg-desc) pkg-dir)
425 pkg-desc)))))
44198b6e
CY
426
427(defun package-load-all-descriptors ()
428 "Load descriptors for installed Emacs Lisp packages.
429This looks for package subdirectories in `package-user-dir' and
430`package-directory-list'. The variable `package-load-list'
431controls which package subdirectories may be loaded.
432
433In each valid package subdirectory, this function loads the
434description file containing a call to `define-package', which
a7d2d465 435updates `package-alist'."
1b8dff23
SM
436 (dolist (dir (cons package-user-dir package-directory-list))
437 (when (file-directory-p dir)
438 (dolist (subdir (directory-files dir))
439 (let ((pkg-dir (expand-file-name subdir dir)))
440 (when (file-directory-p pkg-dir)
441 (package-load-descriptor pkg-dir)))))))
442
443(defun package-disabled-p (pkg-name version)
444 "Return whether PKG-NAME at VERSION can be activated.
445The decision is made according to `package-load-list'.
446Return nil if the package can be activated.
447Return t if the package is completely disabled.
448Return the max version (as a string) if the package is held at a lower version."
449 (let ((force (assq pkg-name package-load-list)))
450 (cond ((null force) (not (memq 'all package-load-list)))
451 ((null (setq force (cadr force))) t) ; disabled
452 ((eq force t) nil)
453 ((stringp force) ; held
454 (unless (version-list-= version (version-to-list force))
455 force))
456 (t (error "Invalid element in `package-load-list'")))))
cced7584 457
f56be016
SM
458(defun package-activate-1 (pkg-desc)
459 (let* ((name (package-desc-name pkg-desc))
2d69b99e
SM
460 (pkg-dir (package-desc-dir pkg-desc))
461 (pkg-dir-dir (file-name-as-directory pkg-dir)))
44198b6e 462 (unless pkg-dir
1b8dff23
SM
463 (error "Internal error: unable to find directory for `%s'"
464 (package-desc-full-name pkg-desc)))
2d69b99e
SM
465 ;; Add to load path, add autoloads, and activate the package.
466 (let ((old-lp load-path))
467 (load (expand-file-name (format "%s-autoloads" name) pkg-dir) nil t)
468 (when (and (eq old-lp load-path)
469 (not (or (member pkg-dir load-path)
470 (member pkg-dir-dir load-path))))
471 ;; Old packages don't add themselves to the `load-path', so we have to
472 ;; do it ourselves.
473 (push pkg-dir load-path)))
cced7584 474 ;; Add info node.
ebf662f4
CY
475 (when (file-exists-p (expand-file-name "dir" pkg-dir))
476 ;; FIXME: not the friendliest, but simple.
477 (require 'info)
478 (info-initialize)
479 (push pkg-dir Info-directory-list))
f56be016 480 (push name package-activated-list)
44198b6e
CY
481 ;; Don't return nil.
482 t))
483
7ede3b65
CY
484(defun package-built-in-p (package &optional min-version)
485 "Return true if PACKAGE is built-in to Emacs.
486Optional arg MIN-VERSION, if non-nil, should be a version list
487specifying the minimum acceptable version."
66bd25ab
SM
488 (let ((bi (assq package package--builtin-versions)))
489 (cond
490 (bi (version-list-<= min-version (cdr bi)))
491 (min-version nil)
492 (t
493 (require 'finder-inf nil t) ; For `package--builtins'.
494 (assq package package--builtins)))))
f56be016
SM
495
496(defun package--from-builtin (bi-desc)
497 (package-desc-create :name (pop bi-desc)
498 :version (package--bi-desc-version bi-desc)
12059709
SM
499 :summary (package--bi-desc-summary bi-desc)
500 :dir 'builtin))
44198b6e 501
4b99edf2
CY
502;; This function goes ahead and activates a newer version of a package
503;; if an older one was already activated. This is not ideal; we'd at
504;; least need to check to see if the package has actually been loaded,
505;; and not merely activated.
a7d2d465
SM
506(defun package-activate (package &optional force)
507 "Activate package PACKAGE.
508If FORCE is true, (re-)activate it if it's already activated."
509 (let ((pkg-descs (cdr (assq package package-alist))))
4b99edf2 510 ;; Check if PACKAGE is available in `package-alist'.
a7d2d465
SM
511 (while
512 (when pkg-descs
513 (let ((available-version (package-desc-version (car pkg-descs))))
514 (or (package-disabled-p package available-version)
515 ;; Prefer a builtin package.
516 (package-built-in-p package available-version))))
517 (setq pkg-descs (cdr pkg-descs)))
4b99edf2
CY
518 (cond
519 ;; If no such package is found, maybe it's built-in.
a7d2d465
SM
520 ((null pkg-descs)
521 (package-built-in-p package))
4b99edf2 522 ;; If the package is already activated, just return t.
a7d2d465 523 ((and (memq package package-activated-list) (not force))
4b99edf2
CY
524 t)
525 ;; Otherwise, proceed with activation.
526 (t
a7d2d465
SM
527 (let* ((pkg-vec (car pkg-descs))
528 (fail (catch 'dep-failure
529 ;; Activate its dependencies recursively.
530 (dolist (req (package-desc-reqs pkg-vec))
531 (unless (package-activate (car req) (cadr req))
532 (throw 'dep-failure req))))))
4b99edf2
CY
533 (if fail
534 (warn "Unable to activate package `%s'.
015eea59 535Required package `%s-%s' is unavailable"
4b99edf2
CY
536 package (car fail) (package-version-join (cadr fail)))
537 ;; If all goes well, activate the package itself.
f56be016 538 (package-activate-1 pkg-vec)))))))
44198b6e 539
fd846ab4
SM
540(defun define-package (_name-string _version-string
541 &optional _docstring _requirements
542 &rest _extra-properties)
44198b6e 543 "Define a new package.
4b99edf2 544NAME-STRING is the name of the package, as a string.
7ede3b65 545VERSION-STRING is the version of the package, as a string.
4b99edf2
CY
546DOCSTRING is a short description of the package, a string.
547REQUIREMENTS is a list of dependencies on other packages.
7ede3b65
CY
548 Each requirement is of the form (OTHER-PACKAGE OTHER-VERSION),
549 where OTHER-VERSION is a string.
187d3296
CY
550
551EXTRA-PROPERTIES is currently unused."
1b8dff23
SM
552 ;; FIXME: Placeholder! Should we keep it?
553 (error "Don't call me!"))
554
555(defun package-process-define-package (exp origin)
556 (unless (eq (car-safe exp) 'define-package)
557 (error "Can't find define-package in %s" origin))
558 (let* ((new-pkg-desc (apply #'package-desc-from-define (cdr exp)))
559 (name (package-desc-name new-pkg-desc))
560 (version (package-desc-version new-pkg-desc))
a7d2d465
SM
561 (old-pkgs (assq name package-alist)))
562 (if (null old-pkgs)
563 ;; If there's no old package, just add this to `package-alist'.
564 (push (list name new-pkg-desc) package-alist)
565 ;; If there is, insert the new package at the right place in the list.
5b165ade
SM
566 (while
567 (if (and (cdr old-pkgs)
568 (version-list-< version
569 (package-desc-version (cadr old-pkgs))))
570 (setq old-pkgs (cdr old-pkgs))
571 (push new-pkg-desc (cdr old-pkgs))
572 nil)))
1b8dff23 573 new-pkg-desc))
44198b6e 574
fd846ab4 575;; From Emacs 22, but changed so it adds to load-path.
44198b6e
CY
576(defun package-autoload-ensure-default-file (file)
577 "Make sure that the autoload file FILE exists and if not create it."
578 (unless (file-exists-p file)
579 (write-region
580 (concat ";;; " (file-name-nondirectory file)
581 " --- automatically extracted autoloads\n"
582 ";;\n"
4fac34ce
SM
583 ";;; Code:\n"
584 "(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))\n"
44198b6e
CY
585 "\f\n;; Local Variables:\n"
586 ";; version-control: never\n"
587 ";; no-byte-compile: t\n"
588 ";; no-update-autoloads: t\n"
589 ";; End:\n"
590 ";;; " (file-name-nondirectory file)
591 " ends here\n")
592 nil file))
593 file)
594
12059709
SM
595(defvar generated-autoload-file)
596(defvar version-control)
597
44198b6e 598(defun package-generate-autoloads (name pkg-dir)
9a70f03d 599 (require 'autoload) ;Load before we let-bind generated-autoload-file!
f56be016 600 (let* ((auto-name (format "%s-autoloads.el" name))
4d6769e1 601 ;;(ignore-name (concat name "-pkg.el"))
44198b6e
CY
602 (generated-autoload-file (expand-file-name auto-name pkg-dir))
603 (version-control 'never))
4fac34ce 604 (package-autoload-ensure-default-file generated-autoload-file)
cd44022c
DH
605 (update-directory-autoloads pkg-dir)
606 (let ((buf (find-buffer-visiting generated-autoload-file)))
f56be016
SM
607 (when buf (kill-buffer buf)))
608 auto-name))
44198b6e 609
4525ce3e
CY
610(defvar tar-parse-info)
611(declare-function tar-untar-buffer "tar-mode" ())
f20def1f
GM
612(declare-function tar-header-name "tar-mode" (tar-header) t)
613(declare-function tar-header-link-type "tar-mode" (tar-header) t)
4525ce3e
CY
614
615(defun package-untar-buffer (dir)
44198b6e 616 "Untar the current buffer.
4525ce3e
CY
617This uses `tar-untar-buffer' from Tar mode. All files should
618untar into a directory named DIR; otherwise, signal an error."
44198b6e 619 (require 'tar-mode)
4525ce3e
CY
620 (tar-mode)
621 ;; Make sure everything extracts into DIR.
3c94d7a6
CY
622 (let ((regexp (concat "\\`" (regexp-quote (expand-file-name dir)) "/"))
623 (case-fold-search (memq system-type '(windows-nt ms-dos cygwin))))
4525ce3e 624 (dolist (tar-data tar-parse-info)
3c94d7a6
CY
625 (let ((name (expand-file-name (tar-header-name tar-data))))
626 (or (string-match regexp name)
627 ;; Tarballs created by some utilities don't list
628 ;; directories with a trailing slash (Bug#13136).
629 (and (string-equal dir name)
630 (eq (tar-header-link-type tar-data) 5))
631 (error "Package does not untar cleanly into directory %s/" dir)))))
4525ce3e 632 (tar-untar-buffer))
44198b6e 633
fd846ab4
SM
634(defun package-generate-description-file (pkg-desc pkg-dir)
635 "Create the foo-pkg.el file for single-file packages."
636 (let* ((name (package-desc-name pkg-desc))
637 (pkg-file (expand-file-name (package--description-file pkg-dir)
638 pkg-dir)))
639 (let ((print-level nil)
640 (print-quoted t)
641 (print-length nil))
642 (write-region
643 (concat
644 (prin1-to-string
645 (list 'define-package
646 (symbol-name name)
647 (package-version-join (package-desc-version pkg-desc))
648 (package-desc-summary pkg-desc)
649 (let ((requires (package-desc-reqs pkg-desc)))
650 (list 'quote
651 ;; Turn version lists into string form.
652 (mapcar
653 (lambda (elt)
654 (list (car elt)
655 (package-version-join (cadr elt))))
656 requires)))))
657 "\n")
658 nil
659 pkg-file))))
660
661(defun package-unpack (pkg-desc)
662 "Install the contents of the current buffer as a package."
663 (let* ((name (package-desc-name pkg-desc))
664 (dirname (package-desc-full-name pkg-desc))
4525ce3e 665 (pkg-dir (expand-file-name dirname package-user-dir)))
fd846ab4
SM
666 (pcase (package-desc-kind pkg-desc)
667 (`tar
668 (make-directory package-user-dir t)
669 ;; FIXME: should we delete PKG-DIR if it exists?
670 (let* ((default-directory (file-name-as-directory package-user-dir)))
671 (package-untar-buffer dirname)))
672 (`single
673 (let ((el-file (expand-file-name (format "%s.el" name) pkg-dir)))
674 (make-directory pkg-dir t)
675 (package--write-file-no-coding el-file)))
676 (kind (error "Unknown package kind: %S" kind)))
677 (package--make-autoloads-and-stuff pkg-desc pkg-dir)
678 ;; Update package-alist.
679 (let ((new-desc (package-load-descriptor pkg-dir)))
680 ;; FIXME: Check that `new-desc' matches `desc'!
681 ;; FIXME: Compilation should be done as a separate, optional, step.
682 ;; E.g. for multi-package installs, we should first install all packages
683 ;; and then compile them.
684 (package--compile new-desc))
685 ;; Try to activate it.
a7d2d465 686 (package-activate name 'force)
fd846ab4
SM
687 pkg-dir))
688
689(defun package--make-autoloads-and-stuff (pkg-desc pkg-dir)
690 "Generate autoloads, description file, etc.. for PKG-DESC installed at PKG-DIR."
691 (package-generate-autoloads (package-desc-name pkg-desc) pkg-dir)
692 (let ((desc-file (package--description-file pkg-dir)))
693 (unless (file-exists-p desc-file)
694 (package-generate-description-file pkg-desc pkg-dir)))
695 ;; FIXME: Create foo.info and dir file from foo.texi?
696 )
697
698(defun package--compile (pkg-desc)
699 "Byte-compile installed package PKG-DESC."
700 (package-activate-1 pkg-desc)
701 (byte-recompile-directory (package-desc-dir pkg-desc) 0 t))
44198b6e 702
c6affbde 703(defun package--write-file-no-coding (file-name)
bc44bef7 704 (let ((buffer-file-coding-system 'no-conversion))
c6affbde 705 (write-region (point-min) (point-max) file-name)))
bc44bef7 706
f561e49a
CY
707(defmacro package--with-work-buffer (location file &rest body)
708 "Run BODY in a buffer containing the contents of FILE at LOCATION.
709LOCATION is the base location of a package archive, and should be
710one of the URLs (or file names) specified in `package-archives'.
711FILE is the name of a file relative to that base location.
712
713This macro retrieves FILE from LOCATION into a temporary buffer,
714and evaluates BODY while that buffer is current. This work
715buffer is killed afterwards. Return the last value in BODY."
fd846ab4 716 (declare (indent 2) (debug t))
da91b5f2 717 `(let* ((http (string-match "\\`https?:" ,location))
f561e49a
CY
718 (buffer
719 (if http
720 (url-retrieve-synchronously (concat ,location ,file))
721 (generate-new-buffer "*package work buffer*"))))
722 (prog1
723 (with-current-buffer buffer
724 (if http
725 (progn (package-handle-response)
726 (re-search-forward "^$" nil 'move)
727 (forward-char)
728 (delete-region (point-min) (point)))
729 (unless (file-name-absolute-p ,location)
730 (error "Archive location %s is not an absolute file name"
731 ,location))
732 (insert-file-contents (expand-file-name ,file ,location)))
733 ,@body)
734 (kill-buffer buffer))))
735
44198b6e 736(defun package-handle-response ()
f561e49a 737 "Handle the response from a `url-retrieve-synchronously' call.
44198b6e
CY
738Parse the HTTP response and throw if an error occurred.
739The url package seems to require extra processing for this.
740This should be called in a `save-excursion', in the download buffer.
741It will move point to somewhere in the headers."
742 ;; We assume HTTP here.
743 (require 'url-http)
744 (let ((response (url-http-parse-response)))
745 (when (or (< response 200) (>= response 300))
44198b6e 746 (error "Error during download request:%s"
66bd25ab 747 (buffer-substring-no-properties (point) (line-end-position))))))
44198b6e 748
fd846ab4 749(defun package-install-from-archive (pkg-desc)
44198b6e 750 "Download and install a tar package."
fd846ab4
SM
751 (let ((location (package-archive-base pkg-desc))
752 (file (concat (package-desc-full-name pkg-desc)
753 (package-desc-suffix pkg-desc))))
f561e49a 754 (package--with-work-buffer location file
fd846ab4 755 (package-unpack pkg-desc))))
44198b6e 756
1ead7dbd
SM
757(defvar package--initialized nil)
758
bc44bef7 759(defun package-installed-p (package &optional min-version)
7ede3b65
CY
760 "Return true if PACKAGE, of MIN-VERSION or newer, is installed.
761MIN-VERSION should be a version list."
a7723be6 762 (unless package--initialized (error "package.el is not yet initialized!"))
a7d2d465
SM
763 (or
764 (let ((pkg-descs (cdr (assq package package-alist))))
765 (and pkg-descs
766 (version-list-<= min-version
767 (package-desc-version (car pkg-descs)))))
768 ;; Also check built-in packages.
769 (package-built-in-p package min-version)))
44198b6e 770
12059709
SM
771(defun package-compute-transaction (packages requirements)
772 "Return a list of packages to be installed, including PACKAGES.
773PACKAGES should be a list of `package-desc'.
96ae4c8f
CY
774
775REQUIREMENTS should be a list of additional requirements; each
7ede3b65
CY
776element in this list should have the form (PACKAGE VERSION-LIST),
777where PACKAGE is a package name and VERSION-LIST is the required
778version of that package.
96ae4c8f
CY
779
780This function recursively computes the requirements of the
781packages in REQUIREMENTS, and returns a list of all the packages
782that must be installed. Packages that are already installed are
783not included in this list."
12059709
SM
784 ;; FIXME: We really should use backtracking to explore the whole
785 ;; search space (e.g. if foo require bar-1.3, and bar-1.4 requires toto-1.1
786 ;; whereas bar-1.3 requires toto-1.0 and the user has put a hold on toto-1.0:
787 ;; the current code might fail to see that it could install foo by using the
788 ;; older bar-1.3).
44198b6e
CY
789 (dolist (elt requirements)
790 (let* ((next-pkg (car elt))
12059709
SM
791 (next-version (cadr elt))
792 (already ()))
793 (dolist (pkg packages)
794 (if (eq next-pkg (package-desc-name pkg))
795 (setq already pkg)))
796 (cond
797 (already
798 (if (version-list-< next-version (package-desc-version already))
799 ;; Move to front, so it gets installed early enough (bug#14082).
800 (setq packages (cons already (delq already packages)))
801 (error "Need package `%s-%s', but only %s is available"
802 next-pkg (package-version-join next-version)
803 (package-version-join (package-desc-version already)))))
804
805 ((package-installed-p next-pkg next-version) nil)
806
807 (t
44198b6e
CY
808 ;; A package is required, but not installed. It might also be
809 ;; blocked via `package-load-list'.
12059709
SM
810 (let ((pkg-descs (cdr (assq next-pkg package-archive-contents)))
811 (found nil)
812 (problem nil))
813 (while (and pkg-descs (not found))
814 (let* ((pkg-desc (pop pkg-descs))
815 (version (package-desc-version pkg-desc))
816 (disabled (package-disabled-p next-pkg version)))
817 (cond
818 ((version-list-< version next-version)
819 (error
820 "Need package `%s-%s', but only %s is available"
821 next-pkg (package-version-join next-version)
822 (package-version-join version)))
823 (disabled
824 (unless problem
825 (setq problem
826 (if (stringp disabled)
827 (format "Package `%s' held at version %s, \
44198b6e 828but version %s required"
12059709
SM
829 next-pkg disabled
830 (package-version-join next-version))
831 (format "Required package '%s' is disabled"
832 next-pkg)))))
833 (t (setq found pkg-desc)))))
834 (unless found
835 (if problem
836 (error problem)
837 (error "Package `%s-%s' is unavailable"
838 next-pkg (package-version-join next-version))))
839 (setq packages
840 (package-compute-transaction (cons found packages)
841 (package-desc-reqs found))))))))
842 packages)
44198b6e
CY
843
844(defun package-read-from-string (str)
845 "Read a Lisp expression from STR.
846Signal an error if the entire string was not used."
847 (let* ((read-data (read-from-string str))
187d3296
CY
848 (more-left
849 (condition-case nil
850 ;; The call to `ignore' suppresses a compiler warning.
851 (progn (ignore (read-from-string
852 (substring str (cdr read-data))))
853 t)
854 (end-of-file nil))))
44198b6e
CY
855 (if more-left
856 (error "Can't read whole string")
857 (car read-data))))
858
859(defun package--read-archive-file (file)
860 "Re-read archive file FILE, if it exists.
861Will return the data from the file, or nil if the file does not exist.
862Will throw an error if the archive version is too new."
863 (let ((filename (expand-file-name file package-user-dir)))
187d3296
CY
864 (when (file-exists-p filename)
865 (with-temp-buffer
866 (insert-file-contents-literally filename)
867 (let ((contents (read (current-buffer))))
868 (if (> (car contents) package-archive-version)
869 (error "Package archive version %d is higher than %d"
870 (car contents) package-archive-version))
871 (cdr contents))))))
44198b6e 872
bc44bef7 873(defun package-read-all-archive-contents ()
96ae4c8f
CY
874 "Re-read `archive-contents', if it exists.
875If successful, set `package-archive-contents'."
fbe3be3f 876 (setq package-archive-contents nil)
bc44bef7 877 (dolist (archive package-archives)
96ae4c8f 878 (package-read-archive-contents (car archive))))
44198b6e 879
bc44bef7 880(defun package-read-archive-contents (archive)
187d3296
CY
881 "Re-read archive contents for ARCHIVE.
882If successful, set the variable `package-archive-contents'.
bc44bef7 883If the archive version is too new, signal an error."
187d3296
CY
884 ;; Version 1 of 'archive-contents' is identical to our internal
885 ;; representation.
66bd25ab
SM
886 (let* ((contents-file (format "archives/%s/archive-contents" archive))
887 (contents (package--read-archive-file contents-file)))
888 (when contents
187d3296
CY
889 (dolist (package contents)
890 (package--add-to-archive-contents package archive)))))
bc44bef7 891
f56be016
SM
892;; Package descriptor objects used inside the "archive-contents" file.
893;; Changing this defstruct implies changing the format of the
894;; "archive-contents" files.
895(cl-defstruct (package--ac-desc
896 (:constructor package-make-ac-desc (version reqs summary kind))
897 (:copier nil)
898 (:type vector))
899 version reqs summary kind)
900
bc44bef7
PH
901(defun package--add-to-archive-contents (package archive)
902 "Add the PACKAGE from the given ARCHIVE if necessary.
f56be016
SM
903PACKAGE should have the form (NAME . PACKAGE--AC-DESC).
904Also, add the originating archive to the `package-desc' structure."
905 (let* ((name (car package))
66bd25ab 906 (version (package--ac-desc-version (cdr package)))
f56be016
SM
907 (pkg-desc
908 (package-desc-create
909 :name name
66bd25ab 910 :version version
f56be016
SM
911 :reqs (package--ac-desc-reqs (cdr package))
912 :summary (package--ac-desc-summary (cdr package))
913 :kind (package--ac-desc-kind (cdr package))
914 :archive archive))
12059709 915 (existing-packages (assq name package-archive-contents))
397703b4 916 (pinned-to-archive (assoc name package-pinned-packages)))
66bd25ab 917 (cond
12059709 918 ;; Skip entirely if pinned to another archive or already installed.
66bd25ab
SM
919 ((or (and pinned-to-archive
920 (not (equal (cdr pinned-to-archive) archive)))
921 (let ((bi (assq name package--builtin-versions)))
12059709 922 (and bi (version-list-= version (cdr bi))))
66bd25ab 923 (let ((ins (cdr (assq name package-alist))))
12059709
SM
924 (and ins (version-list-= version
925 (package-desc-version (car ins))))))
66bd25ab 926 nil)
12059709
SM
927 ((not existing-packages)
928 (push (list name pkg-desc) package-archive-contents))
929 (t
930 (while
931 (if (and (cdr existing-packages)
932 (version-list-<
933 version (package-desc-version (cadr existing-packages))))
934 (setq existing-packages (cdr existing-packages))
a49ff80c
SM
935 (push pkg-desc (cdr existing-packages))
936 nil))))))
12059709
SM
937
938(defun package-download-transaction (packages)
939 "Download and install all the packages in PACKAGES.
940PACKAGES should be a list of package-desc.
96ae4c8f 941This function assumes that all package requirements in
12059709 942PACKAGES are satisfied, i.e. that PACKAGES is computed
96ae4c8f 943using `package-compute-transaction'."
12059709 944 (mapc #'package-install-from-archive packages))
44198b6e
CY
945
946;;;###autoload
5b165ade
SM
947(defun package-install (pkg)
948 "Install the package PKG.
949PKG can be a package-desc or the package name of one the available packages
950in an archive in `package-archives'. Interactively, prompt for its name."
44198b6e 951 (interactive
7254299e
CY
952 (progn
953 ;; Initialize the package system to get the list of package
954 ;; symbols for completion.
955 (unless package--initialized
956 (package-initialize t))
70550acf
PH
957 (unless package-archive-contents
958 (package-refresh-contents))
5b165ade 959 (list (intern (completing-read
12059709
SM
960 "Install package: "
961 (mapcar (lambda (elt) (symbol-name (car elt)))
962 package-archive-contents)
5b165ade 963 nil t)))))
1b8dff23 964 (package-download-transaction
12059709
SM
965 (if (package-desc-p pkg)
966 (package-compute-transaction (list pkg)
967 (package-desc-reqs pkg))
968 (package-compute-transaction ()
969 (list (list pkg))))))
44198b6e 970
ffbf300e
CY
971(defun package-strip-rcs-id (str)
972 "Strip RCS version ID from the version string STR.
44198b6e
CY
973If the result looks like a dotted numeric version, return it.
974Otherwise return nil."
ffbf300e
CY
975 (when str
976 (when (string-match "\\`[ \t]*[$]Revision:[ \t]+" str)
977 (setq str (substring str (match-end 0))))
978 (condition-case nil
979 (if (version-to-list str)
980 str)
981 (error nil))))
44198b6e
CY
982
983(defun package-buffer-info ()
f56be016 984 "Return a `package-desc' describing the package in the current buffer.
187d3296
CY
985
986If the buffer does not contain a conforming package, signal an
987error. If there is a package, narrow the buffer to the file's
988boundaries."
44198b6e 989 (goto-char (point-min))
f677562b 990 (unless (re-search-forward "^;;; \\([^ ]*\\)\\.el ---[ \t]*\\(.*?\\)[ \t]*\\(-\\*-.*-\\*-[ \t]*\\)?$" nil t)
d96ad422 991 (error "Package lacks a file header"))
187d3296
CY
992 (let ((file-name (match-string-no-properties 1))
993 (desc (match-string-no-properties 2))
994 (start (line-beginning-position)))
995 (unless (search-forward (concat ";;; " file-name ".el ends here"))
996 (error "Package lacks a terminating comment"))
997 ;; Try to include a trailing newline.
998 (forward-line)
999 (narrow-to-region start (point))
1000 (require 'lisp-mnt)
1001 ;; Use some headers we've invented to drive the process.
1002 (let* ((requires-str (lm-header "package-requires"))
187d3296
CY
1003 ;; Prefer Package-Version; if defined, the package author
1004 ;; probably wants us to use it. Otherwise try Version.
1005 (pkg-version
1006 (or (package-strip-rcs-id (lm-header "package-version"))
f56be016 1007 (package-strip-rcs-id (lm-header "version")))))
187d3296
CY
1008 (unless pkg-version
1009 (error
1010 "Package lacks a \"Version\" or \"Package-Version\" header"))
f56be016
SM
1011 (package-desc-from-define
1012 file-name pkg-version desc
1013 (if requires-str (package-read-from-string requires-str))
1014 :kind 'single))))
44198b6e 1015
9e277302
JB
1016(declare-function tar-get-file-descriptor "tar-mode" (file))
1017(declare-function tar--extract "tar-mode" (descriptor))
1018
fd846ab4 1019(defun package-tar-file-info ()
44198b6e 1020 "Find package information for a tar file.
fd846ab4
SM
1021The return result is a `package-desc'."
1022 (cl-assert (derived-mode-p 'tar-mode))
1023 (let* ((dir-name (file-name-directory
1024 (tar-header-name (car tar-parse-info))))
1b8dff23 1025 (desc-file (package--description-file dir-name))
fd846ab4
SM
1026 (tar-desc (tar-get-file-descriptor (concat dir-name desc-file))))
1027 (unless tar-desc
1028 (error "No package descriptor file found"))
1029 (with-current-buffer (tar--extract tar-desc)
1030 (goto-char (point-min))
1031 (unwind-protect
1032 (let* ((pkg-def-parsed (read (current-buffer)))
1033 (pkg-desc
1034 (if (not (eq (car pkg-def-parsed) 'define-package))
1035 (error "Can't find define-package in %s"
1036 (tar-header-name tar-desc))
1037 (apply #'package-desc-from-define
1038 (append (cdr pkg-def-parsed))))))
1039 (setf (package-desc-kind pkg-desc) 'tar)
1040 pkg-desc)
1041 (kill-buffer (current-buffer))))))
f56be016 1042
44198b6e 1043
187d3296 1044;;;###autoload
fd846ab4 1045(defun package-install-from-buffer ()
187d3296 1046 "Install a package from the current buffer.
fd846ab4
SM
1047The current buffer is assumed to be a single .el or .tar file that follows the
1048packaging guidelines; see info node `(elisp)Packaging'.
1049Downloads and installs required packages as needed."
1050 (interactive)
1051 (let ((pkg-desc (if (derived-mode-p 'tar-mode)
1052 (package-tar-file-info)
1053 (package-buffer-info))))
1054 ;; Download and install the dependencies.
1055 (let* ((requires (package-desc-reqs pkg-desc))
1056 (transaction (package-compute-transaction nil requires)))
1057 (package-download-transaction transaction))
1058 ;; Install the package itself.
1059 (package-unpack pkg-desc)
1060 pkg-desc))
44198b6e 1061
44198b6e
CY
1062;;;###autoload
1063(defun package-install-file (file)
1064 "Install a package from a file.
1065The file can either be a tar file or an Emacs Lisp file."
1066 (interactive "fPackage file name: ")
1067 (with-temp-buffer
1068 (insert-file-contents-literally file)
fd846ab4
SM
1069 (when (string-match "\\.tar\\'" file) (tar-mode))
1070 (package-install-from-buffer)))
44198b6e 1071
1b8dff23
SM
1072(defun package-delete (pkg-desc)
1073 (let ((dir (package-desc-dir pkg-desc)))
12059709
SM
1074 (if (not (string-prefix-p (file-name-as-directory
1075 (expand-file-name package-user-dir))
1076 (expand-file-name dir)))
1077 ;; Don't delete "system" packages.
1078 (error "Package `%s' is a system package, not deleting"
1079 (package-desc-full-name pkg-desc))
1080 (delete-directory dir t t)
1081 ;; Update package-alist.
1082 (let* ((name (package-desc-name pkg-desc)))
1083 (delete pkg-desc (assq name package-alist)))
1084 (message "Package `%s' deleted." (package-desc-full-name pkg-desc)))))
44198b6e 1085
fd846ab4 1086(defun package-archive-base (desc)
bc44bef7 1087 "Return the archive containing the package NAME."
fd846ab4 1088 (cdr (assoc (package-desc-archive desc) package-archives)))
bc44bef7
PH
1089
1090(defun package--download-one-archive (archive file)
f561e49a
CY
1091 "Retrieve an archive file FILE from ARCHIVE, and cache it.
1092ARCHIVE should be a cons cell of the form (NAME . LOCATION),
1093similar to an entry in `package-alist'. Save the cached copy to
1094\"archives/NAME/archive-contents\" in `package-user-dir'."
66bd25ab
SM
1095 (let* ((dir (expand-file-name (format "archives/%s" (car archive))
1096 package-user-dir)))
f561e49a 1097 (package--with-work-buffer (cdr archive) file
ebf662f4
CY
1098 ;; Read the retrieved buffer to make sure it is valid (e.g. it
1099 ;; may fetch a URL redirect page).
1100 (when (listp (read buffer))
1101 (make-directory dir t)
1102 (setq buffer-file-name (expand-file-name file dir))
1103 (let ((version-control 'never))
f561e49a 1104 (save-buffer))))))
44198b6e 1105
38bb2ca8 1106;;;###autoload
44198b6e
CY
1107(defun package-refresh-contents ()
1108 "Download the ELPA archive description if needed.
ebf662f4
CY
1109This informs Emacs about the latest versions of all packages, and
1110makes them available for download."
44198b6e 1111 (interactive)
5b165ade 1112 ;; FIXME: Do it asynchronously.
44198b6e
CY
1113 (unless (file-exists-p package-user-dir)
1114 (make-directory package-user-dir t))
bc44bef7 1115 (dolist (archive package-archives)
1be3ca5a 1116 (condition-case-unless-debug nil
cb6c4991 1117 (package--download-one-archive archive "archive-contents")
187d3296 1118 (error (message "Failed to download `%s' archive."
cb6c4991 1119 (car archive)))))
bc44bef7 1120 (package-read-all-archive-contents))
44198b6e
CY
1121
1122;;;###autoload
4b99edf2 1123(defun package-initialize (&optional no-activate)
44198b6e 1124 "Load Emacs Lisp packages, and activate them.
4b99edf2
CY
1125The variable `package-load-list' controls which packages to load.
1126If optional arg NO-ACTIVATE is non-nil, don't activate packages."
44198b6e 1127 (interactive)
a7d2d465 1128 (setq package-alist nil)
44198b6e 1129 (package-load-all-descriptors)
bc44bef7 1130 (package-read-all-archive-contents)
4b99edf2
CY
1131 (unless no-activate
1132 (dolist (elt package-alist)
a7d2d465 1133 (package-activate (car elt))))
4b99edf2 1134 (setq package--initialized t))
44198b6e
CY
1135
1136\f
cced7584 1137;;;; Package description buffer.
44198b6e 1138
cced7584
CY
1139;;;###autoload
1140(defun describe-package (package)
1141 "Display the full documentation of PACKAGE (a symbol)."
1142 (interactive
12059709 1143 (let* ((guess (function-called-at-point)))
4b99edf2
CY
1144 (require 'finder-inf nil t)
1145 ;; Load the package list if necessary (but don't activate them).
1146 (unless package--initialized
1147 (package-initialize t))
12059709
SM
1148 (let ((packages (append (mapcar 'car package-alist)
1149 (mapcar 'car package-archive-contents)
1150 (mapcar 'car package--builtins))))
1151 (unless (memq guess packages)
1152 (setq guess nil))
1153 (setq packages (mapcar 'symbol-name packages))
1154 (let ((val
1155 (completing-read (if guess
1156 (format "Describe package (default %s): "
1157 guess)
1158 "Describe package: ")
1159 packages nil t nil nil guess)))
1160 (list (intern val))))))
1161 (if (not (or (package-desc-p package) (and package (symbolp package))))
4b99edf2 1162 (message "No package specified")
cced7584
CY
1163 (help-setup-xref (list #'describe-package package)
1164 (called-interactively-p 'interactive))
1165 (with-help-window (help-buffer)
1166 (with-current-buffer standard-output
1167 (describe-package-1 package)))))
1168
12059709 1169(defun describe-package-1 (pkg)
96ae4c8f 1170 (require 'lisp-mnt)
12059709
SM
1171 (let* ((desc (or
1172 (if (package-desc-p pkg) pkg)
1173 (cadr (assq pkg package-alist))
1174 (let ((built-in (assq pkg package--builtins)))
1175 (if built-in
1176 (package--from-builtin built-in)
1177 (cadr (assq pkg package-archive-contents))))))
1178 (name (if desc (package-desc-name desc) pkg))
1179 (pkg-dir (if desc (package-desc-dir desc)))
1180 (reqs (if desc (package-desc-reqs desc)))
1181 (version (if desc (package-desc-version desc)))
1182 (archive (if desc (package-desc-archive desc)))
1183 (built-in (eq pkg-dir 'builtin))
1184 (installable (and archive (not built-in)))
1185 (status (if desc (package-desc-status desc) "orphan")))
1186 (prin1 name)
cced7584 1187 (princ " is ")
12059709
SM
1188 (princ (if (memq (aref status 0) '(?a ?e ?i ?o ?u)) "an " "a "))
1189 (princ status)
1190 (princ " package.\n\n")
cb6c4991 1191
96ae4c8f 1192 (insert " " (propertize "Status" 'font-lock-face 'bold) ": ")
12059709
SM
1193 (cond (built-in
1194 (insert (propertize (capitalize status)
1195 'font-lock-face 'font-lock-builtin-face)
1196 "."))
1197 (pkg-dir
1198 (insert (propertize (capitalize status) ;FIXME: Why comment-face?
96ae4c8f 1199 'font-lock-face 'font-lock-comment-face))
cb6c4991
CY
1200 (insert " in `")
1201 ;; Todo: Add button for uninstalling.
12059709
SM
1202 (help-insert-xref-button (abbreviate-file-name
1203 (file-name-as-directory pkg-dir))
cb6c4991 1204 'help-package-def pkg-dir)
12059709
SM
1205 (if (and (package-built-in-p name)
1206 (not (package-built-in-p name version)))
4b99edf2
CY
1207 (insert "',\n shadowing a "
1208 (propertize "built-in package"
1209 'font-lock-face 'font-lock-builtin-face)
1210 ".")
1211 (insert "'.")))
cb6c4991 1212 (installable
12059709
SM
1213 (insert (capitalize status))
1214 (insert " from " (format "%s" archive))
55b056ba 1215 (insert " -- ")
4b99edf2 1216 (let ((button-text (if (display-graphic-p) "Install" "[Install]"))
cb6c4991
CY
1217 (button-face (if (display-graphic-p)
1218 '(:box (:line-width 2 :color "dark grey")
1219 :background "light grey"
1220 :foreground "black")
1221 'link)))
4b99edf2 1222 (insert-text-button button-text 'face button-face 'follow-link t
1b8dff23 1223 'package-desc desc
cb6c4991 1224 'action 'package-install-button-action)))
12059709 1225 (t (insert (capitalize status) ".")))
cb6c4991 1226 (insert "\n")
12059709 1227 (and version
96ae4c8f 1228 (insert " "
12059709
SM
1229 (propertize "Version" 'font-lock-face 'bold) ": "
1230 (package-version-join version) "\n"))
4b99edf2
CY
1231
1232 (setq reqs (if desc (package-desc-reqs desc)))
8adb4c33 1233 (when reqs
96ae4c8f 1234 (insert " " (propertize "Requires" 'font-lock-face 'bold) ": ")
8adb4c33
CY
1235 (let ((first t)
1236 name vers text)
1237 (dolist (req reqs)
1238 (setq name (car req)
1239 vers (cadr req)
1240 text (format "%s-%s" (symbol-name name)
1241 (package-version-join vers)))
1242 (cond (first (setq first nil))
1243 ((>= (+ 2 (current-column) (length text))
1244 (window-width))
1245 (insert ",\n "))
1246 (t (insert ", ")))
1247 (help-insert-xref-button text 'help-package name))
1248 (insert "\n")))
96ae4c8f 1249 (insert " " (propertize "Summary" 'font-lock-face 'bold)
12059709
SM
1250 ": " (if desc (package-desc-summary desc)) "\n")
1251
1252 (let* ((all-pkgs (append (cdr (assq name package-alist))
1253 (cdr (assq name package-archive-contents))
1254 (let ((bi (assq name package--builtins)))
1255 (if bi (list (package--from-builtin bi))))))
1256 (other-pkgs (delete desc all-pkgs)))
1257 (when other-pkgs
1258 (insert " " (propertize "Other versions" 'font-lock-face 'bold) ": "
1259 (mapconcat
1260 (lambda (opkg)
1261 (let* ((ov (package-desc-version opkg))
1262 (dir (package-desc-dir opkg))
1263 (from (or (package-desc-archive opkg)
1264 (if (stringp dir) "installed" dir))))
1265 (if (not ov) (format "%s" from)
1266 (format "%s (%s)"
1267 (make-text-button (package-version-join ov) nil
1268 'face 'link
1269 'follow-link t
1270 'action
1271 (lambda (_button)
1272 (describe-package opkg)))
1273 from))))
1274 other-pkgs ", ")
1275 ".\n")))
1276
1277 (insert "\n")
cb6c4991 1278
4b99edf2 1279 (if built-in
96ae4c8f 1280 ;; For built-in packages, insert the commentary.
12059709 1281 (let ((fn (locate-file (format "%s.el" name) load-path
96ae4c8f
CY
1282 load-file-rep-suffixes))
1283 (opoint (point)))
1284 (insert (or (lm-commentary fn) ""))
1285 (save-excursion
1286 (goto-char opoint)
1287 (when (re-search-forward "^;;; Commentary:\n" nil t)
1288 (replace-match ""))
1289 (while (re-search-forward "^\\(;+ ?\\)" nil t)
1290 (replace-match ""))))
12059709 1291 (let ((readme (expand-file-name (format "%s-readme.txt" name)
f561e49a
CY
1292 package-user-dir))
1293 readme-string)
96ae4c8f
CY
1294 ;; For elpa packages, try downloading the commentary. If that
1295 ;; fails, try an existing readme file in `package-user-dir'.
f561e49a 1296 (cond ((condition-case nil
12059709
SM
1297 (package--with-work-buffer
1298 (package-archive-base desc)
1299 (format "%s-readme.txt" name)
f561e49a
CY
1300 (setq buffer-file-name
1301 (expand-file-name readme package-user-dir))
1302 (let ((version-control 'never))
1303 (save-buffer))
1304 (setq readme-string (buffer-string))
1305 t)
1306 (error nil))
1307 (insert readme-string))
96ae4c8f
CY
1308 ((file-readable-p readme)
1309 (insert-file-contents readme)
1310 (goto-char (point-max))))))))
cb6c4991
CY
1311
1312(defun package-install-button-action (button)
1b8dff23
SM
1313 (let ((pkg-desc (button-get button 'package-desc)))
1314 (when (y-or-n-p (format "Install package `%s'? "
1315 (package-desc-full-name pkg-desc)))
1316 (package-install pkg-desc)
cb6c4991
CY
1317 (revert-buffer nil t)
1318 (goto-char (point-min)))))
cced7584
CY
1319
1320\f
44198b6e
CY
1321;;;; Package menu mode.
1322
54ea2a0d 1323(defvar package-menu-mode-map
e91a96fe 1324 (let ((map (make-sparse-keymap))
64eba874 1325 (menu-map (make-sparse-keymap "Package")))
e91a96fe 1326 (set-keymap-parent map tabulated-list-mode-map)
8adb4c33 1327 (define-key map "\C-m" 'package-menu-describe-package)
54ea2a0d
JB
1328 (define-key map "u" 'package-menu-mark-unmark)
1329 (define-key map "\177" 'package-menu-backup-unmark)
1330 (define-key map "d" 'package-menu-mark-delete)
1331 (define-key map "i" 'package-menu-mark-install)
25322144 1332 (define-key map "U" 'package-menu-mark-upgrades)
54ea2a0d
JB
1333 (define-key map "r" 'package-menu-refresh)
1334 (define-key map "~" 'package-menu-mark-obsolete-for-deletion)
1335 (define-key map "x" 'package-menu-execute)
1336 (define-key map "h" 'package-menu-quick-help)
cb6c4991 1337 (define-key map "?" 'package-menu-describe-package)
64eba874
DN
1338 (define-key map [menu-bar package-menu] (cons "Package" menu-map))
1339 (define-key menu-map [mq]
1340 '(menu-item "Quit" quit-window
1341 :help "Quit package selection"))
1342 (define-key menu-map [s1] '("--"))
1343 (define-key menu-map [mn]
1344 '(menu-item "Next" next-line
1345 :help "Next Line"))
1346 (define-key menu-map [mp]
1347 '(menu-item "Previous" previous-line
1348 :help "Previous Line"))
1349 (define-key menu-map [s2] '("--"))
1350 (define-key menu-map [mu]
1351 '(menu-item "Unmark" package-menu-mark-unmark
1352 :help "Clear any marks on a package and move to the next line"))
1353 (define-key menu-map [munm]
7cc6e154 1354 '(menu-item "Unmark Backwards" package-menu-backup-unmark
64eba874
DN
1355 :help "Back up one line and clear any marks on that package"))
1356 (define-key menu-map [md]
7cc6e154 1357 '(menu-item "Mark for Deletion" package-menu-mark-delete
64eba874
DN
1358 :help "Mark a package for deletion and move to the next line"))
1359 (define-key menu-map [mi]
7cc6e154 1360 '(menu-item "Mark for Install" package-menu-mark-install
64eba874 1361 :help "Mark a package for installation and move to the next line"))
d770725a 1362 (define-key menu-map [mupgrades]
7cc6e154 1363 '(menu-item "Mark Upgradable Packages" package-menu-mark-upgrades
d770725a 1364 :help "Mark packages that have a newer version for upgrading"))
64eba874
DN
1365 (define-key menu-map [s3] '("--"))
1366 (define-key menu-map [mg]
7cc6e154 1367 '(menu-item "Update Package List" revert-buffer
64eba874
DN
1368 :help "Update the list of packages"))
1369 (define-key menu-map [mr]
7cc6e154 1370 '(menu-item "Refresh Package List" package-menu-refresh
64eba874
DN
1371 :help "Download the ELPA archive"))
1372 (define-key menu-map [s4] '("--"))
1373 (define-key menu-map [mt]
7cc6e154 1374 '(menu-item "Mark Obsolete Packages" package-menu-mark-obsolete-for-deletion
64eba874
DN
1375 :help "Mark all obsolete packages for deletion"))
1376 (define-key menu-map [mx]
7cc6e154 1377 '(menu-item "Execute Actions" package-menu-execute
64eba874
DN
1378 :help "Perform all the marked actions"))
1379 (define-key menu-map [s5] '("--"))
1380 (define-key menu-map [mh]
1381 '(menu-item "Help" package-menu-quick-help
1382 :help "Show short key binding help for package-menu-mode"))
1383 (define-key menu-map [mc]
1384 '(menu-item "View Commentary" package-menu-view-commentary
1385 :help "Display information about this package"))
54ea2a0d 1386 map)
44198b6e
CY
1387 "Local keymap for `package-menu-mode' buffers.")
1388
60057926
CY
1389(defvar package-menu--new-package-list nil
1390 "List of newly-available packages since `list-packages' was last called.")
1391
e91a96fe 1392(define-derived-mode package-menu-mode tabulated-list-mode "Package Menu"
44198b6e
CY
1393 "Major mode for browsing a list of packages.
1394Letters do not insert themselves; instead, they are commands.
1395\\<package-menu-mode-map>
1396\\{package-menu-mode-map}"
e91a96fe
CY
1397 (setq tabulated-list-format [("Package" 18 package-menu--name-predicate)
1398 ("Version" 12 nil)
1399 ("Status" 10 package-menu--status-predicate)
1400 ("Description" 0 nil)])
1401 (setq tabulated-list-padding 2)
1402 (setq tabulated-list-sort-key (cons "Status" nil))
6874724a 1403 (add-hook 'tabulated-list-revert-hook 'package-menu--refresh nil t)
e91a96fe
CY
1404 (tabulated-list-init-header))
1405
1b8dff23 1406(defmacro package--push (pkg-desc status listname)
e91a96fe
CY
1407 "Convenience macro for `package-menu--generate'.
1408If the alist stored in the symbol LISTNAME lacks an entry for a
1b8dff23
SM
1409package PKG-DESC, add one. The alist is keyed with PKG-DESC."
1410 `(unless (assoc ,pkg-desc ,listname)
1411 ;; FIXME: Should we move status into pkg-desc?
1412 (push (cons ,pkg-desc ,status) ,listname)))
e91a96fe 1413
66bd25ab
SM
1414(defvar package-list-unversioned nil
1415 "If non-nil include packages that don't have a version in `list-package'.")
1416
12059709
SM
1417(defun package-desc-status (pkg-desc)
1418 (let* ((name (package-desc-name pkg-desc))
1419 (dir (package-desc-dir pkg-desc))
1420 (lle (assq name package-load-list))
1421 (held (cadr lle))
1422 (version (package-desc-version pkg-desc)))
1423 (cond
1424 ((eq dir 'builtin) "built-in")
1425 ((and lle (null held)) "disabled")
1426 ((stringp held)
1427 (let ((hv (if (stringp held) (version-to-list held))))
1428 (cond
1429 ((version-list-= version hv) "held")
1430 ((version-list-< version hv) "obsolete")
1431 (t "disabled"))))
1432 ((package-built-in-p name version) "obsolete")
1433 (dir ;One of the installed packages.
1434 (cond
1435 ((not (file-exists-p (package-desc-dir pkg-desc))) "deleted")
1436 ((eq pkg-desc (cadr (assq name package-alist))) "installed")
1437 (t "obsolete")))
1438 (t
1439 (let* ((ins (cadr (assq name package-alist)))
1440 (ins-v (if ins (package-desc-version ins))))
1441 (cond
1442 ((or (null ins) (version-list-< ins-v version))
1443 (if (memq name package-menu--new-package-list)
1444 "new" "available"))
1445 ((version-list-< version ins-v) "obsolete")
1446 ((version-list-= version ins-v) "installed")))))))
1447
1448(defun package-menu--refresh (&optional packages)
1449 "Re-populate the `tabulated-list-entries'.
1450PACKAGES should be nil or t, which means to display all known packages."
1b8dff23 1451 ;; Construct list of (PKG-DESC . STATUS).
12059709 1452 (unless packages (setq packages t))
4d6769e1 1453 (let (info-list name)
e91a96fe
CY
1454 ;; Installed packages:
1455 (dolist (elt package-alist)
1456 (setq name (car elt))
512e3ae1 1457 (when (or (eq packages t) (memq name packages))
12059709
SM
1458 (dolist (pkg (cdr elt))
1459 (package--push pkg (package-desc-status pkg) info-list))))
e91a96fe
CY
1460
1461 ;; Built-in packages:
1462 (dolist (elt package--builtins)
1463 (setq name (car elt))
512e3ae1 1464 (when (and (not (eq name 'emacs)) ; Hide the `emacs' package.
66bd25ab
SM
1465 (or package-list-unversioned
1466 (package--bi-desc-version (cdr elt)))
512e3ae1 1467 (or (eq packages t) (memq name packages)))
1b8dff23 1468 (package--push (package--from-builtin elt) "built-in" info-list)))
e91a96fe
CY
1469
1470 ;; Available and disabled packages:
1471 (dolist (elt package-archive-contents)
1472 (setq name (car elt))
512e3ae1 1473 (when (or (eq packages t) (memq name packages))
12059709
SM
1474 (dolist (pkg (cdr elt))
1475 ;; Hide obsolete packages.
1476 (unless (package-installed-p (package-desc-name pkg)
1477 (package-desc-version pkg))
1478 (package--push pkg (package-desc-status pkg) info-list)))))
e91a96fe 1479
e91a96fe 1480 ;; Print the result.
12059709
SM
1481 (setq tabulated-list-entries
1482 (mapcar #'package-menu--print-info info-list))))
1483
1484(defun package-menu--generate (remember-pos packages)
1485 "Populate the Package Menu.
1486 If REMEMBER-POS is non-nil, keep point on the same entry.
1487PACKAGES should be t, which means to display all known packages,
1488or a list of package names (symbols) to display."
1489 (package-menu--refresh packages)
1490 (tabulated-list-print remember-pos))
e91a96fe
CY
1491
1492(defun package-menu--print-info (pkg)
1493 "Return a package entry suitable for `tabulated-list-entries'.
1b8dff23
SM
1494PKG has the form (PKG-DESC . STATUS).
1495Return (PKG-DESC [NAME VERSION STATUS DOC])."
1496 (let* ((pkg-desc (car pkg))
1497 (status (cdr pkg))
1498 (face (pcase status
1499 (`"built-in" 'font-lock-builtin-face)
1500 (`"available" 'default)
1501 (`"new" 'bold)
1502 (`"held" 'font-lock-constant-face)
1503 (`"disabled" 'font-lock-warning-face)
1504 (`"installed" 'font-lock-comment-face)
1505 (_ 'font-lock-warning-face)))) ; obsolete.
1506 (list pkg-desc
1507 (vector (list (symbol-name (package-desc-name pkg-desc))
e91a96fe
CY
1508 'face 'link
1509 'follow-link t
1b8dff23 1510 'package-desc pkg-desc
e91a96fe 1511 'action 'package-menu-describe-package)
1b8dff23
SM
1512 (propertize (package-version-join
1513 (package-desc-version pkg-desc))
e91a96fe
CY
1514 'font-lock-face face)
1515 (propertize status 'font-lock-face face)
1b8dff23
SM
1516 (propertize (package-desc-summary pkg-desc)
1517 'font-lock-face face)))))
44198b6e
CY
1518
1519(defun package-menu-refresh ()
ebf662f4
CY
1520 "Download the Emacs Lisp package archive.
1521This fetches the contents of each archive specified in
1522`package-archives', and then refreshes the package menu."
44198b6e 1523 (interactive)
25322144 1524 (unless (derived-mode-p 'package-menu-mode)
187d3296 1525 (error "The current buffer is not a Package Menu"))
44198b6e 1526 (package-refresh-contents)
512e3ae1 1527 (package-menu--generate t t))
44198b6e 1528
e91a96fe
CY
1529(defun package-menu-describe-package (&optional button)
1530 "Describe the current package.
1531If optional arg BUTTON is non-nil, describe its associated package."
44198b6e 1532 (interactive)
1b8dff23 1533 (let ((pkg-desc (if button (button-get button 'package-desc)
66bd25ab 1534 (tabulated-list-get-id))))
1b8dff23 1535 (if pkg-desc
12059709
SM
1536 (describe-package pkg-desc)
1537 (error "No package here"))))
44198b6e
CY
1538
1539;; fixme numeric argument
4d6769e1 1540(defun package-menu-mark-delete (&optional _num)
44198b6e
CY
1541 "Mark a package for deletion and move to the next line."
1542 (interactive "p")
fb87e0fb 1543 (if (member (package-menu-get-status) '("installed" "obsolete"))
e91a96fe 1544 (tabulated-list-put-tag "D" t)
015eea59 1545 (forward-line)))
44198b6e 1546
4d6769e1 1547(defun package-menu-mark-install (&optional _num)
44198b6e
CY
1548 "Mark a package for installation and move to the next line."
1549 (interactive "p")
60057926 1550 (if (member (package-menu-get-status) '("available" "new"))
e91a96fe 1551 (tabulated-list-put-tag "I" t)
015eea59 1552 (forward-line)))
44198b6e 1553
4d6769e1 1554(defun package-menu-mark-unmark (&optional _num)
44198b6e
CY
1555 "Clear any marks on a package and move to the next line."
1556 (interactive "p")
e91a96fe 1557 (tabulated-list-put-tag " " t))
44198b6e
CY
1558
1559(defun package-menu-backup-unmark ()
1560 "Back up one line and clear any marks on that package."
1561 (interactive)
1562 (forward-line -1)
e91a96fe 1563 (tabulated-list-put-tag " "))
44198b6e
CY
1564
1565(defun package-menu-mark-obsolete-for-deletion ()
1566 "Mark all obsolete packages for deletion."
1567 (interactive)
1568 (save-excursion
1569 (goto-char (point-min))
44198b6e 1570 (while (not (eobp))
25322144 1571 (if (equal (package-menu-get-status) "obsolete")
e91a96fe 1572 (tabulated-list-put-tag "D" t)
44198b6e
CY
1573 (forward-line 1)))))
1574
1575(defun package-menu-quick-help ()
1576 "Show short key binding help for package-menu-mode."
1577 (interactive)
1578 (message "n-ext, i-nstall, d-elete, u-nmark, x-ecute, r-efresh, h-elp"))
1579
cb6c4991
CY
1580(define-obsolete-function-alias
1581 'package-menu-view-commentary 'package-menu-describe-package "24.1")
44198b6e 1582
44198b6e 1583(defun package-menu-get-status ()
1b8dff23
SM
1584 (let* ((id (tabulated-list-get-id))
1585 (entry (and id (assq id tabulated-list-entries))))
25322144
CY
1586 (if entry
1587 (aref (cadr entry) 2)
44198b6e
CY
1588 "")))
1589
25322144
CY
1590(defun package-menu--find-upgrades ()
1591 (let (installed available upgrades)
1592 ;; Build list of installed/available packages in this buffer.
1593 (dolist (entry tabulated-list-entries)
1b8dff23
SM
1594 ;; ENTRY is (PKG-DESC [NAME VERSION STATUS DOC])
1595 (let ((pkg-desc (car entry))
4d6769e1 1596 (status (aref (cadr entry) 2)))
25322144 1597 (cond ((equal status "installed")
1b8dff23 1598 (push pkg-desc installed))
60057926 1599 ((member status '("available" "new"))
1b8dff23
SM
1600 (push (cons (package-desc-name pkg-desc) pkg-desc)
1601 available)))))
1602 ;; Loop through list of installed packages, finding upgrades.
1603 (dolist (pkg-desc installed)
1604 (let ((avail-pkg (assq (package-desc-name pkg-desc) available)))
25322144 1605 (and avail-pkg
1b8dff23
SM
1606 (version-list-< (package-desc-version pkg-desc)
1607 (package-desc-version (cdr avail-pkg)))
25322144
CY
1608 (push avail-pkg upgrades))))
1609 upgrades))
1610
1611(defun package-menu-mark-upgrades ()
1612 "Mark all upgradable packages in the Package Menu.
1613For each installed package with a newer version available, place
1614an (I)nstall flag on the available version and a (D)elete flag on
1615the installed version. A subsequent \\[package-menu-execute]
1616call will upgrade the package."
1617 (interactive)
1618 (unless (derived-mode-p 'package-menu-mode)
1619 (error "The current buffer is not a Package Menu"))
1620 (let ((upgrades (package-menu--find-upgrades)))
1621 (if (null upgrades)
1622 (message "No packages to upgrade.")
1623 (widen)
1624 (save-excursion
1625 (goto-char (point-min))
1626 (while (not (eobp))
1b8dff23
SM
1627 (let* ((pkg-desc (tabulated-list-get-id))
1628 (upgrade (cdr (assq (package-desc-name pkg-desc) upgrades))))
25322144
CY
1629 (cond ((null upgrade)
1630 (forward-line 1))
1b8dff23 1631 ((equal pkg-desc upgrade)
25322144
CY
1632 (package-menu-mark-install))
1633 (t
1634 (package-menu-mark-delete))))))
1635 (message "%d package%s marked for upgrading."
1636 (length upgrades)
1637 (if (= (length upgrades) 1) "" "s")))))
1638
a7da0114 1639(defun package-menu-execute (&optional noquery)
015eea59
CY
1640 "Perform marked Package Menu actions.
1641Packages marked for installation are downloaded and installed;
eeb468da
GM
1642packages marked for deletion are removed.
1643Optional argument NOQUERY non-nil means do not ask the user to confirm."
44198b6e 1644 (interactive)
25322144 1645 (unless (derived-mode-p 'package-menu-mode)
e91a96fe 1646 (error "The current buffer is not in Package Menu mode"))
1b8dff23 1647 (let (install-list delete-list cmd pkg-desc)
015eea59
CY
1648 (save-excursion
1649 (goto-char (point-min))
1650 (while (not (eobp))
1651 (setq cmd (char-after))
e91a96fe 1652 (unless (eq cmd ?\s)
1b8dff23
SM
1653 ;; This is the key PKG-DESC.
1654 (setq pkg-desc (tabulated-list-get-id))
e91a96fe 1655 (cond ((eq cmd ?D)
1b8dff23 1656 (push pkg-desc delete-list))
e91a96fe 1657 ((eq cmd ?I)
1b8dff23 1658 (push pkg-desc install-list))))
015eea59 1659 (forward-line)))
25322144 1660 (when install-list
a7da0114
YB
1661 (if (or
1662 noquery
1663 (yes-or-no-p
1b8dff23
SM
1664 (if (= (length install-list) 1)
1665 (format "Install package `%s'? "
1666 (package-desc-full-name (car install-list)))
1667 (format "Install these %d packages (%s)? "
1668 (length install-list)
1669 (mapconcat #'package-desc-full-name
1670 install-list ", ")))))
25322144 1671 (mapc 'package-install install-list)))
015eea59
CY
1672 ;; Delete packages, prompting if necessary.
1673 (when delete-list
a7da0114
YB
1674 (if (or
1675 noquery
1676 (yes-or-no-p
015eea59 1677 (if (= (length delete-list) 1)
1b8dff23
SM
1678 (format "Delete package `%s'? "
1679 (package-desc-full-name (car delete-list)))
015eea59
CY
1680 (format "Delete these %d packages (%s)? "
1681 (length delete-list)
1b8dff23
SM
1682 (mapconcat #'package-desc-full-name
1683 delete-list ", ")))))
015eea59 1684 (dolist (elt delete-list)
1be3ca5a 1685 (condition-case-unless-debug err
1b8dff23 1686 (package-delete elt)
015eea59
CY
1687 (error (message (cadr err)))))
1688 (error "Aborted")))
015eea59 1689 (if (or delete-list install-list)
512e3ae1 1690 (package-menu--generate t t)
015eea59 1691 (message "No operations specified."))))
44198b6e 1692
e91a96fe
CY
1693(defun package-menu--version-predicate (A B)
1694 (let ((vA (or (aref (cadr A) 1) '(0)))
1695 (vB (or (aref (cadr B) 1) '(0))))
1696 (if (version-list-= vA vB)
1697 (package-menu--name-predicate A B)
1698 (version-list-< vA vB))))
1699
1700(defun package-menu--status-predicate (A B)
1701 (let ((sA (aref (cadr A) 2))
1702 (sB (aref (cadr B) 2)))
1703 (cond ((string= sA sB)
1704 (package-menu--name-predicate A B))
60057926
CY
1705 ((string= sA "new") t)
1706 ((string= sB "new") nil)
1707 ((string= sA "available") t)
e91a96fe 1708 ((string= sB "available") nil)
60057926 1709 ((string= sA "installed") t)
e91a96fe 1710 ((string= sB "installed") nil)
60057926 1711 ((string= sA "held") t)
e91a96fe 1712 ((string= sB "held") nil)
60057926 1713 ((string= sA "built-in") t)
e91a96fe 1714 ((string= sB "built-in") nil)
60057926
CY
1715 ((string= sA "obsolete") t)
1716 ((string= sB "obsolete") nil)
e91a96fe
CY
1717 (t (string< sA sB)))))
1718
1719(defun package-menu--description-predicate (A B)
1720 (let ((dA (aref (cadr A) 3))
1721 (dB (aref (cadr B) 3)))
1722 (if (string= dA dB)
1723 (package-menu--name-predicate A B)
1724 (string< dA dB))))
1725
1726(defun package-menu--name-predicate (A B)
1b8dff23
SM
1727 (string< (symbol-name (package-desc-name (car A)))
1728 (symbol-name (package-desc-name (car B)))))
44198b6e
CY
1729
1730;;;###autoload
e91a96fe 1731(defun list-packages (&optional no-fetch)
44198b6e 1732 "Display a list of packages.
e91a96fe
CY
1733This first fetches the updated list of packages before
1734displaying, unless a prefix argument NO-FETCH is specified.
44198b6e 1735The list is displayed in a buffer named `*Packages*'."
e91a96fe
CY
1736 (interactive "P")
1737 (require 'finder-inf nil t)
8a500a91 1738 ;; Initialize the package system if necessary.
4b99edf2
CY
1739 (unless package--initialized
1740 (package-initialize t))
60057926
CY
1741 (let (old-archives new-packages)
1742 (unless no-fetch
1743 ;; Read the locally-cached archive-contents.
1744 (package-read-all-archive-contents)
1745 (setq old-archives package-archive-contents)
1746 ;; Fetch the remote list of packages.
1747 (package-refresh-contents)
1748 ;; Find which packages are new.
1749 (dolist (elt package-archive-contents)
1750 (unless (assq (car elt) old-archives)
1751 (push (car elt) new-packages))))
1752
1753 ;; Generate the Package Menu.
1754 (let ((buf (get-buffer-create "*Packages*")))
1755 (with-current-buffer buf
1756 (package-menu-mode)
1757 (set (make-local-variable 'package-menu--new-package-list)
1758 new-packages)
1759 (package-menu--generate nil t))
1760 ;; The package menu buffer has keybindings. If the user types
1761 ;; `M-x list-packages', that suggests it should become current.
1762 (switch-to-buffer buf))
1763
1764 (let ((upgrades (package-menu--find-upgrades)))
1765 (if upgrades
1766 (message "%d package%s can be upgraded; type `%s' to mark %s for upgrading."
1767 (length upgrades)
1768 (if (= (length upgrades) 1) "" "s")
1769 (substitute-command-keys "\\[package-menu-mark-upgrades]")
1770 (if (= (length upgrades) 1) "it" "them"))))))
44198b6e 1771
cb8759ca 1772;;;###autoload
96ae4c8f 1773(defalias 'package-list-packages 'list-packages)
cb8759ca 1774
512e3ae1
CY
1775;; Used in finder.el
1776(defun package-show-package-list (packages)
1777 "Display PACKAGES in a *Packages* buffer.
1778This is similar to `list-packages', but it does not fetch the
1779updated list of packages, and it only displays packages with
1780names in PACKAGES (which should be a list of symbols)."
1781 (require 'finder-inf nil t)
1782 (let ((buf (get-buffer-create "*Packages*")))
1783 (with-current-buffer buf
1784 (package-menu-mode)
1785 (package-menu--generate nil packages))
1786 (switch-to-buffer buf)))
1787
44198b6e
CY
1788(defun package-list-packages-no-fetch ()
1789 "Display a list of packages.
1790Does not fetch the updated list of packages before displaying.
1791The list is displayed in a buffer named `*Packages*'."
1792 (interactive)
e91a96fe 1793 (list-packages t))
44198b6e 1794
44198b6e
CY
1795(provide 'package)
1796
1797;;; package.el ends here