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: Auto include locals and skip non-dirs and excluded in workspace member search #184

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 63 additions & 21 deletions xbuild/src/cargo/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pub enum Inheritable<T> {
pub struct Manifest {
pub workspace: Option<Workspace>,
pub package: Option<Package>,
#[serde(default)]
pub dependencies: HashMap<String, Dependency>,
}

impl Manifest {
Expand All @@ -34,37 +36,68 @@ impl Manifest {
.context("The provided Cargo.toml does not contain a `[workspace]`")?;
let workspace_root = utils::canonicalize(workspace_root)?;

// Check all member packages inside the workspace
let mut all_members = HashMap::new();
let mut member_dirs = vec![];

// resolve members and exclude globs
let exclude = workspace
.exclude
.iter()
.map(|g| glob::Pattern::new(workspace_root.join(g).to_str().unwrap()))
.collect::<Result<Vec<_>, _>>()?;
for member in &workspace.members {
for manifest_dir in glob::glob(workspace_root.join(member).to_str().unwrap())? {
let manifest_dir = manifest_dir?;
let manifest_path = manifest_dir.join("Cargo.toml");
let manifest = Manifest::parse_from_toml(&manifest_path).with_context(|| {
format!(
"Failed to load manifest for workspace member `{}`",
manifest_dir.display()
)
})?;

// Workspace members cannot themselves be/contain a new workspace
anyhow::ensure!(
manifest.workspace.is_none(),
"Did not expect a `[workspace]` at `{}`",
manifest_path.display(),
);
if !manifest_dir.is_dir() || exclude.iter().any(|g| g.matches_path(&manifest_dir)) {
continue;
}
member_dirs.push(manifest_dir);
}
}

// include all local path dependencies
if self.package.is_some() {
for dep in self.dependencies.values() {
if let Dependency::Table { path: Some(path) } = dep {
let manifest_dir = workspace_root.join(path);
if manifest_dir.starts_with(&workspace_root) {
member_dirs.push(manifest_dir);
}
}
}
}

// And because they cannot contain a [workspace], they may not be a virtual manifest
// and must hence contain [package]
anyhow::ensure!(
// Check all member packages inside the workspace
let mut all_members = HashMap::new();

for manifest_dir in member_dirs {
if all_members.contains_key(&manifest_dir) {
continue;
}

let manifest_path = manifest_dir.join("Cargo.toml");
let manifest = Manifest::parse_from_toml(&manifest_path).with_context(|| {
format!(
"Failed to load manifest for workspace member `{}`",
manifest_dir.display()
)
})?;

// Workspace members cannot themselves be/contain a new workspace
anyhow::ensure!(
manifest.workspace.is_none(),
"Did not expect a `[workspace]` at `{}`",
manifest_path.display(),
);

// And because they cannot contain a [workspace], they may not be a virtual manifest
// and must hence contain [package]
anyhow::ensure!(
manifest.package.is_some(),
"Failed to parse manifest at `{}`: virtual manifests must be configured with `[workspace]`",
manifest_path.display(),
);

all_members.insert(manifest_dir, (manifest_path, manifest));
}
all_members.insert(manifest_dir, (manifest_path, manifest));
}

Ok(all_members)
Expand Down Expand Up @@ -113,6 +146,8 @@ pub struct Workspace {
pub default_members: Vec<String>,
#[serde(default)]
pub members: Vec<String>,
#[serde(default)]
pub exclude: Vec<String>,

pub package: Option<WorkspacePackage>,
}
Expand All @@ -125,6 +160,13 @@ pub struct WorkspacePackage {
pub description: Option<String>,
}

#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum Dependency {
Table { path: Option<PathBuf> },
Version(String),
}

#[derive(Clone, Debug, Deserialize)]
pub struct Package {
pub name: String,
Expand Down
Loading