aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Volpiatto2015-02-01 19:45:47 -0200
committerArtur Malabarba2015-02-01 20:17:51 -0200
commite2f0f263df89a156ff5b4b05e3b3aae457eb38a9 (patch)
tree80b4c9aea6e5fcd427200b54d88cb25640b9695b
parent92a8dec54ed3314ca06f40cd0c226c4267a160e8 (diff)
downloademacs-e2f0f263df89a156ff5b4b05e3b3aae457eb38a9.tar.gz
emacs-e2f0f263df89a156ff5b4b05e3b3aae457eb38a9.zip
emacs-lisp/package.el: Don't allow deleting dependencies.
-rw-r--r--lisp/ChangeLog26
-rw-r--r--lisp/emacs-lisp/package.el203
2 files changed, 192 insertions, 37 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 0a3c7c95929..742aced3a7c 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,29 @@
12015-02-01 Thierry Volpiatto <thierry.volpiatto@gmail.com>
2
3 * emacs-lisp/package.el: Don't allow deleting dependencies.
4
5 (package-used-elsewhere-p): New function.
6 (package-delete): Use it, return now an error when trying to
7 delete a package used as dependency by another package.
8
9 Add a reinstall package command.
10 (package-reinstall): New function.
11
12 Add a package-autoremove command.
13 (package-selected-packages): New user var.
14 (package-install): Add an optional arg to notify interactive use.
15 Fix docstring. Save installed package to
16 packages-installed-directly.
17 (package-install-from-buffer): Same.
18 (package-user-selected-packages-install): Allow installing all
19 packages in packages-installed-directly at once.
20 (package--get-deps): New function.
21 (package-autoremove): New function.
22 (package-install-button-action): Call package-install with
23 interactive arg.
24 (package-menu-execute): Same but only for only for not installed
25 packages.
26
12015-01-31 Stefan Monnier <monnier@iro.umontreal.ca> 272015-01-31 Stefan Monnier <monnier@iro.umontreal.ca>
2 28
3 * emacs-lisp/eieio.el (defclass): Use new eieio-make-class-predicate 29 * emacs-lisp/eieio.el (defclass): Use new eieio-make-class-predicate
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 88fc950ee21..db8d8685574 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -333,6 +333,17 @@ contents of the archive."
333 :group 'package 333 :group 'package
334 :version "24.4") 334 :version "24.4")
335 335
336(defcustom package-selected-packages nil
337 "Store here packages installed explicitely by user.
338This variable will be feeded automatically by emacs,
339when installing a new package.
340This variable will be used by `package-autoremove' to decide
341which packages are no more needed.
342You can use it to (re)install packages on other machines
343by running `package-user-selected-packages-install'."
344 :group 'package
345 :type '(repeat (choice symbol)))
346
336(defvar package--default-summary "No description available.") 347(defvar package--default-summary "No description available.")
337 348
338(cl-defstruct (package-desc 349(cl-defstruct (package-desc
@@ -1187,10 +1198,13 @@ using `package-compute-transaction'."
1187 (mapc #'package-install-from-archive packages)) 1198 (mapc #'package-install-from-archive packages))
1188 1199
1189;;;###autoload 1200;;;###autoload
1190(defun package-install (pkg) 1201(defun package-install (pkg &optional arg)
1191 "Install the package PKG. 1202 "Install the package PKG.
1192PKG can be a package-desc or the package name of one the available packages 1203PKG can be a package-desc or the package name of one the available packages
1193in an archive in `package-archives'. Interactively, prompt for its name." 1204in an archive in `package-archives'. Interactively, prompt for its name
1205and add PKG to `package-selected-packages'.
1206When called from lisp you will have to use ARG if you want to
1207simulate an interactive call to add PKG to `package-selected-packages'."
1194 (interactive 1208 (interactive
1195 (progn 1209 (progn
1196 ;; Initialize the package system to get the list of package 1210 ;; Initialize the package system to get the list of package
@@ -1206,7 +1220,11 @@ in an archive in `package-archives'. Interactively, prompt for its name."
1206 (unless (package-installed-p (car elt)) 1220 (unless (package-installed-p (car elt))
1207 (symbol-name (car elt)))) 1221 (symbol-name (car elt))))
1208 package-archive-contents)) 1222 package-archive-contents))
1209 nil t))))) 1223 nil t))
1224 "\p")))
1225 (when (and arg (not (memq pkg package-selected-packages)))
1226 (customize-save-variable 'package-selected-packages
1227 (cons pkg package-selected-packages)))
1210 (package-download-transaction 1228 (package-download-transaction
1211 (if (package-desc-p pkg) 1229 (if (package-desc-p pkg)
1212 (package-compute-transaction (list pkg) 1230 (package-compute-transaction (list pkg)
@@ -1214,6 +1232,16 @@ in an archive in `package-archives'. Interactively, prompt for its name."
1214 (package-compute-transaction () 1232 (package-compute-transaction ()
1215 (list (list pkg)))))) 1233 (list (list pkg))))))
1216 1234
1235;;;###autoload
1236(defun package-reinstall (pkg)
1237 "Reinstall package PKG."
1238 (interactive (list (intern (completing-read
1239 "Reinstall package: "
1240 (mapcar 'symbol-name
1241 (mapcar 'car package-alist))))))
1242 (package-delete (cadr (assq pkg package-alist)) t)
1243 (package-install pkg))
1244
1217(defun package-strip-rcs-id (str) 1245(defun package-strip-rcs-id (str)
1218 "Strip RCS version ID from the version string STR. 1246 "Strip RCS version ID from the version string STR.
1219If the result looks like a dotted numeric version, return it. 1247If the result looks like a dotted numeric version, return it.
@@ -1354,24 +1382,29 @@ is derived from the main .el file in the directory.
1354 1382
1355Downloads and installs required packages as needed." 1383Downloads and installs required packages as needed."
1356 (interactive) 1384 (interactive)
1357 (let ((pkg-desc 1385 (let* ((pkg-desc
1358 (cond 1386 (cond
1359 ((derived-mode-p 'dired-mode) 1387 ((derived-mode-p 'dired-mode)
1360 ;; This is the only way a package-desc object with a `dir' 1388 ;; This is the only way a package-desc object with a `dir'
1361 ;; desc-kind can be created. Such packages can't be 1389 ;; desc-kind can be created. Such packages can't be
1362 ;; uploaded or installed from archives, they can only be 1390 ;; uploaded or installed from archives, they can only be
1363 ;; installed from local buffers or directories. 1391 ;; installed from local buffers or directories.
1364 (package-dir-info)) 1392 (package-dir-info))
1365 ((derived-mode-p 'tar-mode) 1393 ((derived-mode-p 'tar-mode)
1366 (package-tar-file-info)) 1394 (package-tar-file-info))
1367 (t 1395 (t
1368 (package-buffer-info))))) 1396 (package-buffer-info))))
1397 (name (package-desc-name pkg-desc)))
1369 ;; Download and install the dependencies. 1398 ;; Download and install the dependencies.
1370 (let* ((requires (package-desc-reqs pkg-desc)) 1399 (let* ((requires (package-desc-reqs pkg-desc))
1371 (transaction (package-compute-transaction nil requires))) 1400 (transaction (package-compute-transaction nil requires)))
1372 (package-download-transaction transaction)) 1401 (package-download-transaction transaction))
1373 ;; Install the package itself. 1402 ;; Install the package itself.
1374 (package-unpack pkg-desc) 1403 (package-unpack pkg-desc)
1404 (unless (memq name package-selected-packages)
1405 (push name package-selected-packages)
1406 (customize-save-variable 'package-selected-packages
1407 package-selected-packages))
1375 pkg-desc)) 1408 pkg-desc))
1376 1409
1377;;;###autoload 1410;;;###autoload
@@ -1388,26 +1421,120 @@ The file can either be a tar file or an Emacs Lisp file."
1388 (when (string-match "\\.tar\\'" file) (tar-mode))) 1421 (when (string-match "\\.tar\\'" file) (tar-mode)))
1389 (package-install-from-buffer))) 1422 (package-install-from-buffer)))
1390 1423
1391(defun package-delete (pkg-desc) 1424(defun package--get-deps (pkg &optional only)
1392 (let ((dir (package-desc-dir pkg-desc))) 1425 (let* ((pkg-desc (cadr (assq pkg package-alist)))
1393 (if (not (string-prefix-p (file-name-as-directory 1426 (direct-deps (cl-loop for p in (package-desc-reqs pkg-desc)
1394 (expand-file-name package-user-dir)) 1427 for name = (car p)
1395 (expand-file-name dir))) 1428 when (assq name package-alist)
1396 ;; Don't delete "system" packages. 1429 collect name))
1397 (error "Package `%s' is a system package, not deleting" 1430 (indirect-deps (unless (eq only 'direct)
1398 (package-desc-full-name pkg-desc)) 1431 (cl-loop for p in direct-deps
1399 (delete-directory dir t t) 1432 for dep = (cadr (assq p package-alist))
1400 ;; Remove NAME-VERSION.signed file. 1433 when (and dep (assq p package-alist))
1401 (let ((signed-file (concat dir ".signed"))) 1434 append (mapcar 'car
1402 (if (file-exists-p signed-file) 1435 (package-desc-reqs
1403 (delete-file signed-file))) 1436 dep))))))
1404 ;; Update package-alist. 1437 (cl-case only
1405 (let* ((name (package-desc-name pkg-desc)) 1438 (direct direct-deps)
1406 (pkgs (assq name package-alist))) 1439 (separate (list direct-deps indirect-deps))
1407 (delete pkg-desc pkgs) 1440 (indirect indirect-deps)
1408 (unless (cdr pkgs) 1441 (t (append direct-deps indirect-deps)))))
1409 (setq package-alist (delq pkgs package-alist)))) 1442
1410 (message "Package `%s' deleted." (package-desc-full-name pkg-desc))))) 1443;;;###autoload
1444(defun package-user-selected-packages-install ()
1445 "Ensure packages in `package-selected-packages' are installed.
1446If some packages are not installed propose to install them."
1447 (interactive)
1448 (cl-loop for p in package-selected-packages
1449 unless (package-installed-p p)
1450 collect p into lst
1451 finally
1452 (if lst
1453 (when (y-or-n-p
1454 (format "%s packages will be installed:\n%s, proceed?"
1455 (length lst)
1456 (mapconcat 'symbol-name lst ", ")))
1457 (mapc 'package-install lst))
1458 (message "All your packages are already installed"))))
1459
1460(defun package-used-elsewhere-p (pkg-desc &optional pkg-list)
1461 "Check in PKG-LIST if PKG-DESC is used elsewhere as dependency.
1462
1463When not specified, PKG-LIST default to `package-alist'
1464with PKG-DESC entry removed.
1465Returns the first package found in PKG-LIST where PKG is used as dependency."
1466 (unless (string= (package-desc-status pkg-desc) "obsolete")
1467 (let ((pkg (package-desc-name pkg-desc)))
1468 (cl-loop with alist = (or pkg-list
1469 (remove (assq pkg package-alist)
1470 package-alist))
1471 for p in alist thereis
1472 (and (memq pkg (mapcar 'car (package-desc-reqs (cadr p))))
1473 (car p))))))
1474
1475(defun package-delete (pkg-desc &optional force)
1476 "Delete package PKG-DESC.
1477
1478Argument PKG-DESC is a full description of package as vector.
1479When package is used elsewhere as dependency of another package,
1480refuse deleting it and return an error.
1481If FORCE is non--nil package will be deleted even if it is used
1482elsewhere."
1483 (let ((dir (package-desc-dir pkg-desc))
1484 (name (package-desc-name pkg-desc))
1485 pkg-used-elsewhere-by)
1486 (cond ((not (string-prefix-p (file-name-as-directory
1487 (expand-file-name package-user-dir))
1488 (expand-file-name dir)))
1489 ;; Don't delete "system" packages.
1490 (error "Package `%s' is a system package, not deleting"
1491 (package-desc-full-name pkg-desc)))
1492 ((and (null force)
1493 (setq pkg-used-elsewhere-by
1494 (package-used-elsewhere-p pkg-desc)))
1495 ;; Don't delete packages used as dependency elsewhere.
1496 (error "Package `%s' is used by `%s' as dependency, not deleting"
1497 (package-desc-full-name pkg-desc)
1498 pkg-used-elsewhere-by))
1499 (t
1500 (delete-directory dir t t)
1501 ;; Remove NAME-VERSION.signed file.
1502 (let ((signed-file (concat dir ".signed")))
1503 (if (file-exists-p signed-file)
1504 (delete-file signed-file)))
1505 ;; Update package-alist.
1506 (let ((pkgs (assq name package-alist)))
1507 (delete pkg-desc pkgs)
1508 (unless (cdr pkgs)
1509 (setq package-alist (delq pkgs package-alist))))
1510 (message "Package `%s' deleted." (package-desc-full-name pkg-desc))))))
1511
1512;;;###autoload
1513(defun package-autoremove ()
1514 "Remove packages that are no more needed.
1515
1516Packages that are no more needed by other packages in
1517`package-selected-packages' and their dependencies
1518will be deleted."
1519 (interactive)
1520 (let* (old-direct
1521 (needed (cl-loop for p in package-selected-packages
1522 if (assq p package-alist)
1523 append (package--get-deps p) into lst
1524 else do (push p old-direct)
1525 finally return lst)))
1526 (cl-loop for p in (mapcar 'car package-alist)
1527 unless (or (memq p needed)
1528 (memq p package-selected-packages))
1529 collect p into lst
1530 finally (if lst
1531 (when (y-or-n-p (format "%s packages will be deleted:\n%s, proceed? "
1532 (length lst)
1533 (mapconcat 'symbol-name lst ", ")))
1534 (mapc (lambda (p)
1535 (package-delete (cadr (assq p package-alist)) t))
1536 lst))
1537 (message "Nothing to autoremove")))))
1411 1538
1412(defun package-archive-base (desc) 1539(defun package-archive-base (desc)
1413 "Return the archive containing the package NAME." 1540 "Return the archive containing the package NAME."
@@ -1721,7 +1848,7 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages."
1721 (let ((pkg-desc (button-get button 'package-desc))) 1848 (let ((pkg-desc (button-get button 'package-desc)))
1722 (when (y-or-n-p (format "Install package `%s'? " 1849 (when (y-or-n-p (format "Install package `%s'? "
1723 (package-desc-full-name pkg-desc))) 1850 (package-desc-full-name pkg-desc)))
1724 (package-install pkg-desc) 1851 (package-install pkg-desc 1)
1725 (revert-buffer nil t) 1852 (revert-buffer nil t)
1726 (goto-char (point-min))))) 1853 (goto-char (point-min)))))
1727 1854
@@ -2178,7 +2305,9 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm."
2178 (length install-list) 2305 (length install-list)
2179 (mapconcat #'package-desc-full-name 2306 (mapconcat #'package-desc-full-name
2180 install-list ", "))))) 2307 install-list ", ")))))
2181 (mapc 'package-install install-list))) 2308 (mapc (lambda (p)
2309 (package-install p (and (null (package-installed-p p)) 1)))
2310 install-list)))
2182 ;; Delete packages, prompting if necessary. 2311 ;; Delete packages, prompting if necessary.
2183 (when delete-list 2312 (when delete-list
2184 (if (or 2313 (if (or