I'd like to get the list of installable versions of a Rust crate in a script.
I want to get not the installed version but installable versions.
You can see the list of installable versions on https://crates.io .
e.g. https://crates.io/crates/skim/versions
I'd like to get the list in a script.
I checked cargo's sub commands and command line options, but I couldn't find any command and option that I want.
I couldn't find any similar command in cargo
documentation either. But It seems like there is an API endpoint(/api/v1/crates/<crate_name>/versions
) available to get all the installable versions of a crate
.
Since you are looking for a cargo
command, You can extend cargo with your own custom command.
Extending Cargo with Custom Commands
Cargo is designed so you can extend it with new subcommands without having to modify Cargo. If a binary in your
$PATH
is namedcargo-something
, you can run it as if it was a Cargo subcommand by runningcargo something
. Custom commands like this are also listed when you runcargo --list
. Being able to usecargo install
to install extensions and then run them just like the built-in Cargo tools is a super convenient benefit of Cargo’s design.
To do that first create a new project:
$ cargo new cargo-list-installable-versions --bin
Please note that the project name should be of the format cargo-YOUR_SUB_COMMAND_NAME
. Now add these two dependencies to Cargo.toml
file.
reqwest = { version = "0.11.18", features = ["blocking", "json"] }
serde_json = "1.0.96"
Now in main.rs
you can implement the logic to get the versions from the API endpoint /api/v1/crates/<crate_name>/versions
.
Here is the very basic implementation.
use std::env;
fn main() {
if let Some(package_name) = env::args().nth(2) {
let client = reqwest::blocking::Client::builder()
.user_agent("YOUR_USER_AGENT")
.build()
.unwrap();
let api_url = format!(
"https://crates.io/api/v1/crates/{}/versions",
package_name.trim()
);
let resp = client
.get(api_url)
.send()
.unwrap()
.json::<serde_json::Value>()
.unwrap();
if let Some(installable_versions) = resp["versions"].as_array() {
for version in installable_versions {
println!("{}", version["num"])
}
}
} else {
eprintln!("package name is missing")
}
}
Now build & release the project. Make sure to add the release folder to the $PATH
environment variable.
$ cargo build --release
$ export PATH="PATH_TO_YOUR_RELEASE_FOLDER:$PATH"
Now you are ready to consume your subcommand. If you configured everything correctly you can see list-installable-versions
subcommand under cargo --list
. To actually run it you can use
$ cargo list-installable-versions <crate_name>
This will print all installable-versions of the <crate_name>
.