This variable will be used by `package-autoremove' to decide
which packages are no more needed.
You can use it to (re)install packages on other machines
-by running `package-user-selected-packages-install'."
+by running `package-user-selected-packages-install'.
+
+To check if a package is contained in this list here, use
+`package--user-selected-p', as it may populate the variable with
+a sane initial value."
:group 'package
:type '(repeat symbol))
nil))
alist)))
+(defun package--user-selected-p (pkg)
+ "Return non-nil if PKG is a package was installed by the user.
+PKG is a package name.
+This looks into `package-selected-packages', populating it first
+if it is still empty."
+ (unless (consp package-selected-packages)
+ (customize-save-variable
+ 'package-selected-packages
+ (setq package-selected-packages (package--find-non-dependencies))))
+ (memq pkg package-selected-packages))
+
(defun package-download-transaction (packages)
"Download and install all the packages in PACKAGES.
PACKAGES should be a list of package-desc.
package-archive-contents))
nil t))
t)))
- (when (and mark-selected (not (memq pkg package-selected-packages)))
- (customize-save-variable 'package-selected-packages
- (cons pkg package-selected-packages)))
+ (let ((name (if (package-desc-p pkg)
+ (package-desc-name pkg)
+ pkg)))
+ (when (and mark-selected (not (package--user-selected-p name)))
+ (customize-save-variable 'package-selected-packages
+ (cons name package-selected-packages))))
(package-download-transaction
(if (package-desc-p pkg)
(package-compute-transaction (list pkg)
"Reinstall package: "
(mapcar #'symbol-name
(mapcar #'car package-alist))))))
- (package-delete (cadr (assq pkg package-alist)) 'force
- (memq pkg package-selected-packages))
+ (package-delete (cadr (assq pkg package-alist)) 'force 'nosave)
(package-install pkg))
(defun package-strip-rcs-id (str)
(package-download-transaction transaction))
;; Install the package itself.
(package-unpack pkg-desc)
- (unless (memq name package-selected-packages)
- (push name package-selected-packages)
+ (unless (package--user-selected-p name)
(customize-save-variable 'package-selected-packages
- package-selected-packages))
+ (cons name package-selected-packages)))
pkg-desc))
;;;###autoload
"Ensure packages in `package-selected-packages' are installed.
If some packages are not installed propose to install them."
(interactive)
- (cl-loop for p in package-selected-packages
- unless (package-installed-p p)
- collect p into lst
- finally
- (if lst
- (when (y-or-n-p
- (format "%s packages will be installed:\n%s, proceed?"
- (length lst)
- (mapconcat #'symbol-name lst ", ")))
- (mapc #'package-install lst))
- (message "All your packages are already installed"))))
+ ;; We don't need to populate `package-selected-packages' before
+ ;; using here, because the outcome is the same either way (nothing
+ ;; gets installed).
+ (if (not package-selected-packages)
+ (message "`package-selected-packages' is empty, nothing to install")
+ (cl-loop for p in package-selected-packages
+ unless (package-installed-p p)
+ collect p into lst
+ finally
+ (if lst
+ (when (y-or-n-p
+ (format "%s packages will be installed:\n%s, proceed?"
+ (length lst)
+ (mapconcat #'symbol-name lst ", ")))
+ (mapc #'package-install lst))
+ (message "All your packages are already installed")))))
(defun package--used-elsewhere-p (pkg-desc &optional pkg-list)
"Non-nil if PKG-DESC is a dependency of a package in PKG-LIST.
(unless (cdr pkgs)
(setq package-alist (delq pkgs package-alist))))
;; Update package-selected-packages.
- (when (and (memq name package-selected-packages)
- (null nosave))
+ (when (and (null nosave)
+ (package--user-selected-p name))
(customize-save-variable
'package-selected-packages (remove name package-selected-packages)))
(message "Package `%s' deleted." (package-desc-full-name pkg-desc))))))
`package-selected-packages' and their dependencies
will be deleted."
(interactive)
- (let ((needed (cl-loop for p in package-selected-packages
- if (assq p package-alist)
- append (package--get-deps p))))
- (cl-loop for p in (mapcar #'car package-alist)
- unless (or (memq p needed)
- (memq p package-selected-packages))
- 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))
- (message "Nothing to autoremove")))))
+ ;; If `package-selected-packages' is nil, it would make no sense to
+ ;; try to populate it here, because then `package-autoremove' will
+ ;; do absolutely nothing.
+ (when (or package-selected-packages
+ (yes-or-no-p
+ "`package-selected-packages' is empty! Really remove ALL packages? "))
+ (let ((needed (cl-loop for p in package-selected-packages
+ if (assq p package-alist)
+ ;; `p' and its dependencies are needed.
+ append (cons p (package--get-deps p)))))
+ (cl-loop for p in (mapcar #'car package-alist)
+ unless (memq p needed)
+ 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))
+ (message "Nothing to autoremove"))))))
(defun package-archive-base (desc)
"Return the archive containing the package NAME."
(unless no-activate
(dolist (elt package-alist)
(package-activate (car elt))))
- (when (and package-alist (not package-selected-packages))
- (customize-save-variable 'package-selected-packages
- (package--find-non-dependencies)))
(setq package--initialized t))
\f