Function: package-isolate

package-isolate is an interactive and byte-compiled function defined in package.el.gz.

Signature

(package-isolate PACKAGES &optional TEMP-INIT)

Documentation

Start an uncustomized Emacs and only load a set of PACKAGES.

Interactively, prompt for PACKAGES to load, which should be specified separated by commas. If called from Lisp, PACKAGES should be a list of packages to load. If TEMP-INIT is non-nil, or when invoked with a prefix argument, the Emacs user directory is set to a temporary directory. This command is intended for testing Emacs and/or the packages in a clean environment.

Probably introduced at or before Emacs version 30.1.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/package.el.gz
(defun package-isolate (packages &optional temp-init)
  "Start an uncustomized Emacs and only load a set of PACKAGES.
Interactively, prompt for PACKAGES to load, which should be specified
separated by commas.
If called from Lisp, PACKAGES should be a list of packages to load.
If TEMP-INIT is non-nil, or when invoked with a prefix argument,
the Emacs user directory is set to a temporary directory.
This command is intended for testing Emacs and/or the packages
in a clean environment."
  (interactive
   (cl-loop for p in (cl-loop for p in (package--alist) append (cdr p))
	    unless (package-built-in-p p)
	    collect (cons (package-desc-full-name p) p) into table
	    finally return
	    (list
             (cl-loop for c in
                      (completing-read-multiple
                       "Packages to isolate: " table
                       nil t)
                           collect (alist-get c table nil nil #'string=))
                  current-prefix-arg)))
  (let* ((name (concat "package-isolate-"
                       (mapconcat #'package-desc-full-name packages ",")))
         (all-packages (delete-consecutive-dups
                        (sort (append packages (mapcan #'package--dependencies packages))
                              (lambda (p0 p1)
                                (string< (package-desc-name p0) (package-desc-name p1))))))
         initial-scratch-message package-load-list)
    (with-temp-buffer
      (insert ";; This is an isolated testing environment, with these packages enabled:\n\n")
      (dolist (package all-packages)
        (push (list (package-desc-name package)
                    (package-version-join (package-desc-version package)))
              package-load-list)
        (insert ";; - " (package-desc-full-name package))
        (unless (memq package packages)
          (insert " (dependency)"))
        (insert "\n"))
      (insert "\n")
      (setq initial-scratch-message (buffer-string)))
    (apply #'start-process (concat "*" name "*") nil
           (list (expand-file-name invocation-name invocation-directory)
                 "--quick" "--debug-init"
                 "--init-directory" (if temp-init
                                        (make-temp-file name t)
                                      user-emacs-directory)
                 (format "--eval=%S"
                         `(progn
                            (setq initial-scratch-message ,initial-scratch-message)

                            (require 'package)
                            ,@(mapcar
                               (lambda (dir)
                                 `(add-to-list 'package-directory-list ,dir))
                               (cons package-user-dir package-directory-list))
                            (setq package-load-list ',package-load-list)
                            (package-activate-all)))))))