Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cargo can't install crates with a version string including the + character #9410

Closed
amyspark opened this issue Apr 24, 2021 · 6 comments · Fixed by #9467
Closed

cargo can't install crates with a version string including the + character #9410

amyspark opened this issue Apr 24, 2021 · 6 comments · Fixed by #9467
Labels
C-bug Category: bug

Comments

@amyspark
Copy link

amyspark commented Apr 24, 2021

Problem
cargo in Linux can't install crates like cargo-c, whose versions include a + character in them.

Steps

  1. cargo install cargo-c --version=0.8.0+cargo-0.51

Possible Solution(s)
A workaround in Linux is to quote the semver with double quotes. In Windows, this workaround errors out similarly to Linux.

Notes

Output of cargo version: cargo 1.51.0 (43b129a20 2021-03-16)

In Linux, the error is:

~> cargo install cargo-c --version=0.80+cargo-0.51
error: the `--vers` provided, `0.80+cargo-0.51`, is not a valid semver version: cannot parse '0.80+cargo-0.51' as a semver

if you want to specify semver range, add an explicit qualifier, like ^0.80+cargo-0.51

or alternatively (like in our CI):

Updating crates.io index
Downloading crates ...
error: failed to download from `https://crates.io/api/v1/crates/cargo-c/0.8.0/download`

Caused by:
    failed to get 200 response from `https://crates.io/api/v1/crates/cargo-c/0.8.0/download`, got 404

In Mac and Windows, it succeeds without escaping. Escaping the version string on Windows returns:

error: the `--vers` provided, `"0.8.0+cargo-0.51"`, is not a valid semver version: cannot parse '"0.8.0+cargo-0.51"' as a semver
@amyspark amyspark added the C-bug Category: bug label Apr 24, 2021
@amyspark
Copy link
Author

Note this is similar to rustwasm/wasm-pack#907.

@ehuss
Copy link
Contributor

ehuss commented Apr 25, 2021

Hi! Sorry I'm a bit confused since the error seems correct to me. 0.80+cargo-0.51 is an invalid semver version, since it is missing the patch version. cargo install cargo-c --version=0.8.0+cargo-0.51 seems to work for me. Looks like maybe it is missing a period?

FWIW, everything after the + is ignored, so it generally isn't needed.

@alvinhochun
Copy link

For me, if I run this on Bash on Linux it tries to fetch the wrong version on a relatively clean Cargo environment, which makes it seem like the part after the + was not parsed. If I try it with quotes, it fetches the requested version correctly.

However, if I then run the original command again the second time, it installs fine. It looks like it now works because a version of "0.8.0" is already cached locally.

$ cargo install cargo-c --version 0.8.0+cargo-0.51
    Updating crates.io index
error: failed to download from `https://crates.io/api/v1/crates/cargo-c/0.8.0/download`

Caused by:
  failed to get 200 response from `https://crates.io/api/v1/crates/cargo-c/0.8.0/download`, got 404
$ cargo install cargo-c --version "0.8.0+cargo-0.51"
  Downloaded cargo-c v0.8.0+cargo-0.51
  Downloaded 1 crate (29.5 KB) in 0.55s
^C
$ cargo install cargo-c --version 0.8.0+cargo-0.51
    Updating crates.io index
  Installing cargo-c v0.8.0+cargo-0.51
^C

@ehuss
Copy link
Contributor

ehuss commented Apr 25, 2021

Thanks for the clarification! I see the problem now. For me, it only fails after the first download of the index. (It might happen in other scenarios.)

The reasons are complicated, but it boils down to a global cache in cargo (the package id cache). The Version object ignores the build metadata for Eq/PartialEq/Hash. If the cache happens to be first populated with a variant that is missing the metadata, then every time it behaves as-if the metadata does not exist.

The reason it gets populated without the metadata is that there is this code path which checks if the package is already installed without updating the index. Since the index doesn't exist, it hits this code path which checks if it is yanked. That particular code path uses a VerionReq to create a PackageId, which ends up poisoning the cache with an PackageId without metadata. Then, when it does download the index and try to actually install the package, it ends up with a PackageId missing the metadata, and then the download link is computed incorrectly.

Whew... That will be tricky to fix, but I'll take a look at it.

@alvinhochun
Copy link

alvinhochun commented Apr 26, 2021

Ah I see, so the quoting in my test is just a red herring.

I would be glad to see this fixed eventually, but if we need to run CI builds now on a fresh environment (let's say a docker container), is there a better workaround than running the cargo install twice?

@ehuss
Copy link
Contributor

ehuss commented Apr 26, 2021

Unfortunately I am unable to think of a better workaround for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants