cli
cli copied to clipboard
Add option to install from a local file
Rationale
- I want to do
eask install --local ./some/path. - But how do I get fresh changes from
./some/path, do I reinstall for every change? - No: Have Eask install whenever
package-initializeis run! - But how does Eask know which packages to reinstall and from where?
- Add local state
Changes
Adds --local option to eask install. All args are interpreted as paths in that case.
Adds a few functions that save data in .eask/ver/eask-state.el:
(eask-read-state-var 'local-packages) ;; alist of package-name to path
(eask-set-state-var 'local-packages '((foo . "./some/path")))
(eask--save-state) ;; this is added to post-command-hook
Reinstalls saved 'local-packages whenever eask-pkg-init is called.
Notes
- Might need to put the reinstall step somewhere other than
eask-pkg-initif performance is bad - Haven't tested it a lot
TODOs
- [ ] uninstall a local package
- [ ] display local package source in
eask list - [ ] test adding a file to a local package
- [ ] test adding a dependency to a local package
- [ ] add integration tests
- [ ] update doco
- cmd docs
- hugo docs
Maybe we should have a new command eask install-file [paths..] (name came from package-install-file).
I recommend we store eask--state-alist in Eask-file since eask-state.el can be lost after eask clean workspace. π€
How about?
(depends-on "foo-mode" :local "/path/to/foo-mode")
And handle local packages right before https://github.com/emacs-eask/cli/blob/master/lisp/_prepare.el#L1514.
Could you check out #317? I hope it's what you're looking for! π
You can now install it with:
# directory
eask install-file /path/to/foo-mode
# .tar file
eask install-file /path/to/foo-mode.tar
# .el file
eask install-file /path/to/foo-mode.el
In Eask-file:
(depends-on "foo-mode" :file "/path/to/foo-mode")
Now it becomes the dependency to your project, then do eask install-deps.
Haha this is a complex feature... because it's really 3 related features:
- packages installed from a local file
- packages that are reinstalled every run
- packages that are installed but not saved in the eask file
I think we should use both #316 and #317, but should work out the naming of commands and options to present all these features to the user in the least confusing way.
I'll refer to these use cases below:
- local install user installs from a file AND saves it in the eask file
e.g. using a dependency in a git submodule or a using eask to manage
~/.emacs.d - local override user installs from a file but DOESN'T save it in the eask file e.g. testing changes to a dependency, or simultaneously working on packages
- npm link when the user has an archive of local packages which can be installed by name
So, this PR enables local override (and perhaps npm link), but #317 enables local install -- both are useful features, but how do we organize them?
Local Install by Linking
First let's look at the "npm link" use case. I think this is optional to support. (We could implement it by using the save-state helpers in this commit to save links in the global eask folder). If we decided to make it, then it would make sense to redefine eask link to match. Then the other two use cases would look like
# in ./json-mode
eask link # json-mode -> ./path/to/json-mode stored in ~/.eask/eask-state.el
# in ./foo-mode
# local install
# user manually add (depends-on json-mode) to Easkfile
eask install-deps # fails to install json-mode
eask link add json-mode
eask install-deps # succeeds, but is not required after link add
# local override
# no depends-on in Easkfile, link is temporary
eask link add json-mode
Note that there are no necessary changes to eask install in this case!
It might make sense to expose the "reinstalled every run" feature by having, say, eask install-file mean "install once, do not reinstall" and eask link add mean "reinstall every run".
Commands or Options
Now assume we are not using the "npm link" use case, and just consider the remaining two use cases. How should the commands and options be organized?
The most flexible choice is to use options for the eask install command. Then the user is free to use any combination of the options. The risk is that some combinations don't make sense, or that the meaning of different combinations is too confusing.
Here's how the use cases would look when using options:
- local override
eask install --source=local --temp ./path/to/json - local install
eask install --source=local ./path/to/json - reinstall as an option
eask install --source=local --reinstall ./path/to/json
New cases that are possible with these options:
eask install --temp ivyeask install --reinstall ivyeask install --source=github abo-abo/swipergenerates a recipe in the Eask file
The other alternative (suggested in #317) is to use separate commands per install source. This is a good choice if we want to focus the functionality of the commands. For example, if we decide that a local install must always reinstall, it makes no sense to have --reinstall, and eask install-file will imply that feature.
We could write down the equivalent command/option versions
eask link-file ./path/to/jsoniseask install --source=local --temp ./path/to/jsonnote: I addedlink-fileso thatinstallalways means "change the Eask file"eask install-file ./path/to/jsoniseask install --source=local ./path/to/json
If you think of commands like link-file and install-file as aliases for groups of options, then we just need to decide which options are sensible, which groups of options are valid, and what to call those groups.
Summary
I think these are the decisions:
- should we implement the "npm link" use case at all? (this will affect the next decisions)
- should
--temp(don't save in Eask file) be a user option? - should
--reinstallbe a user option? - do we prefer
eask install --source=fileoreask install-file - are the extra features implied by new options worth supporting?
I hope you enjoyed my essay ;)
Let's break this down a little. There are too many features at a time right now. π¬
Things to clarify:
eask install-fileinstalls packages temporarily, making it available only within the workspace. To make it a permanent dependency, you need to add it to your Eask-file, allowing installation viaeask install-deps.eask install-fileintegrates withpackage.el, so theeask listcommand will function as expected.- There is currently no
reinstallexcept the commandeask reinstall. We can use--forceflag toeask install-file --force /path/to/foo-modeto force reinstall it.
It might make sense to expose the "reinstalled every run" feature by having, say, eask install-file mean "install once, do not reinstall" and eask link add mean "reinstall every run".
I'm confuse here. link is a command that creates a link to elpa directory and that's it. There is really no installation going on. You would need to use eask link delete to remove the link or eask clean workspace to remove entire .eask folder. π€
What I currently have in mind:
- Install file temporarily (fresh): -
eask install-file - Install file every run (fresh): -
eask install-file --force - Install once (not fresh): -
eask link add
Furthermore, you only need to change Eask-file when you want your users to install via eask install-deps.
(depends-on "foo-mode" :file "/path/to/foo-mode") ; Force your users to install it so it cannot go wrong!
Not mentioning link now, I think it's can be a separate issue/PR. :)
There are too many features at a time right now.
Fair enough, I'm trying to think of features we might want so that changes we make now don't block other possibilities.
It is definitely possible to just make "adds a file package" as a feature and "automatic reinstall" a later feature. This PR was mainly about showing that both are possible.
I'm confuse here. link is a command that creates a link to elpa directory and that's it. There is really no installation going on.
Again, I'm trying to think of how it should work. So I'm ignoring how commands work for now and thinking about how a user, looking only at the docs, will think that they work. Sorry for not clarifying that.
Install file every run (fresh): - eask install-file --force
This reads as though you are reinstalling the file just once? Or do you mean it will make Eask automatically install it every run?
What I currently have in mind
Putting on my "silly user" hat :billed_cap:, I would ask these questions:
- I can install a file temporarily and a file is just a package, so how can I install a package (from an archive) temporarily?
- When I
eask install packageit helpfully adds adepends-onform, but how can I automatically add that for a file? - What does
eask install --forcedo?
This reads as though you are reinstalling the file just once? Or do you mean it will make Eask automatically install it every run?
Oops, I meant to install it just once. Use eask install-deps βforce on every run.
I can install a file temporarily and a file is just a package, so how can I install a package (from an archive) temporarily?
What do you mean temporarily? π€ My definition in this context means you install it once but cannot install it with eask install-deps since it's not listed in the Eask-file.
Assuming we have the exact definition, you have these options:
eask install(from archive)eask install-vc(directly from repo)
When I eask install package it helpfully adds a depends-on form, but how can I automatically add that for a file?
It does not. I hope I have this feature, but it's not easy to implement with my current implementation. π π₯² I can explain why, but this is currently out of scope.
What does eask install --force do?
It lets you overwrite installed packages (reinstall). If the package is not installed, just install it.
ββ-
No worries! I am trying to understand your needs. ππ
This might not be exactly the same, but I wanted to let you know that global scope packages are now treated as system packages by default (via the package-directory-list variable). This change gives users greater control over which packages they want to use and reuse. :)
The commit changes is in e0732f26a179ccceed96528cc71d9903b2f5fe4e.