Open purcell opened 6 years ago
P.S. Perhaps :ensure-noerror
would be a better name...
What could cause a package to be uninstallable? Would it be a platform specific or repository specific issue or something specific to a package not working properly?
Also what's the current behavior, would use-package stop loading the rest of the use-package forms in this case?
What could cause a package to be uninstallable? Would it be a platform specific or repository specific issue or something specific to a package not working properly?
If I try to :ensure
a package which depends on Emacs 25.2 in Emacs 25.1, for example.
In my personal config, which a bunch of crazy people seem to also use for some reason, I loosely support a wide range of Emacsen, but omit certain functionality if the host Emacs is not sufficiently recent.
Also what's the current behavior, would use-package stop loading the rest of the use-package forms in this case?
Yes, I believe so, but I haven't tested recently. When package.el
fails to install a package due to unresolved dependencies, I believe it looks the same to the startup elisp as if the machine were offline. IIRC package.el
can determine that a package will be uninstallable by looking at the local package archive info, so there shouldn't be constant network lookups at start-up time if there are use-package
forms containing unsatisfiable :maybe-ensure
flags.
Thanks for the explanation. I would be in favor of making :ensure
degrade gracefully when the Emacs version doesn't work (just like a falsey :if
or a missing dependency in a normal use-package
form), unless @jwiegley wants to keep this separate.
Yes, that might also make sense.
What do you guys want the default behavior to be? I don't use :ensure
.
Funnily enough I was just thinking of this today. For my money, I would like :ensure
to, well ensure, but if it fails to work equivalent to :disabled t
.
The scenario I hit most often is this. I update my .emacs using unison or other file sync tool. Then I hit the road, and try to run Emacs. During the file sync, I've pulled in something that adds an new ensure. Now I can't start Emacs cleanly, because I am offline. Instead I think use-package should issue warnings about failed ensures both otherwise leave a usable Emacs (minus the packages that It can't install).
The choice of default behaviour hinges on the question of whether a use-package
user should be able to (or should have to) specify ahead of time whether failing to install any given package will break their config. This seems quite at odds with the basic selling point of use-package
.
So probably the default should indeed be to have :ensure
soft-fail. The level of outrage it expresses is a separate question, then. If one uses this mechanism to make an emacs config degrade gracefully on older Emacsen in which certain packages can't be installed, then outright warn
calls would be overly intrusive. However, in @phillord's use case they're probably the best choice.
So how about a new defcustom
like use-package-ensure-failed-hook
(or -handler
), which would name a function to be invoked when a package cannot be ensure
d? The default would be to call warn
, but users could change this to produce either a hard error
, or a quiet message
? (Sophisticated users could presumably then let-bind this over certain use-package
forms if they really wanted to.)
I am actually in two minds about this. I am definately in favour of a hard-fail -- this is surely much better when you are getting your config sorted. A nice big breakage is just what you need -- a puny message hidden in the spam of a normal start up is not good. Otherwise, you think everything is fine then spend ages trying to work out what is happening when functionality that you think should be there is not.
Of course, I am also totally in favour of a soft-break when I am offline. In the ideal world, use-package should use esp.el
to work out which.
More sanely, I think a simple boolean would be enough. Looking though the code base, I realise that even this is not 100% necessary, since use-package already has a "what function should I call to do the ensure" variable. Does use-package not have any general variable saying whether things should be fail-fast or soft-fail? A single point of configuration probably makes more sense than 20 variables for each keyword.
A nice big breakage is just what you need
That's why I suggested something based on warn
as the default: it pops up a window that's hard to ignore, while stopping short of an outright error.
Looking though the code base, I realise that even this is not 100% necessary, since use-package already has a "what function should I call to do the ensure" variable.
Ah yes: use-package-ensure-function
! In that case, given the direction that this has been going, perhaps what we need is a use-package-ensure-elpa-noerror
as an alternative value for that defcustom
. Though it's not obvious to me if returning nil
from that would be sufficient to skip the entire use-package
form.
As it stands, no it wouldn't. One thing I did notice is that the require
form that is generated is surrounded by a condition-case-unless-debug
. Pushing the ensure
call into this would solve the problem.
I don't currently use
use-package
myself, but I was playing with it a while ago and wanted certainuse-package
clauses to degrade gracefully if the packages were uninstallable on the current host Emacs. I came up with the following, which someone might find useful, so I thought I'd post it here in case it would be a generally useful addition.