radian-software / straight.el

🍀 Next-generation, purely functional package manager for the Emacs hacker.
MIT License
2.72k stars 150 forks source link

Signal warning if ~/.emacs.d/elpa exists #1036

Open raxod502 opened 1 year ago

raxod502 commented 1 year ago

Due to behavior of Emacs that we can't change, if the user has installed package(s) via package.el in the past, then they will be loaded at init, even if the user intends to use straight.el instead to manage packages. This behavior can be disabled with (setq package-enable-at-startup nil) in early-init.el, but the cause of the issue is often unclear.

Given that loading packages from both package.el and straight.el in parallel is not a common use case to my knowledge, I suggest that straight.el should signal a warning by default if ~/.emacs.d/elpa exists, notifying the user that they may wish to delete or move that directory to avoid unexpected (versions of) packages being loaded. I suggest also that there be some configuration option which can be used to suppress the warning if the user for some reason does desire this dual loading behavior.

See, e.g.: https://github.com/radian-software/straight.el/issues/1019#issuecomment-1368578607

progfolio commented 1 year ago

I wonder if the warning should be conditioned on the presence of the package feature instead. This would catch more cases and should be simpler to test. e.g.

(when (and straight-warn-if-other-package-manger (featurep 'package))
  (warn "Loading package.el alongside straight.el may cause conflicts"))

Or, an alternative, extensible approach:

(defcustom straight-incompatibility-warnings
  `((,(apply-partially #'featurep 'package) .
     "Loading package.el alongside straight.el may cause conflicts"))

  "Alist of form: (PREDICATE . WARNING).
Each element is tested for when loading straight.el.
If PREDICATE returns non-nil, WARNING is issued.
Setting this to nil will disable all such warnings."
  :type 'alist)

;; when loading straight.el
(cl-loop for (pred . warning) in straight-incompatibility-warnings
         when (funcall pred) do (warn warning))
raxod502 commented 1 year ago

Ah, sure, that seems reasonable. I guess per this code in startup.el:

  ;; If any package directory exists, initialize the package system.
  (and user-init-file
       package-enable-at-startup
       (not (bound-and-true-p package--activated))
       (catch 'package-dir-found
     (let ((dirs (cons package-user-dir package-directory-list)))
       (dolist (dir dirs)
         (when (file-directory-p dir)
           (dolist (subdir (directory-files dir))
         (when (let ((subdir (expand-file-name subdir dir)))
                         (and (file-directory-p subdir)
                              (file-exists-p
                               (expand-file-name
                                (package--description-file subdir)
                                subdir))))
           (throw 'package-dir-found t)))))))
       (package-activate-all))

The package feature is only loaded when the directory exists. The warning should probably explain that the simplest way to disable package.el in most cases is to delete ~/.emacs.d/elpa, but conditioning it on the feature rather than the directory seems sensible.