Function: package-vc--unpack-1
package-vc--unpack-1 is a byte-compiled function defined in
package-vc.el.gz.
Signature
(package-vc--unpack-1 PKG-DESC)
Documentation
Prepare PKG-DESC that is already checked-out.
When there's a relevant pkg-spec it is used for checkout directory.
Otherwise dir slot of PKG-SPEC is used. This includes downloading
missing dependencies, generating autoloads, generating a package
description file (used to identify a package as a VC package later on),
building documentation and marking the package as installed.
Source Code
;; Defined in /usr/src/emacs/lisp/emacs-lisp/package-vc.el.gz
(defun package-vc--unpack-1 (pkg-desc)
"Prepare PKG-DESC that is already checked-out.
When there's a relevant pkg-spec it is used for checkout directory.
Otherwise `dir' slot of PKG-SPEC is used. This includes downloading
missing dependencies, generating autoloads, generating a package
description file (used to identify a package as a VC package later on),
building documentation and marking the package as installed."
(let* (;; Main package directory, under `package-user-dir'. This is
;; the same `checkout-dir' when package has been installed with
;; `package-vc-install'.
(pkg-dir (package-desc-dir pkg-desc))
(pkg-spec (package-vc--desc->spec pkg-desc))
;; Directory where the package repository has been checked out.
;; This is the `dir' argument of
;; `package-vc-install-from-checkout'.
(checkout-dir (package-vc--checkout-dir pkg-desc))
;; Directory where package's Lisp code resides. It may be
;; equal to `checkout-dir' or be a subdirectory of it.
(lisp-dir (package-vc--checkout-dir pkg-desc 'lisp-dir))
missing)
;; In case the package was installed directly from source, the
;; dependency list wasn't know beforehand, and they might have
;; to be installed explicitly.
(let ((ignored-files
(if (plist-get pkg-spec :ignored-files)
(mapconcat
(lambda (ignore)
(wildcard-to-regexp
(if (string-match-p "\\`/" ignore)
(concat checkout-dir ignore)
(concat "*/" ignore))))
(plist-get pkg-spec :ignored-files)
"\\|")
regexp-unmatchable))
(deps '()))
(dolist (file (directory-files lisp-dir t "\\.el\\'" t))
(unless (string-match-p ignored-files file)
(with-temp-buffer
(insert-file-contents file)
(when-let* ((require-lines (lm-header-multiline "package-requires")))
(thread-last
(mapconcat #'identity require-lines " ")
package-read-from-string
lm--prepare-package-dependencies
(nconc deps)
(setq deps))))))
(dolist (dep deps)
(cl-callf version-to-list (cadr dep)))
(setf (package-desc-reqs pkg-desc) deps)
(setf missing (package-vc-install-dependencies (delete-dups deps)))
(setf missing (delq (assq (package-desc-name pkg-desc)
missing)
missing)))
;; Generate autoloads
(let* ((name (package-desc-name pkg-desc))
(auto-name (format "%s-autoloads.el" name)))
(package-generate-autoloads name lisp-dir)
;; There are two cases when we wish to "indirect" the loading of
;; autoload files:
;;
;; 1. a package specification has a `:lisp-dir' entry listing
;; indicting that the actual Lisp code is located in a
;; subdirectory of the checkout,
;;
;; 2. the package has been installed using
;; `package-vc-install-from-checkout' and we want to load the
;; other directory instead -- which is outside of the checkout.
;; We can therefore take file inequality as a sign that we have to
;; set up an indirection.
(unless (file-equal-p lisp-dir pkg-dir)
(write-region
(concat
";; Autoload indirection for package-vc -*- lexical-binding: t -*-\n\n"
(prin1-to-string
;; The indirection is just a single load statement to the
;; actual file (we don't want to use symbolic links due to
;; portability reasons). Detecting which of the two cases
;; mentioned above we are setting up can be done by checking
;; if the directory with the lisp code is a subdirectory of
;; the package directory.
`(load ,(if (file-in-directory-p lisp-dir pkg-dir)
`(expand-file-name
,(file-relative-name
(expand-file-name auto-name lisp-dir)
pkg-dir)
(or (and load-file-name
(file-name-directory load-file-name))
(car load-path)))
(expand-file-name auto-name lisp-dir)))))
nil (expand-file-name auto-name pkg-dir))))
;; Generate package file
(let ((pkg-file (expand-file-name (package--description-file pkg-dir) pkg-dir)))
(package-vc--generate-description-file pkg-desc pkg-file))
;; Process :make and :shell-command arguments before building documentation
(when (or (eq package-vc-allow-build-commands t)
(memq (package-desc-name pkg-desc)
package-vc-allow-build-commands))
(package-vc--make pkg-spec pkg-desc))
;; Detect a manual
(when (executable-find "install-info")
(dolist (doc-file (ensure-list (plist-get pkg-spec :doc)))
(package-vc--build-documentation pkg-desc doc-file)))
;; Remove any previous instance of PKG-DESC from `package-alist'
(let ((pkgs (assq (package-desc-name pkg-desc) package-alist)))
(when pkgs
(setf (cdr pkgs) (seq-remove #'package-vc-p (cdr pkgs)))))
;; Remove all compiled files to allow for macros to be used from
;; source files, regardless of order of source files compilation and
;; load ordering. As a side effect there are no compiled files for
;; source files that no longer exist.
(dolist (elc-file (directory-files-recursively
lisp-dir
(rx string-start
(not ".") (zero-or-more anychar) ".elc"
string-end)
nil
(lambda (dir)
(and (file-accessible-directory-p dir)
(not (string-prefix-p "." dir))))))
(delete-file elc-file))
;; Update package-alist.
(let* ((new-desc (package-load-descriptor pkg-dir))
(compile-desc (package-desc-create :name (package-desc-name new-desc)
:dir lisp-dir)))
;; Activation has to be done before compilation, so that if we're
;; upgrading and macros have changed we load the new definitions
;; before compiling.
(when (package-activate-1 new-desc :reload :deps)
;; `package-activate-1' will reload all necessary package files
;; as long as their stems are relative to of `pkg-dir'. If
;; that's not the case (for example for packages with different
;; `checkout-dir' or with source files in a sub directory of
;; `pkg-dir'), we want to reload package files from the
;; `lisp-dir' before compilation.
(unless (file-equal-p lisp-dir pkg-dir)
(package--reload-previously-loaded compile-desc))
;; `package-activate-1' will add info node as long as dir file
;; exists in `pkg-dir'. We need to manually add it when
;; `checkout-dir' is in different location.
(unless (file-equal-p checkout-dir pkg-dir)
(package--add-info-node checkout-dir))
;; FIXME: Compilation should be done as a separate, optional, step.
;; E.g. for multi-package installs, we should first install all packages
;; and then compile them.
(package--compile compile-desc)
(when package-native-compile
(package--native-compile-async compile-desc))
;; After compilation, load again any files loaded by
;; `package-activate-1', so that we use the byte-compiled
;; definitions. This time we'll use `compile-desc' straight
;; away.
(package--reload-previously-loaded compile-desc)))
;; Mark package as selected
(let ((name (package-desc-name pkg-desc)))
(unless (memq name package-selected-packages)
(package--save-selected-packages
(cons name package-selected-packages))))
(package--quickstart-maybe-refresh)
;; Confirm that the installation was successful
(let ((main-file (package-vc--main-file pkg-desc)))
(message "VC package `%s' installed (Version %s, Revision %S).%s"
(package-desc-name pkg-desc)
(lm-with-file main-file
(package-strip-rcs-id
(or (lm-header "package-version")
(lm-header "version"))))
(vc-working-revision main-file)
(if missing
(format
" Failed to install the following dependencies: %s"
(mapconcat
(lambda (p)
(format "%s (%s)" (car p) (cadr p)))
missing ", "))
"")))
t))