Mismatch between `cargo pkgid` and `cargo metadata` (and human-readable names)
The "package_id" field in cargo metadata is not a valid package id specification.
Take the output of cargo metadata | jq '.packages[0].id' of your local crate. I get "abort_on_panic 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)"
This is not a valid package id specification (cargo pkgid fails). The correct equivalent is "https://github.com/rust-lang/crates.io-index#abort_on_panic:2.0.0".
How are we supposed to convert back and forth between these two seemingly incompatible formats? To go from cargo pkgid -> cargo metadata, I had to re-implement my own matching logic and search back over the metadata :(
Human Redable package ids
Say I have a cargo_metadata::PackageId.
How do I print this back to the user as a cargo pkgid?
The simple answer is to print back the crate's name. In most cases this is unambiguous. Right now (in my current crate) syn refers unambiguously to a single version. That's good
But that doesn't work if there are multiple versions of the crate. What if we have libc:0.1.12 and also libc:0.2.109?
At this point, a simple "print package name" is not a good way to output a PackageId, because libc would be ambiguous.
In addition cargo pkgid supports arbitrary urls like https://github.com/Techcable/my-library#0.2.0-alpha.5. Version + name could be ambiguous in the presence of git dependencies :(
You don't want to have to output a full https://github.com/rust-lang/crates.io-index#syn:1.0.82 when syn is unambiguous, but you also want to be able to handle the ambiguity when it comes out.
Workarounds
As a hack to workaround the lack of cargo pkgid --short <pkg> in my cargo outdir tool, I had to write a post-processing pass pass to analyze for potential conflicts. Then I had to normalize cargo metadata ids back to the minimal package id.
Once again this is made more difficult to cargo_metadata::PackageId using a non-standard format that is incompatible with cargo pkgid, it's also super difficult to go from package ids -> human readable "short" package ids.
So there are there two problems :(
As far as I can tell, there is no way to map theses. package_id's format is internal to cargo and subject to change. It'd be convenient for us if they changed it to a fully qualified pkgid but I do not know what complications that involves.
The next best thing I can think of is trying to get cargo metadata to also output the pkgid. Unsure how receptive folks will be to that.
Internally, cargo does have a mechanism for converting between them, PackageSpecId::from_package_id. You could dig through that, the Displays and serde implementation of each, etc to work out how it does it. I see that only as a stopgap, if used at all.