Original issue: #6667
Implementation PR: #6798
Documentation: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#install-upgrade
Summary
Instead of failing when cargo install detects a package is already installed, it will upgrade if the versions don't match, or do nothing (exit 0) if it is considered "up-to-date".
cargo +nightly install foo -Z install-upgrade
Unresolved questions
Cargo.lock, mtime for path sources, etc). The current set was chosen to be practical and simple and should cover most use cases. Otherwise --force is intended as a workaround for more advanced requirements.--no-track be kept, or is there a better approach for packaging? Does it have the right behavior? See also #3316.Should there be a way to upgrade all outdated packages? (See #6667 for more about this.)
That's probably a different feature right? Or why would we need to resolve this as part of this one?
If a new version of a package drops a binary, should those dropped binaries be uninstalled when the new package is installed? Currently it only replaces binaries.
I think this should behave like uninstalling the package, and then installing the newer one, so that would mean that yes, this should do that. Having said this, printing a warning: ... when this happens wouldn't hurt (as long as there is a quiet mode available).
That's probably a different feature right? Or why would we need to resolve this as part of this one?
Yea, in my original proposal I indicated it should probably be separate. I just included it here for completeness in case people felt it was important.
I think this should behave like uninstalling the package
That sounds good to me.
My perspective here is mostly that of an end-user, but having just read through the implementation PR I do have some opinions on these questions:
- Is it tracking the correct information?
As you note, the current set (at least what is listed there) seems to me to be a pretty good set of distinguishers between versions. I was personally only thinking about versions as being criteria鈥攖his set also covers more information. It might be nice to update _all_ installations that match the given criteria. For example, if I've installed for target A and target B of crate foo, I'd expect cargo install foo to see both targets updated, or tell the user that it wants a specific install to operate on.
- Should there be a way to upgrade all outdated packages?
I think so, but I don't see a way to make this fit with the verbiage cargo install. I think a separate subcommand (cargo upgrade/cargo update, for example) that checks installed packages for updates and makes them happen would be best. Since the information you store has a big installs key, I think this should be somewhat straightforward.
- Should
--no-trackbe kept, or is there a better approach for packaging? Does it have the right behavior?
Based on the description given, I think it's just about right. For packaging, I personally am of the mind that --no-track is a good option to prevent pollution. The documentation or name could be changed; --no-track indicates to me instead that the installation will not be tracked by some analytics engine. Perhaps --no-store-installs-metadata or something more concise?
In building Docker images with Crates, I think having --no-track is a sane option; though I think the tendency is to just ignore the ~/.cargo directory entirely. So it might not be necessary, but could definitely be of use.
- Should this be the new default? Should there be an option to disable upgrades and revert to the old behavior?
For the cargo install subcommand, I absolutely think so. This will require some education through documentation changes, but I think many users that come from other languages like JS/Ruby prefer this ergonomic over a flag that they have to pass to explicitly enable the behavior. This would also fall under the same token as that which make install users would be used to; generally install targets that I have seen in the wild will overwrite existing artifacts with no concern.
I could definitely see a cargo install --install-only or cargo install --no-upgrade that dies if something is already installed. But then again, I also think cargo install could just be assumed to install the latest version, as I don't think many users who are installing things globally via cargo install would care if a second iteration overwrites.
- If a new version of a package drops a binary, should those dropped binaries be uninstalled when the new package is installed? Currently it only replaces binaries.
I think replacement of remaining binaries is fine, with a warning added indicating that binaries were dropped. Though, since doing so would require comparison of the former and latter states anyhow, it might just be better to uninstall dangling binaries and warn the user that you did that. This could also be toggleable behavior. (Proposal: --keep-dangling.)
There is one additional item鈥擨 would like the final version of this feature to just reuse $CARGO_HOME/.crates.toml, but with a [v2] key, if possible. I wasn't sure if this was part of the plan, but I think it'd be the cleanest end-result.
I would've preferred this as a flag like: cargo install --upgrade but this is still good, any plans for stabilization?
Will this also compile the crate with the nightly toolchain? Is there a way to use the install-upgrade command from nightly but compile the actual crate with stable?
@kathampy This feature is nightly-only until it is stabilized.
- Should there be a way to upgrade all outdated packages?
I do think it is important to have. 鉂わ笍
I think we could adapt what pip do here about the command line flag.
-U, --upgrade Upgrade all specified packages to the newest available version. The handling of dependencies depends on the upgrade-strategy used.
--upgrade-strategy <upgrade_strategy>
Determines how dependency upgrading should be handled [default: only-if-needed]. "eager" - dependencies are upgraded regardless of whether the currently installed version satisfies the requirements of the upgraded package(s). "only-if-
needed" - are upgraded only when they do not satisfy the requirements of the upgraded package(s).
Also, do we have any plan to stabilize this feature in near future?
Determines how dependency upgrading should be handled
I am not following what this option has to do with Cargo. This feature is for installing binary packages and dependencies are not installed in a separate fashion (AIUI). Are you proposing that this subcommand will reinstall the binary package if _any_ of its dependencies have updated since the binary was compiled? Do we even track that information?
I have posted a proposal to stabilize at #7560.
Most helpful comment
I do think it is important to have. 鉂わ笍