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