142

I used cargo install to globally install a package, such as rustfmt or racer.

How can I update the installed package without first deleting it ( cargo uninstall) and then running cargo install again.

Is there an update command?

Avindra Goolcharan
  • 4,032
  • 3
  • 41
  • 39
w.brian
  • 16,296
  • 14
  • 69
  • 118

5 Answers5

194

There is no such command in vanilla cargo (well, there's cargo install but that's for dependencies), but since cargo supports third-party subcommands there is an answer: the cargo-update crate.

Install as usual with

cargo install cargo-update

then use

cargo install-update -a

to update all installed packages, for more usage information and examples see the cargo install-update manpage.

Disclaimer: am author

Nico Schlömer
  • 53,797
  • 27
  • 201
  • 249
набиячлэвэли
  • 4,099
  • 4
  • 29
  • 40
84

As of Rust 1.41.0, you can use the following command to update crates to their latest version:

cargo install <crate>

This came from pull request #6798 (Add install-upgrade) and was stabilized in #7560 (Stabilize install-upgrade).

How does it work?

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".

Forcing an upgrade / re-installation

The following command will always uninstall, download and compile the latest version of the crate - even if there's no newer version available. Under normal circumstances the install-upgrade feature should be preferred as it does save time and bandwidth if there's no new version of the crate.

cargo install --force <crate>

Documentation

Further information can be found in the GitHub issue rust-lang/cargo#6797 and in the official documentation chapter.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Nicolai Fröhlich
  • 51,330
  • 11
  • 126
  • 130
  • Will this also compile them with nightly? – Monstieur Aug 21 '19 at 14:39
  • 1
    This is now stabilized, and the default behavior. You no longer need to use the nightly channel or provide the `-Z install-upgrade` argument. https://github.com/rust-lang/cargo/pull/7560 – Rag Jan 10 '20 at 11:09
  • 1
    If you wish to update all packages a simple shell command such as `cargo install --list | grep '^[a-zA-Z0-9_\-]* v[0-9.]*:$' | cut -d ' ' -f1 | xargs cargo install` would suffice – Tom Aug 07 '21 at 22:01
  • Automatic upgrade does not seem to be the default behavior in Rust 1.55.0; I had `wasm-pack 0.10.0` installed, but when I tried to update it to `0.10.1` using `cargo install wasm-pack` I got an error: `error: binary 'wasm-pack' already exists in destination` and had to use `--force`. – Herohtar Sep 28 '21 at 21:09
30

A solution I've found is to add the --force flag to the install command. For example cargo install --force clippy. This will effectively re-install the latest version.

w.brian
  • 16,296
  • 14
  • 69
  • 118
25

Here is a one-liner to update all installed Cargo crates, except those installed from a local folder:

cargo install $(cargo install --list | egrep '^[a-z0-9_-]+ v[0-9.]+:$' | cut -f1 -d' ')

Explanation:

  • List installed packages
  • Filter to lines which contain package names and versions, and exclude ones with filesystem paths
  • Cut those lines to only include the package name
  • cargo install with the resulting package names
David Bailey
  • 940
  • 1
  • 10
  • 21
1

I use the command

cargo install --locked $(cat $CARGO_HOME/.crates2.json | jq -r '.installs | keys[] | split(" ")[0]')

You need jq to run this command. I use this command to reliably get the installed packages.

Please note that i have used --locked here. Without --locked few builds may fail. For example, as of today, if you use cargo install-update -a, you will get a message like "Failed to update pueue, ripgrep_all." (Here, replace pueue, ripgrep_all with packages that need --locked).

Another thing is, we may have some dependencies to update the installed package. For that i made a function which will first get the dependencies then update the installed package.

Here is a sample function for fish shell.

function rust_update_packages
    # cargo install --locked ripgrep_all
    # cargo install --locked pueue
    # Alacritty Dependencies
    apt install -y cmake pkg-config libfreetype6-dev libfontconfig1-dev libxcb-xfixes0-dev libxkbcommon-dev python3
    cargo install --locked $(cat $CARGO_HOME/.crates2.json | jq -r '.installs | keys[] | split(" ")[0]')
end

For other shell, only the function syntax will change, the body of the function will remain same.

Ahmad Ismail
  • 11,636
  • 6
  • 52
  • 87