Feedback on `cargo-upgrade` to prepare it for merging

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

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, not Cargo.toml
  • cargo update -p foo@ver, @ver is used to disambiguate foo within the dependency tree (must be full version)
    • --precise ver takes a full version for replacing ver in the lockfile and must remain compatible
    • --aggresive to recursively update foo

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-versions or a way to update requirements without updating the lockfile

Proposal 1: Deprecate cargo update in favor of cargo upgrade

  • cargo upgrade (formerly cargo 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 --pinned needed?
  • Open question: what command handles the role of cargo update -p foo --precise ver?

Proposal 2: Separate Commands

  • cargo upgrade only does incompatible (formerly cargo upgrade --incompatible allow --compatible ignore)
  • cargo update --save does compatible

Proposal 3: Merge Upgrade into Update

  • cargo update stays the same except...
  • cargo update --save (formerly cargo upgrade --incompatible false --compatible true)
    • Concern: Inconsistency on whether --save is needed feels off to me
  • cargo update --incompatible (formerly cargo upgrade --incompatible true --compatible false)
  • cargo update -p tokio_03 de-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 --precise and not allow controlling the precision or operators, do we hack up --precises behavior, or find a new flag?
    • Open question if ver is incompatible, do your need --save, -i, or either?
  • Open question can add support for cargo update --precise --save to fully specify all version requirements
  • cargo update && cargo update --save --locked would be an error, mirroring cargo adds behavior which has --locked apply 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 --edges flag which works when talking about graphs but not really in this context
  • Can we correctly limit upgrades that would cause incompatible links?
  • 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
1 Like