Subject: Re: bug#77468: 30.1.50; package-quickstart file is not relocatable

From: Spencer Baugh <[email-masked]>
Date: Tue, 08 Apr 2025 14:30:26 -0400

Stefan Monnier <[email-masked]> writes:

>>> We can just `setq` a private global var.  It's conceptually
>>> ugly, but it gets the job done.  As long as we support only a single
>>> global `package-quickstart.el` that should be good enough.
>> I guess you prefer this to the approach in the patch I sent, where I
>> let-bind default-directory outside the load of package-quickstart-file?
>
> Your approach is cleaner but I'm just worried that someone out there
> loads the package-quickstart file "by hand".

Ah, good point.  I'll just do the setq, see patch:

>From 4699b39c629433e295988a1695261ce3d56400ea Mon Sep 17 00:00:00 2001
From: Spencer Baugh <[email-masked]>
Date: Wed, 2 Apr 2025 17:21:24 -0400
Subject: [PATCH] Use relative names where possible in package-quickstart.el

package-quickstart.el hardcodes many absolute file names, which
makes it break if user-emacs-directory moves, or in other
situations.  To be slightly more robust to this, use relative
file names to packages that are located in the same directory as
package-quickstart.el.

* lisp/emacs-lisp/package.el (package--quickstart-dir,
package--quickstart-rel): Add.
(package-quickstart-refresh): Use package--quickstart-rel on
file names.  (bug#77468)
---
 lisp/emacs-lisp/package.el | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index b9a8dacab15..bec44a6b637 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -4591,6 +4591,19 @@ package--quickstart-maybe-refresh
     (delete-file (concat package-quickstart-file "c"))
     (delete-file package-quickstart-file)))
 
+(defvar package--quickstart-dir nil
+  "Set by `package-quickstart-file' to the directory containing it.")
+
+(defun package--quickstart-rel (file)
+  "Return an expr depending on `package--quickstart-dir' which evaluates to FILE.
+
+If FILE is in `package--quickstart-dir', returns an expression that is
+relative to that directory, so if that directory is moved we can still
+find FILE."
+  (if (file-in-directory-p file package--quickstart-dir)
+      `(file-name-concat package--quickstart-dir ,(file-relative-name file package--quickstart-dir))
+    file))
+
 (defun package-quickstart-refresh ()
   "(Re)Generate the `package-quickstart-file'."
   (interactive)
@@ -4605,7 +4618,8 @@ package-quickstart-refresh
         ;; aren't truncated.
         (print-length nil)
         (print-level nil)
-        (Info-directory-list '("")))
+        (Info-directory-list '(""))
+        (package--quickstart-dir nil))
     (dolist (elt package-alist)
       (condition-case err
           (package-activate (car elt))
@@ -4617,12 +4631,16 @@ package-quickstart-refresh
       (emacs-lisp-mode)                 ;For `syntax-ppss'.
       (insert ";;; Quickstart file to activate all packages at startup  -*- lexical-binding:t -*-\n")
       (insert ";; ¡¡ This file is autogenerated by `package-quickstart-refresh', DO NOT EDIT !!\n\n")
+      (setq package--quickstart-dir
+            (file-name-directory (expand-file-name package-quickstart-file)))
+      (insert (pp '(setq package--quickstart-dir
+                         (file-name-directory (expand-file-name load-file-name)))))
       (dolist (pkg package--quickstart-pkgs)
         (let* ((file
                 ;; Prefer uncompiled files (and don't accept .so files).
                 (let ((load-suffixes '(".el" ".elc")))
                   (locate-library (package--autoloads-file-name pkg))))
-               (pfile (prin1-to-string file)))
+               (pfile (prin1-to-string (package--quickstart-rel file))))
           (insert "(let* ((load-file-name " pfile ")\
 \(load-true-file-name load-file-name))\n")
           (insert-file-contents file)
@@ -4638,12 +4656,13 @@ package-quickstart-refresh
                   (append ',(mapcar #'package-desc-name package--quickstart-pkgs)
                           package-activated-list)))
           (current-buffer))
-      (let ((info-dirs (butlast Info-directory-list)))
+      (let ((info-dirs
+             (mapcar #'package--quickstart-rel (butlast Info-directory-list))))
         (when info-dirs
           (pp `(progn (require 'info)
                       (info-initialize)
                       (setq Info-directory-list
-                            (append ',info-dirs Info-directory-list)))
+                            (append (list . ,info-dirs) Info-directory-list)))
               (current-buffer))))
       ;; Use `\s' instead of a space character, so this code chunk is not
       ;; mistaken for an actual file-local section of package.el.
-- 
2.39.3