Paket: Confusion between "paket install" and "paket update"

Created on 29 May 2015  路  17Comments  路  Source: fsprojects/Paket

There's considerable overlap in the behavior of paket install and paket update, and some confusion on which one should be used in which situation.

Summary

  • paket update could also be called paket forget-everything-and-re-resolve (and-install-into-projects)
  • paket install could also be called paket only-update-packages-where-absolutely-necessary (and-install-into-projects)

Proposed solution: My intuition is that paket install should really be called paket update --pin-unchanged, because this is what it really does.

paket install does not really have a purpose anymore then, but should probably be kept for compatibility reasons. The documentation of paket install could then say: "paket install has the same effect as paket update --pin-unchanged". This would also remove the confusion between the two commands.

For completeness: The third use case (no updates to paket.lock) is already covered by another command:

  • paket restore could also be called paket do-not-update-versions-and-install-into-projects

Details:

Behavior of paket update:

  1. Delete paket.lock if it exists, therefore discarding the currently used versions of the packages (_UpdateProcess.Update_).
  2. Compute a new paket.lock file based on paket.dependencies (_UpdateProcess.SmartInstall/.SelectiveUpdate_)
  3. (Optionally:) Install everything from paket.lock (_InstallProcess.InstallIntoProjects_)

    Behavior of paket install:

  4. If no paket.lock file exists: Same behavior as paket update (it just calls _UpdateProcess. SmartInstall_)

  5. If a paket.lock file exists: (_UpdateProcess.SmartInstall/.SelectiveUpdate_)

    1. Compare paket.lock and paket.dependencies to find (_DependencyChangeDetection. findChangesInDependenciesFile_):



      • Dependencies that were added to paket.dependencies


      • Dependencies where the current version from paket.lock does not match the version requirement from paket.dependencies



    2. Pin all unchanged dependencies (i.e. the ones that are not newly added or modified)

    3. Compute a new paket.lock, taking into account the pinned dependencies.

  6. Install everything from paket.lock (_InstallProcess.InstallIntoProjects_)

    Behavior of paket restore:

  7. Install everything from paket.lock (_RestoreProcess.Restore_)

question

Most helpful comment

Your're right; I cross-checked RestoreProcess.Restore to verify this.

I incorporated your feedback into my proposal above. The original text is marked using strikethrough. Do you think it's better now?


To get the terminology clear (and to try to establish an ubiquituous language):

Explanation:
The relevant parts for the vocabulary are marked in bold.

  • "What the docs say" contains the wording for Paket's documentation.
  • "What is meant" contains the operations that actually take place.
  • "Verb" contains the command for paket (e.g. paket add) that realizes the domain operation from the first column.

| What the
docs say: | What is meant: | Verb |
| --- | --- | --- |
| Add/Install a package | _Add the package to paket.dependencies (and paket.references), update paket.lock as necessary,_ download _the package and_ update _the project files._ | add |
| ??? | _Add the package to paket.dependencies (and paket.references) and update paket.lock._ | add --no-install |
| Install all packages | _Update paket.lock as necessary,_ download _all packages and_ update _the project files._ | install |
| | | |
| Remove/Uninstall a package | _Remove the package from paket.dependencies (and paket.references), update paket.lock as necessary, delete the downloaded files and_ update _the project files._ | remove |
| ??? | _Remove the package from paket.dependencies (and paket.references) and update paket.lock as necessary._ | remove --no-install |
| | | |
| Update one or all packages | _Look for new versions of a single/all packages and write them into paket.lock (and_ download/install _them if not told otherwise)._ | update |
| Download the packages | _Download the .nupkg files into packages/ but do nothing else._ | restore |
| Update (the) project/s files | _Update the project files with the current DLL paths (and download them according to paket.lock if necessary)._ | (install) |

What's your feedback on the table above? Does it match the "mental model" of the expected end user?

All 17 comments

My mental model is based around this documentation from bundler:

bundle install
Install the gems specified by the Gemfile or Gemfile.lock

bundle update
Update dependencies to their latest versions

Bundler has no restore, but an existing Gemfile.lock + bundle install does basically the same as paket restore w.r.t. dependency resolution. As far as I understand, paket restore does not modify project files (a good thing), while paket install does.

Also, my understanding is that paket update does not simply forget the lockfile, since you can also update specific dependencies with paket update nuget foo.

To suggest a one-line documentation for the sake of this discussion:

paket install
Install the dependencies specified by the paket.dependencies or paket.lock file and update projects

paket restore
Install the dependencies specified by the paket.lock file

paket update [nuget foo]
Update one or all dependencies to their latest version and update projects

I like that these high-level commands exist and I feel that none of these should be replaced by a parameter.

I like your proposed one-line documentation, and I think that they avoid the confusion.
After finding the reason why paket install behaves the way it does in issue #777, I also think that its behavior makes sense.

So the only think that should be clarified is the documentation. I'd proprose the following extension to your one-line documentation (note that I'm looking for a more consice wording):

paket install
Install the dependencies specified by the paket.dependencies or paket.lock file and update projects

If the paket.dependencies file has been changed since the last update of the paket.lock file (e.g. added dependencies or changed version requirements), Paket will update the paket.lock file to make it match paket.dependencies again.

In difference to paket update, paket install will only look for new versions of dependencies that have been modified in paket.dependencies, and pin the versions of all other dependencies.

I think this matches quite well what the manpage of bundle install says:

Install the gems specified in your Gemfile(5). If this is the first time you run bundle install (and a Gemfile.lock does not exist), Bundler will fetch all remote sources, resolve dependencies and install all needed gems.

If a Gemfile.lock does exist, and you have not updated your Gemfile(5), Bundler will fetch all remote sources, but use the dependencies specified in the Gemfile.lock instead of resolving dependencies.

If a Gemfile.lock does exist, and you have updated your Gemfile(5), Bundler will use the dependencies in the Gemfile.lock for all gems that you did not update, but will re-resolve the dependencies of gems that you did update. You can find more information about this update process below under CONSERVATIVE UPDATING.

I didn't know the manpage of bundler yet; I think that I find their description more understandable than my proposal. Thanks for looking it up!

I also find it interesting that they use the term "conservative updating", because that one came to my mind, too.

what's the status here? do you propose to improve the docs? If so could you please send a PR. I think the distinction between update and install is very important.

My proposal would be to update the documentation for paket update andpaket install,paket restore` as proposed by agross and me. To sum it up:

paket install
Download Install the dependencies specified by the paket.dependencies or paket.lock file and update projects.

If the paket.dependencies file has been changed since the last update of the paket.lock file (e.g. added dependencies or changed version requirements), Paket will update the paket.lock file to make it match paket.dependencies again.

In difference to paket update, paket install will only look for new versions of dependencies that have been modified in paket.dependencies, and use the version from paket.lock for all other dependencies.

paket restore
Download and install the dependencies specified by the paket.lock file.

paket restore fails with an error if the paket.lock file does not exist. No packages are downloaded in that case. Please see paket install and paket update to learn how to create the paket.lock file.

paket update [nuget foo]
Update one or all dependencies to their latest version and update projects.

_Updating all packages_
If you do not specify a package, then all packages from paket.dependencies are updated.

First, the current paket.lock file is deleted. paket update then recomputes the current dependency resolution, as explained under Package resolution algorithm, and writes it to paket.lock. It then proceeds to download the packages and to install them into the projects.

Please see paket install if you want to keep the current versions from your paket.lock file.

$ paket update [--force|-f] [--hard] [--redirects] [--no-install]

_Updating a single package_
It's also possible to update only a single package and to keep all other dependencies fixed:

$ paket update nuget PACKAGENAME [version VERSION] [--force|-f] [--hard] [--redirects] [--no-install]

Note that the part after the italic headings should go into update.md.

I'm currently busy with my bachelor thesis, so it might take me some time to put the things above in a pull request. But it's definitely on my list.

IMO that description of paket restore is misleading. Restore does not install anything, it merely restores files which may be missing due to them being excluded from source control.

Your're right; I cross-checked RestoreProcess.Restore to verify this.

I incorporated your feedback into my proposal above. The original text is marked using strikethrough. Do you think it's better now?


To get the terminology clear (and to try to establish an ubiquituous language):

Explanation:
The relevant parts for the vocabulary are marked in bold.

  • "What the docs say" contains the wording for Paket's documentation.
  • "What is meant" contains the operations that actually take place.
  • "Verb" contains the command for paket (e.g. paket add) that realizes the domain operation from the first column.

| What the
docs say: | What is meant: | Verb |
| --- | --- | --- |
| Add/Install a package | _Add the package to paket.dependencies (and paket.references), update paket.lock as necessary,_ download _the package and_ update _the project files._ | add |
| ??? | _Add the package to paket.dependencies (and paket.references) and update paket.lock._ | add --no-install |
| Install all packages | _Update paket.lock as necessary,_ download _all packages and_ update _the project files._ | install |
| | | |
| Remove/Uninstall a package | _Remove the package from paket.dependencies (and paket.references), update paket.lock as necessary, delete the downloaded files and_ update _the project files._ | remove |
| ??? | _Remove the package from paket.dependencies (and paket.references) and update paket.lock as necessary._ | remove --no-install |
| | | |
| Update one or all packages | _Look for new versions of a single/all packages and write them into paket.lock (and_ download/install _them if not told otherwise)._ | update |
| Download the packages | _Download the .nupkg files into packages/ but do nothing else._ | restore |
| Update (the) project/s files | _Update the project files with the current DLL paths (and download them according to paket.lock if necessary)._ | (install) |

What's your feedback on the table above? Does it match the "mental model" of the expected end user?

very cool

Is there a single-command way to update only the non-version-locked dependencies and restore everything else? I know I can make a group (and I will if I have to), but I'd love it if this was a built-in function.

I don't really understand. Can you create a new issue with concrete sample?

@forki, possibly. I'm still trying to wrap my head around it -- we were using ripple, before, and that was my first exposure to dependency management, and I've been asked to research and determine whether Paket can be a replacement for it. The answer is a definite yes, but I need to figure out what is similar / different between the two.

So, to answer your question, by the time I know enough to really make an example, I may already know the answer.

ok. maybe you can rephrase the question then?

Small reaction to this old issue, the table from https://github.com/fsprojects/Paket/issues/848#issuecomment-109312241 would actually make a nice summary to the docs as an overview

@CumpsD PRs very welcome!

If you can confirm the table is correct i can make a PR

we will review on the PR again - and discuss wording

Was this page helpful?
0 / 5 - 0 ratings

Related issues

palutz picture palutz  路  6Comments

matthid picture matthid  路  6Comments

renangms picture renangms  路  5Comments

purkhusid picture purkhusid  路  8Comments

haraldsteinlechner picture haraldsteinlechner  路  4Comments