Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upIntroduce cargo metadata subcommand #2196
Conversation
rust-highfive
assigned
alexcrichton
Dec 5, 2015
This comment has been minimized.
This comment has been minimized.
rust-highfive
commented
Dec 5, 2015
|
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @alexcrichton (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
matklad
reviewed
Dec 5, 2015
| features: Vec<String>, | ||
| no_default_features: bool) | ||
| -> CargoResult<(Resolve, Vec<Package>)> { | ||
| let mut source = try!(PathSource::for_path(manifest.parent().unwrap(), config)); |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Another question is where should we put documentation for the format? Is the help message a right place? |
matklad
force-pushed the
matklad:metadata2
branch
from
e58e6d4
to
fcc1831
Dec 5, 2015
bors
added a commit
that referenced
this pull request
Dec 8, 2015
This comment has been minimized.
This comment has been minimized.
|
@matklad how about inline code documentation in the relevant module file? |
This comment has been minimized.
This comment has been minimized.
Sure :) We want to use cargo metadata with a plugin for Intellij IDEA. IDEA based IDEs are "smart": they build a syntax tree from source code and perform "static analysis" (completion, navigation, refactorings, ...) using it. To build such tree across several files, we need to know some metadata about the project. The most vital piece of information is a list of crate roots that belong to the project. Only if you know crate roots ( Note that a rust project can include several cargo subprojects (path dependencies), so we need this information too. Another place where we need help from cargo is extren crates declarations. We need to resolve We don't use
Missing output is Ok, it will be easy to add more information later. Moreover, if we output too much, we may make changing the internal cargo structures harder, because the serialized output is currently tied to this structures.
I would argue that this also falls into "missing information" category. There are two pieces of data here: a flat list of known packages and a dependency DAG. At the moment,
This is an important piece of information, but it is not needed at least for our use case. It can be added later.
Hm, target serialization does include
Not sure what it is, but seems like it does not belong here :)
What is the relation between a |
This comment has been minimized.
This comment has been minimized.
|
@alexcrichton 1.5 is Thinking of it more, I propose the following format: {
"packages": [
{
"name": "foo",
"package_id": "some_name some_version some_source_id",
//...
},
//...
],
"graph": [
"root": "some_name some_version some_source_id",
"edges": [
//...
]
]
}That is, we should include a So we can remove this from the output. A thing that bothers me a little is that |
This comment has been minimized.
This comment has been minimized.
|
Thanks for pushing on this again @matklad! Currently I'm at a work week in Orlando, but I hope to digest more of this first thing next week! |
alexcrichton
reviewed
Dec 16, 2015
| flag_manifest_path: Option<String>, | ||
| flag_no_default_features: bool, | ||
| flag_output_format: OutputFormat, | ||
| flag_output_path: OutputTo, |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Dec 16, 2015
Member
Perhaps this could just be Option<String>? That way a custom Decodable implementation isn't needed
alexcrichton
reviewed
Dec 16, 2015
| Valid values: toml, json | ||
| --features FEATURES Space-separated list of features | ||
| --no-default-features Do not include the `default` feature | ||
| --manifest-path PATH Path to the manifest |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Dec 16, 2015
Member
This may also want to support a --target argument as that'll affect the structure of the dependency graph. This should also support the standard -q and --color flag we have now
This comment has been minimized.
This comment has been minimized.
matklad
Dec 17, 2015
Author
Member
added -q and --color.
Not sure what should I do with target: resolve_dependencies does not have a target among arguments: https://github.com/matklad/cargo/blob/metadata2/src/cargo/ops/cargo_compile.rs#L100
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jan 14, 2016
Member
Ah it looks like I never responded to this, but --target no longer affects the structure of the dependency graph (that was a bug actually), so this should be good to go.
alexcrichton
reviewed
Dec 16, 2015
|
|
||
| let deps = try!(ops::resolve_dependencies(&package, | ||
| config, | ||
| None, |
This comment has been minimized.
This comment has been minimized.
alexcrichton
reviewed
Dec 16, 2015
| use ops; | ||
|
|
||
|
|
||
| #[derive(RustcDecodable)] |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Dec 16, 2015
Member
Huh I'm kinda surprised this works, does this emit strings by default? It may be better to explicitly just take a string and then convert it to an enum manually (may give better errors as well)
alexcrichton
reviewed
Dec 16, 2015
| OutputTo::StdOut => println!("{}", serialized_str), | ||
| OutputTo::Path(ref path) => { | ||
| let mut file = try!(fs::File::create(path)); | ||
| try!(file.write_all(serialized_str.as_bytes())); |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Dec 16, 2015
Member
There's a helper function paths::write which should encompass this write-the-whole-file logic. This may also want to chain errors to give some more contextual information about what failed.
alexcrichton
reviewed
Dec 16, 2015
| #[derive(RustcEncodable)] | ||
| struct RootPackageInfo<'a> { | ||
| name: &'a str, | ||
| version: String, |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Dec 16, 2015
Member
Instead of name/version, could this just store a PackageId? That should contain all the information necessary to map this to a package in packages
This comment has been minimized.
This comment has been minimized.
alexcrichton
Dec 16, 2015
Member
Also wow the SerializedPackage on the other end is ... quite lacking! I think that that end over there will perhaps want some improvements as well (e.g. using a PackageId instead)
This comment has been minimized.
This comment has been minimized.
matklad
Dec 16, 2015
Author
Member
Instead of name/version, could this just store a PackageId? That should contain all the information necessary to map this to a package in packages
Yep, meant exactly that in my graph: {root: package_id, edges: [...]} suggestion.
alexcrichton
reviewed
Dec 16, 2015
| struct RootPackageInfo<'a> { | ||
| name: &'a str, | ||
| version: String, | ||
| features: Option<&'a HashMap<String, Vec<String>>>, |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Dec 16, 2015
Member
Does this need to be included here? It seems that this should be discoverable through the packages array below.
This comment has been minimized.
This comment has been minimized.
|
Thanks @matklad! This is looking good to me. I think it's important to rely on the standard I've got a few bike-sheddy points that I'd like to discuss here:
Thoughts? To respond to some of your points as well, I agree that limiting the amount of information being printed is a good idea. I'd just want to make sure that this is useful in a first draft rather than restricting it too much in terms of the information being printed. For example I'm ok with not emitting the dependency graph for now, that can always be added later. |
This comment has been minimized.
This comment has been minimized.
Hm,
Will look at the
Does anybody uses |
This comment has been minimized.
This comment has been minimized.
|
Ah yes
Where all the packages in resolve are listed as package ids. That way tools can use resolve to figure out what the precise structure is, and then they can use the package metadata information in the packages array to figure out things like source paths and such. |
This comment has been minimized.
This comment has been minimized.
|
Also I'm not sure if there are too many users of |
This comment has been minimized.
This comment has been minimized.
Should we include both declared and resolved dependencies in the output? I'd say yes: this will help to detect issues like #2064 |
This comment has been minimized.
This comment has been minimized.
|
@alexcrichton I'm a bit worried that Package and Manifest have almost identical representation: https://github.com/rust-lang/cargo/blob/master/src/cargo/core/manifest.rs#L47-L52 If I add Given this comment I'm not even sure that we need both a Package and a Manifest ;) |
This comment has been minimized.
This comment has been minimized.
I think we should, yeah, but in separate locations (to mirror what Cargo does)
An excellent point! I think it should be ok to actually just have the |
matklad
force-pushed the
matklad:metadata2
branch
from
209e354
to
c24746e
Dec 17, 2015
This comment has been minimized.
This comment has been minimized.
There is Particularly, there is no I'd better provide a separate |
This comment has been minimized.
This comment has been minimized.
|
Ah actually I think that's basically exactly what we want here, could you elaborate on what's missing from constructing it? (e.g. you've already got a I will say though idiomatically the implementation of |
This comment has been minimized.
This comment has been minimized.
|
The entry in the lock file looks like this:
Note that in Package id string can be reconstructed from this three things, but it does not feel right. |
matklad
force-pushed the
matklad:metadata2
branch
2 times, most recently
from
4757aca
to
f8d5a21
Jan 25, 2016
matklad
added some commits
Dec 5, 2015
matklad
force-pushed the
matklad:metadata2
branch
from
f8d5a21
to
4c66b8f
Jan 25, 2016
matklad
referenced this pull request
Jan 25, 2016
Closed
Improve output of machine oriented commands #2313
matklad
force-pushed the
matklad:metadata2
branch
from
4c66b8f
to
b24bf7e
Jan 25, 2016
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
bors
added a commit
that referenced
this pull request
Jan 25, 2016
This comment has been minimized.
This comment has been minimized.
|
@alexcrichton what is the release schedule for cargo? Am I correct that |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
@matklad yeah this'll ride the normal release trains and will be available in Rust 1.8 |
This comment has been minimized.
This comment has been minimized.
|
Ouch, @alexcrichton, I think we've missed one rather major issue here, this one
The id's in {
"packages": [
{
"name": "geom",
"version": "0.1.0",
// This id is different
"id": "geom 0.1.0 (path+file:\/\/\/home\/matklad\/projects\/rustraytracer)",
"source": null,
...
},
...
],
"resolve": {
"root": {
"name": "rustraytracer",
"version": "0.1.0",
"source": null,
"dependencies": [
// from this id :(
"geom 0.1.0",
"rand 0.3.11 (registry+https:\/\/github.com\/rust-lang\/crates.io-index)",
"regex 0.1.41 (registry+https:\/\/github.com\/rust-lang\/crates.io-index)",
"rustc-serialize 0.3.16 (registry+https:\/\/github.com\/rust-lang\/crates.io-index)",
"simple_parallel 0.3.0 (registry+https:\/\/github.com\/rust-lang\/crates.io-index)",
"time 0.1.33 (registry+https:\/\/github.com\/rust-lang\/crates.io-index)",
"utils 0.1.0"
]
},
...
},
}In |
This comment has been minimized.
This comment has been minimized.
|
Oh dear that is indeed not good! I can't seem to recall myself why there are two |
This comment has been minimized.
This comment has been minimized.
Probably not. The one from resolve is "context sensitive". Look at this function: https://github.com/rust-lang/cargo/blob/master/src/cargo/core/resolver/encode.rs#L189. It creates an Unfortunately it depends on the |
This comment has been minimized.
This comment has been minimized.
|
Hm ok, so the requirements of resolve are indeed a little different. We don't want to emit filesystem paths to the lock file because otherwise they'd just oscillate over time as you migrate among machines. That being said there aren't too many uses for encoding package ids, and in general it amounts to an assertion that path-based source ids are omitted where everything else is included. It's probably fine for now to change the encodable implementation for package ids to ignore path sources and that way it'll match resolve (and resolve can use the same implementation) |
This comment has been minimized.
This comment has been minimized.
I've tried to do it here and the result is unsatisfactory. The crux of the problem is that
This makes me think again that maybe we should leave lock-file resolve serilization to lockfile only, and instead provide a simpler and more natural generic serialization for resolve :) And there is one more thing, |
This comment has been minimized.
This comment has been minimized.
|
Hm ok, I forgot that package ids were being encoded for Sorry for the roundabout way to conclude that! |
This comment has been minimized.
This comment has been minimized.
Experiment is a nice way to make a ( I hope so :) ) correct conclusion. here is a PR: #2331 |
matklad commentedDec 5, 2015
Most of the work was done by @dan-t in #1225 and by @winger in #1434
Fixes #2193
I failed to properly rebase previous attempts so I just salvaged this from bits and pieces.
@alexcrichton are you sure that the default format should be TOML? I think that TOML is more suitable for humans, and JSON is better (at the moment at least) for tools. Maybe we should default to
TOMLJSON?