[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: package.el dependencies
From: |
Thierry Volpiatto |
Subject: |
Re: package.el dependencies |
Date: |
Wed, 28 Jan 2015 08:30:07 +0100 |
I will not have a good connection until next week, so I am unable to
push a branch, so I am just attaching patch of all my changes against
package.el here.
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 88fc950..df3a108 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -333,6 +333,15 @@ contents of the archive."
:group 'package
:version "24.4")
+(defcustom packages-installed-directly nil
+ "Store here packages installed explicitely by user.
+This variable will be feeded automaticaly by emacs,
+so you should not modify it yourself.
+This variable will be used by `package-autoremove' to decide
+which packages are no more needed."
+ :group 'package
+ :type '(repeat (choice symbol)))
+
(defvar package--default-summary "No description available.")
(cl-defstruct (package-desc
@@ -1187,7 +1196,7 @@ using `package-compute-transaction'."
(mapc #'package-install-from-archive packages))
;;;###autoload
-(defun package-install (pkg)
+(defun package-install (pkg &optional arg)
"Install the package PKG.
PKG can be a package-desc or the package name of one the available packages
in an archive in `package-archives'. Interactively, prompt for its name."
@@ -1206,7 +1215,11 @@ in an archive in `package-archives'. Interactively,
prompt for its name."
(unless (package-installed-p (car elt))
(symbol-name (car elt))))
package-archive-contents))
- nil t)))))
+ nil t))
+ "\p")))
+ (when (and arg (not (memq pkg packages-installed-directly)))
+ (customize-save-variable 'packages-installed-directly
+ (cons pkg packages-installed-directly)))
(package-download-transaction
(if (package-desc-p pkg)
(package-compute-transaction (list pkg)
@@ -1388,26 +1401,105 @@ The file can either be a tar file or an Emacs Lisp
file."
(when (string-match "\\.tar\\'" file) (tar-mode)))
(package-install-from-buffer)))
-(defun package-delete (pkg-desc)
- (let ((dir (package-desc-dir pkg-desc)))
- (if (not (string-prefix-p (file-name-as-directory
- (expand-file-name package-user-dir))
- (expand-file-name dir)))
- ;; Don't delete "system" packages.
- (error "Package `%s' is a system package, not deleting"
- (package-desc-full-name pkg-desc))
- (delete-directory dir t t)
- ;; Remove NAME-VERSION.signed file.
- (let ((signed-file (concat dir ".signed")))
- (if (file-exists-p signed-file)
- (delete-file signed-file)))
- ;; Update package-alist.
- (let* ((name (package-desc-name pkg-desc))
- (pkgs (assq name package-alist)))
- (delete pkg-desc pkgs)
- (unless (cdr pkgs)
- (setq package-alist (delq pkgs package-alist))))
- (message "Package `%s' deleted." (package-desc-full-name pkg-desc)))))
+(defun package--get-deps (pkg &optional only)
+ (let* ((pkg-desc (cadr (assq pkg package-alist)))
+ (direct-deps (cl-loop for p in (package-desc-reqs pkg-desc)
+ for name = (car p)
+ when (assq name package-alist)
+ collect name))
+ (indirect-deps (unless (eq only 'direct)
+ (cl-loop for p in direct-deps
+ for dep = (cadr (assq p package-alist))
+ when (and dep (assq p package-alist))
+ append (mapcar 'car
+ (package-desc-reqs
+ dep))))))
+ (cl-case only
+ (direct direct-deps)
+ (separate (list direct-deps indirect-deps))
+ (indirect indirect-deps)
+ (t (append direct-deps indirect-deps)))))
+
+(defun package-used-elsewhere-p (pkg &optional pkg-list)
+ "Check in PKG-LIST if PKG is used elsewhere as dependency.
+When not specified, PKG-LIST default to `package-alist' with PKG entry removed.
+Argument PKG is a symbol.
+Returns the first package found in PKG-LIST where PKG is used as dependency."
+ (cl-loop with alist = (or pkg-list
+ (remove (assq pkg package-alist)
+ package-alist))
+ for p in alist thereis
+ (and (memq pkg (mapcar 'car (package-desc-reqs (cadr p))))
+ (car p))))
+
+(defun package-delete (pkg-desc &optional force)
+ "Delete package PKG-DESC.
+
+Argument PKG-DESC is a full description of package as vector.
+When package is used elsewhere as dependency of another package,
+refuse deleting it and return an error.
+If FORCE is non--nil package will be deleted even if it is used
+elsewhere."
+ (let ((dir (package-desc-dir pkg-desc))
+ (name (package-desc-name pkg-desc))
+ pkg-used-elsewhere-by)
+ (cond ((not (string-prefix-p (file-name-as-directory
+ (expand-file-name package-user-dir))
+ (expand-file-name dir)))
+ ;; Don't delete "system" packages.
+ (error "Package `%s' is a system package, not deleting"
+ (package-desc-full-name pkg-desc)))
+ ((and (null force)
+ (setq pkg-used-elsewhere-by
+ (package-used-elsewhere-p name)))
+ ;; Don't delete packages used as dependency elsewhere.
+ (error "Package `%s' is used by `%s' as dependency, not deleting"
+ (package-desc-full-name pkg-desc)
+ pkg-used-elsewhere-by))
+ (t
+ (delete-directory dir t t)
+ ;; Remove NAME-VERSION.signed file.
+ (let ((signed-file (concat dir ".signed")))
+ (if (file-exists-p signed-file)
+ (delete-file signed-file)))
+ ;; Update package-alist.
+ (let ((pkgs (assq name package-alist)))
+ (delete pkg-desc pkgs)
+ (unless (cdr pkgs)
+ (setq package-alist (delq pkgs package-alist))))
+ (message "Package `%s' deleted." (package-desc-full-name
pkg-desc))))))
+
+;;;###autoload
+(defun package-autoremove ()
+ "Remove packages that are no more needed.
+
+Packages that are no more needed by other packages in
+`packages-installed-directly' and their dependencies
+will be deleted."
+ (interactive)
+ (let* (old-direct
+ (needed (cl-loop for p in packages-installed-directly
+ if (assq p package-alist)
+ append (package--get-deps p) into lst
+ else do (push p old-direct)
+ finally return lst)))
+ (cl-loop for p in (mapcar 'car package-alist)
+ unless (or (memq p needed)
+ (memq p packages-installed-directly))
+ collect p into lst
+ finally (if lst
+ (when (y-or-n-p (format "%s packages will be
deleted:\n%s, proceed? "
+ (length lst)
+ (mapconcat 'symbol-name lst
", ")))
+ (mapc (lambda (p)
+ (package-delete (cadr (assq p
package-alist)) t))
+ lst)
+ (customize-save-variable
+ 'packages-installed-directly
+ (cl-loop for p in packages-installed-directly
+ unless (memq p old-direct)
+ collect p)))
+ (message "Nothing to autoremove")))))
(defun package-archive-base (desc)
"Return the archive containing the package NAME."
@@ -2178,7 +2270,7 @@ Optional argument NOQUERY non-nil means do not ask the
user to confirm."
(length install-list)
(mapconcat #'package-desc-full-name
install-list ", ")))))
- (mapc 'package-install install-list)))
+ (mapc (lambda (p) (package-install p 1)) install-list)))
;; Delete packages, prompting if necessary.
(when delete-list
(if (or
--
Thierry
Get my Gnupg key:
gpg --keyserver pgp.mit.edu --recv-keys 59F29997
Re: package.el dependencies, Thierry Volpiatto, 2015/01/26
Re: package.el dependencies, Artur Malabarba, 2015/01/26
Re: package.el dependencies,
Thierry Volpiatto <=
Re: package.el dependencies, Dmitry Gutov, 2015/01/28
Re: package.el dependencies, Artur Malabarba, 2015/01/28
Re: package.el dependencies, Thierry Volpiatto, 2015/01/28
Re: package.el dependencies, Stefan Monnier, 2015/01/28
Re: package.el dependencies, Ivan Shmakov, 2015/01/28
Re: package.el dependencies, Artur Malabarba, 2015/01/28