Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature request] Support package snapshot #298

Closed
weihanglo opened this issue Apr 16, 2021 · 9 comments
Closed

[Feature request] Support package snapshot #298

weihanglo opened this issue Apr 16, 2021 · 9 comments

Comments

@weihanglo
Copy link

Sometimes upgrading packages may results in conflicts between packages. By having a snapshot of all current packages with exact commits, we can restore from the snapshot without much labor.

Reference: vim-plug supports snapshot.

@wbthomason
Copy link
Owner

Thanks for the idea and reference! I'd be happy to help guide a PR implementing this (it should be pretty straightforward), if you or anyone else is interested.

@weihanglo
Copy link
Author

Yes, I can help! It would be awesome to have some instruction.

@c3n21
Copy link
Contributor

c3n21 commented May 22, 2021

Since already a month has passed and there isn't any progress I would like to step-in and make this feature (since I need this too).

The idea I had is the following:

  • create a PackerSnapshot command which can take an optional argument which will be the name of the snapshot (all the plugins will be snapshotted except the disabled ones)
  • create a PackerRollback command which takes an argument and what it does is rollback to the given snapshot (with autocompletion for the snapshots' names which is nice)
  • create a PackerDelete command which deletes a snapshot given the name
  • in the config we could add an option to enable automatic snapshot after each PackerInstall or PackerUpdate or PackerClean
  • eventually add a timer which deletes old snapshots created automatically after installs, updates and cleans (so snapshots created with a name will be saved permanently unless the user wants to delete it)

How does this sound to you @wbthomason @weihanglo ?

Edit: I've forgot to mention that the snapshot will create a file (maybe Json?) and it will associate plugin name with the commit's hash and the branch used. The rollback operation will just hard reset to the commit specified in the snapshot

@bew
Copy link

bew commented May 22, 2021

me, dropping in from nowhere, hi! 👋

Imo this gives too much intelligence to the snapshot system.

Taking inspiration from vim-plug, I like how it only generates a simple vim file with 1 line for each plugin, specifying it's name and the revision.
And the file content is in a scratch buffer, it's not saved anywhere the plugin knows about. If I want to keep it I can hit :w some_place.vim and manage the snapshot file however I want.

(here is an example snapshot: https://github.com/bew/dotfiles/blob/0d74848b7d8fde734c2ad47e7b4e78e27f43a3b0/nvim/plugins.lock)

And when you want to restore a snapshot, you simply have to :source some_place.vim, this will source the snapshot and fill a special vim dictionary, and then force update all the plugins to the versions in the snapshot.

In packer's case the snapshot file could be in Lua, but the general idea could be kept I think. Unless there are specific things for packer? (I don't actually use it currently, but I'm keeping my third eye on it I'd say)

What do you think of this?

@c3n21
Copy link
Contributor

c3n21 commented May 22, 2021

me, dropping in from nowhere, hi! wave

Imo this gives too much intelligence to the snapshot system.

Taking inspiration from vim-plug, I like how it only generates a simple vim file with 1 line for each plugin, specifying it's name and the revision.
And the file content is in a scratch buffer, it's not saved anywhere the plugin knows about. If I want to keep it I can hit :w some_place.vim and manage the snapshot file however I want.

(here is an example snapshot: https://github.com/bew/dotfiles/blob/0d74848b7d8fde734c2ad47e7b4e78e27f43a3b0/nvim/plugins.lock)

And when you want to restore a snapshot, you simply have to :source some_place.vim, this will source the snapshot and fill a special vim dictionary, and then force update all the plugins to the versions in the snapshot.

In packer's case the snapshot file could be in Lua, but the general idea could be kept I think. Unless there are specific things for packer? (I don't actually use it currently, but I'm keeping my third eye on it I'd say)

What do you think of this?

I was actually happy with that system since I've been using VimPlug for a while and I loved that snapshot feature, for me it would be fine.

However I feel like packer is not as minimalist as vim-plug since it can manage config files, extensions' dependencies and other features that are not strictly necessary for a plugin manager.
I believe that packer resembles more something like a package manager, and having a builtin API to manage snapshots would make sense for me (or maybe support them via extension?)

@weihanglo
Copy link
Author

I have an almost identical opinion as what @bew's said. A dumb snapshot system is great enough to me. It is also simpler to implement. Therefore I propose that at this moment the snapshot system aligns to a simple design, and we'll then wait for feedback to decide the next iteration.

@bew
Copy link

bew commented May 27, 2021

@wbthomason Hi, what's your take on this? dumb/simple snapshot system vs a 'complex' one?

Personally the dumb system is all I want, so I can use git to track plugin versions change and use the same plugins on multiple systems

@wbthomason
Copy link
Owner

@bew There's a bit more discussion on #370, but: I favor a sort of middle ground, at least to start. I think we want snapshots to be closer to plug's "list of commits" (though this may change later if we want to persist configuration variables, etc.), and I'm fine with having a set of PackerSnapshot, PackerRollback, PackerSnapshotDelete commands to make management a bit easier, but I don't think we want to add more complexity like automatic timed deletion, etc. - really, nothing more complex than handling saving the snapshot file for you.

All this said, I never used the snapshot feature (in plug or anything else) when I used other plugin managers, so I may not have a good intuition for what complexity is necessary/useful and what just adds bloat.

tl;dr: I think we want plug-like simple snapshots, but I'm fine also adding management commands (without any automatic management like auto-deletion).

wbthomason added a commit that referenced this issue Feb 25, 2022
Thanks @c3n21!

* feat(snapshot)

Add snapshotting feature

* fix(snapshot)

Set (stdpath 'cache')/packer as default snapshot path location

* fix(rollback)

Fixed revert = nil

* fix(rollback): working

* modify(packer): packer.snapshot and packer.rollback use f-args

* refactor(packer)

* snapshot_path changed to stdpath("cache")/packer.nvim
* using vim.loop.fs for snapshot_complete

* refactor: packer, snapshot, git

* using vim.loop functions to write files
* refactor of snapshot as a module
* refactor of async function of git module

* fix(git): revert_to

* now it works

* refactor(packer, snapshot)

* renamed snapshot() to create()
* moved snapshot completion functions into `snapshot` module
needs `config.snapshot_path`
* set default snapshot to nil
* initialize snapshot module in packer.startup to avoid errors with `config` table not being available

* test(snapshot): fixed tests

* test(snapshot): fix

* doc(snapshot): update snapshot feature docs

* refactor(snapshot): rename PackerRollback, PackerDelete commands

Renamed commands:
* PackerRollback -> PackerSnapshotRollback
* PackerDelete -> PackerSnapshotDelete

* docs(snapshot): update commands name

* refactor(snapshot): add notify on snapshot/rollback complete

* refactor(snapshot): using JSON for snapshot files

* fix(snapshot): automatically create stdpath('cache')/packer.nvim

* test(snapshot): WIP

* fix(snapshot)

Fixed bug in PackerSnapshotRollback that when provided a snapshot name
it will first look in the root of `packer.nvim`, and then in `config.snapshot_path`
which can cause some issues if there are other files named the same as
the snapshots inside the root of `packer.nvim`

* test(snapshot): WIP

* test(snapshot): cleanup and fix

* fix(snapshot): can't rollback if snapshot is older than repo

* snapshot.rollback() will first run `git fetch --depth 999999 --progress` to fetch the history, and then rollback

* Update Neovim versions for testing

* Attempt to fix snapshot tests by using proper async function

* refactor(snapshot)

* refactor(snapshot)

* chore: format with stylua

* refactor(snapshot)

* when taking a snapshot, if `snapshot_name` exists the user will be asked if they want to
  overwrite the existing snapshot
* better error handling
* packer.snapshot() will default to '%Y-%m-%d' if no snapshot name is
  provided

* chore: format with stylua

* refactor(snapshot)

* when taking a snapshot, if `snapshot_name` exists the user will be asked if they want to
  overwrite the existing snapshot
* better error handling
* packer.snapshot() will default to '%Y-%m-%d' if no snapshot name is
  provided

* refactor(snapshot)

snapshot.delete is not async

* refactor(snapshot): improved async logic of rollback

* build

Dockerfile:
* added non-root user `test`
* added entrypoint to automatically run `make test` inside archlinux
  container
* copy packer.nvim directly into the container

Makefile:
* added run and run-tests to quickly run tests inside the container

Co-authored-by: Wil Thomason <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@weihanglo
Copy link
Author

Since #370 is merged and it works for me, I am going to close this issue.
Thanks @c3n21 for making this landed. Also thanks you all reviewers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants