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

Fix: Not all projects have a root package #61

Merged
merged 2 commits into from Feb 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 30 additions & 16 deletions src/config.rs
Expand Up @@ -20,27 +20,41 @@ struct ParseConfig {

impl Config {
pub fn from_metadata(metadata: &cargo_metadata::Metadata) -> Result<Config> {
let root_package_id = metadata
.resolve
.as_ref()
.and_then(|resolve| resolve.root.clone())
.ok_or("Cannot infer the root project id")?;

// Find the root package by id in the list of packages. It is logical error if the root
// package is not found in the list.
let root_manifest = metadata.workspace_root.join("Cargo.toml");
let root_package = metadata
.packages
.iter()
.find(|package| package.id == root_package_id)
.expect("The package is not found in the `cargo metadata` output");
.find(|package| package.manifest_path == root_manifest);

let crate_metadata = root_package.metadata.get("cargo-xbuild");
let config = match crate_metadata {
Some(json) => {
serde_json::from_value(json.clone())
.map_err(|_| "parsing package.metadata.cargo-xbuild section failed")?
let config = match root_package {
Some(root_package) => {
let crate_metadata = root_package.metadata.get("cargo-xbuild");
match crate_metadata {
Some(json) => serde_json::from_value(json.clone()).map_err(|e| {
format!(
"parsing package.metadata.cargo-xbuild section failed: {}",
e
)
})?,
None => ParseConfig::default(),
}
}
None => {
// The project has no root package. This could be because it only defines a
// dummy `Cargo.toml` at the root without a `[package]` section.
//
// The problem in this case is that we don't have a reasonable place to read
// the config from. There are multiple `Cargo.toml`s in this workspace and it
// is not clear which one is the "canonical" Cargo.toml with the xbuild config.
//
// So we can't read the config for such projects. To make this transparent to
// the user, we print a warning.
eprintln!(
"WARNING: There is no root package to read the cargo-xbuild config from."
);
// There is no config to read, so we use default options
ParseConfig::default()
}
None => ParseConfig::default(),
};

Ok(Config {
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Expand Up @@ -161,7 +161,7 @@ pub fn build(args: cli::Args, command_name: &str) -> Result<ExitStatus> {
.expect("cargo metadata invocation failed");
let root = Path::new(&metadata.workspace_root);
let crate_config = config::Config::from_metadata(&metadata)
.map_err(|_| "parsing package.metadata.cargo-xbuild section failed")?;
.map_err(|e| format!("reading package.metadata.cargo-xbuild section failed: {}", e))?;

// We can't build sysroot with stable or beta due to unstable features
let sysroot = rustc::sysroot(verbose)?;
Expand Down