Looking to summarize a recent discussion on where to go from here. I've tried to go back and include some details from the thread but I likely missed some.
Expected user operations across cargo update and cargo upgrade
- Selective upgrade to latest compatible, latest incompatible, or user-provided version req
- Selective locking to a specific version
- Bulk upgrade to latest compatible
- Bulk upgrade to latest incompatible
- Selectively ignoring renamed dependencies as they are likely meant to be used with a specific major version (e.g.
tokio_03) - Selectively ignoring non-default version requirement operators as the user might have intended to pin things
- Selectively ignoring renamed dependencies as they are likely meant to be used with a specific major version (e.g.
Note: "compatible" and "incompatible" are relative to the version requirements and not semver (though thats the default version requirement operator)
cargo update today
- Works at workspace level
- Edits
Cargo.lock, notCargo.toml -
cargo update -p foo@ver,@veris used to disambiguatefoowithin the dependency tree (must be full version)-
--precise vertakes a full version for replacingverin the lockfile and must remain compatible -
--aggresiveto recursively updatefoo
-
Considerations:
- What do we optimize for (ie default)? For some workflows:
-
[[bin]]maintainers may want bulk updates of everything, most likely with a focus on compatible as incompatible might need hand updates -
[lib]normal/build deps: maintainers may want compatible updates by hand. incompatible bulk updates are good for checking of it works but sometimes they will need to be done by hand -
[lib]dev-only deps: like[[bin]]
-
- Upcoming MSRV-aware resolver (personally leaning towards this always being enabled)
-
-Zdirect-minimal-versions- Users may want to keep their lockfile and requirements in-sync so what gets tested locally is at least what your dependents will use
- This either requires a sticky
-Zdirect-minimal-versionsor a way to update requirements without updating the lockfile
Proposal 1: Deprecate cargo update in favor of cargo upgrade
-
cargo upgrade(formerlycargo update && cargo upgrade --to-lockfile) -
cargo upgrade --incompatible/cargo upgrade -i- Change version requirements to latest incompatible, leaving compatible versions the same
- Non-recursively updates lock file
- Ignores pinned dependencies
-
cargo upgrade -p foo- Change dep names "foo" (not dependency package names)
- Can be used with
-i,--pinned
-
cargo upgrade -p foo@verreq- Change dep names "foo" to the specified version req
-
Open question: is
--pinnedneeded?
-
Open question: what command handles the role of
cargo update -p foo --precise ver?
Proposal 2: Separate Commands
-
cargo upgradeonly does incompatible (formerlycargo upgrade --incompatible allow --compatible ignore) -
cargo update --savedoes compatible
Proposal 3: Merge Upgrade into Update
-
cargo updatestays the same except... -
cargo update --save(formerlycargo upgrade --incompatible false --compatible true)-
Concern: Inconsistency on whether
--saveis needed feels off to me
-
Concern: Inconsistency on whether
-
cargo update --incompatible(formerlycargo upgrade --incompatible true --compatible false) -
cargo update -p tokio_03de-sugars the dep name to package name + version (tokio@0.3.12) -
cargo update -p foo --precise ver-
Open question do we make a version requirement out of
--preciseand not allow controlling the precision or operators, do we hack up--precises behavior, or find a new flag? -
Open question if
veris incompatible, do your need--save,-i, or either?
-
Open question do we make a version requirement out of
-
Open question can add support for
cargo update --precise --saveto fully specify all version requirements -
cargo update && cargo update --save --lockedwould be an error, mirroringcargo adds behavior which has--lockedapply to the manifest as well
Note:
- All of these switch from being able to upgrade both compatible and incompatible in a single command to requiring two invocations. We are assuming that doing both is a low enough occurrence that the simplified set of flags for the more common cases justifies it
- We have not addressed users limiting actions to normal+build vs dev
- Cargo tree does this through the
--edgesflag which works when talking about graphs but not really in this context
- Cargo tree does this through the
- Can we correctly limit upgrades that would cause incompatible
links?- See cargo upgrade selects versions of native dependencies which are not compatible with transitive packages · Issue #844 · killercup/cargo-edit · GitHub
- Personally, just ran into a failure with this with
git2
- Do we bother allowing upgrading of pinned dependencies? Leaning towards "no"
- When only upgrading incompatible version requirements, if that forces a direct dependency to do a compatible upgrade, should we also update the version requirements?
I think the next step is updating cargo-edit to one of the proposals for us to gain first-hand experience with how it works out
- (1) and (2) would be easy to implement for just getting something better into people's hands
- (3) would be the most different in workflow and I suspect the one that we would learn the most from people using it even if I personally hope we don't go this route