From 7362674bb69d0206c9d55e727602a5ba519dde4b Mon Sep 17 00:00:00 2001
From: Radon Rosborough <radon.neon@gmail.com>
Date: Sun, 13 Jan 2019 20:44:15 -0700
Subject: [PATCH] Only signal package.el warnings when needed

Previously, `package-initialize' signaled a warning whenever it was
called more than once during startup.  This was annoying to users.
Now, `package-initialize' simply does nothing on a second call, so it
"just works" without any configuration changes by users.

Advanced users may have customized `package-load-list',
`package-user-dir', or `package-directory-list' in their init-file
before calling `package-initialize', in which case this new behavior
would be incorrect.  To remedy that problem, we still signal a warning
when the value of one of those variables has changed since the last
time `package-initialize' was called, but we dutifully perform the
reinitialization so that their configuration will continue to work.

Such advanced users will probably want to set
`package-enable-at-startup' to nil in their early init-file (see
`early-init-file').  This will suppress the warning as a byproduct.

* lisp/emacs-lisp/package.el (package-initialize): Skip
reinitialization unless the values of relevant user options have
changed, and signal a warning in that case (but not otherwise).
(package--user-option-values): New variable, to check whether the
values of relevant user options have changed.
---
 lisp/emacs-lisp/package.el | 61 ++++++++++++++++++++++++++------------
 1 file changed, 42 insertions(+), 19 deletions(-)

diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index cf39fa2896..0bb45addd5 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -1445,6 +1445,11 @@ package-read-all-archive-contents
 ;; available on disk.
 (defvar package--initialized nil)
 
+(defvar package--user-option-values nil
+  "Values of user options last time `package-initialize' was called.
+This is an alist whose keys are symbols naming user options and
+whose values are the previous values of those symbols.")
+
 ;;;###autoload
 (defun package-initialize (&optional no-activate)
   "Load Emacs Lisp packages, and activate them.
@@ -1458,26 +1463,44 @@ package-initialize
 individual packages after calling `package-initialize' -- this is
 taken care of by `package-initialize'.
 
-If `package-initialize' is called twice during Emacs startup,
-signal a warning, since this is a bad idea except in highly
-advanced use cases.  To suppress the warning, remove the
-superfluous call to `package-initialize' from your init-file.  If
-you have code which must run before `package-initialize', put
-that code in the early init-file."
+If `package-initialize' is called more than once with different
+values for the user option `package-load-list',
+`package-user-dir', or `package-directory-list', signal a
+warning.  The most likely cause of this warning is that Emacs
+calls `package-initialize' before loading the early init-file,
+then you adjust one or more of these user options and call
+`package-initialize' again.  To prevent Emacs from calling
+`package-initialize' with the wrong options before loading your
+init-file, set `package-enable-at-startup' to nil in your early
+init-file (see `early-init-file')."
   (interactive)
-  (when (and package--initialized (not after-init-time))
-    (lwarn '(package reinitialization) :warning
-           "Unnecessary call to `package-initialize' in init file"))
-  (setq package-alist nil)
-  (setq package-enable-at-startup nil)
-  (package-load-all-descriptors)
-  (package-read-all-archive-contents)
-  (setq package--initialized t)
-  (unless no-activate
-    (package-activate-all))
-  ;; This uses `package--mapc' so it must be called after
-  ;; `package--initialized' is t.
-  (package--build-compatibility-table))
+  (let ((variable-changed
+         (cl-dolist (link package--user-option-values nil)
+           (unless (equal (symbol-value (car link)) (cdr link))
+             (cl-return (car link))))))
+    (when (and package--initialized variable-changed)
+      (lwarn
+       '(package reinitialization) :warning
+       "Package.el reinitialized with changed value for `%S' (%S -> %S)"
+       variable-changed
+       (alist-get variable-changed package--user-option-values)
+       (symbol-value variable-changed)))
+    (unless (and package--initialized (not variable-changed))
+      (setq package-alist nil)
+      (setq package-enable-at-startup nil)
+      (package-load-all-descriptors)
+      (package-read-all-archive-contents)
+      (setq package--initialized t)
+      (unless no-activate
+        (package-activate-all))
+      ;; This uses `package--mapc' so it must be called after
+      ;; `package--initialized' is t.
+      (package--build-compatibility-table)
+      (dolist (var '(package-load-list
+                     package-user-dir
+                     package-directory-list))
+        (setf (alist-get var package--user-option-values)
+              (symbol-value var))))))
 
 (defvar package-quickstart-file)
 
-- 
2.20.1

