fix(cargo-wdk): workspace resolution in build and clean actions to match cargo - #706
fix(cargo-wdk): workspace resolution in build and clean actions to match cargo#706svasista-ms wants to merge 2 commits into
build and clean actions to match cargo#706Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates cargo-wdk’s build and clean flows to better match Cargo’s workspace resolution behavior (Issue #477), especially when invoked from within a workspace subdirectory.
Changes:
- Pass the
Metadataprovider intoCleanActionand usecargo metadatato detect workspaces before falling back to “emulated workspace” scanning. - Add a
NotAbsoluteerror variant for clean to mirror build’s handling of unexpected non-absolute paths. - Add/adjust
CleanActionunit tests for the new workspace-detection behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| crates/cargo-wdk/src/cli.rs | Wires Metadata into CleanAction::new(...) so clean can query cargo metadata. |
| crates/cargo-wdk/src/actions/clean/mod.rs | Adds workspace detection via cargo metadata before emulated workspace scanning. |
| crates/cargo-wdk/src/actions/clean/error.rs | Adds NotAbsolute error variant for workspace root resolution failures. |
| crates/cargo-wdk/src/actions/build/mod.rs | Adds workspace-root inference attempt when Cargo.toml is not in the current directory. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let owns_working_dir = cargo_metadata.workspace_packages().iter().any(|p| { | ||
| p.manifest_path | ||
| .parent() | ||
| .and_then(|path| absolute(path.as_std_path()).ok()) | ||
| .is_some_and(|package_dir| package_dir.starts_with(&self.working_dir)) | ||
| }); | ||
|
|
||
| if owns_working_dir { | ||
| let workspace_root = absolute(cargo_metadata.workspace_root.as_std_path()) | ||
| .map_err(|e| { | ||
| CleanActionError::NotAbsolute( | ||
| cargo_metadata.workspace_root.clone().into(), | ||
| e, | ||
| ) | ||
| })?; | ||
| debug!( | ||
| "Working directory {} lies inside the workspace rooted at {}; running cargo \ | ||
| clean from workspace root", | ||
| self.working_dir.display(), | ||
| workspace_root.display() | ||
| ); | ||
| return self.run_cargo_clean(&workspace_root); | ||
| } |
| let owns_working_dir = cargo_metadata.workspace_packages().iter().any(|p| { | ||
| p.manifest_path | ||
| .parent() | ||
| .and_then(|path| absolute(path.as_std_path()).ok()) | ||
| .is_some_and(|package_dir| package_dir.starts_with(&self.working_dir)) | ||
| }); | ||
|
|
||
| if owns_working_dir { | ||
| let workspace_root = absolute(cargo_metadata.workspace_root.as_std_path()) | ||
| .map_err(|e| { | ||
| BuildActionError::NotAbsolute( | ||
| cargo_metadata.workspace_root.clone().into(), | ||
| e, | ||
| ) | ||
| })?; | ||
| debug!( | ||
| "Working directory {} lies inside the workspace rooted at {}; running build \ | ||
| from workspace root", | ||
| self.working_dir.display(), | ||
| workspace_root.display() | ||
| ); | ||
| return self.run_from_workspace_root(&workspace_root); | ||
| } |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #706 +/- ##
==========================================
+ Coverage 80.47% 81.02% +0.54%
==========================================
Files 26 26
Lines 5722 5951 +229
Branches 5722 5951 +229
==========================================
+ Hits 4605 4822 +217
- Misses 989 998 +9
- Partials 128 131 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…and `clean` actions
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (3)
crates/cargo-wdk/src/actions/mod.rs:149
find_workspace_rootalways returnscargo_metadata.workspace_root, which for a workspace member subdirectory (e.g.member/src/) will typically be the workspace root, not the nearest package root. InBuildAction::runthis causescargo wdk buildfrom inside a member subtree to build/package every workspace member (because it later runs from the workspace root), which diverges fromcargo build’s “nearest Cargo.toml” behavior and can significantly increase build time.
absolute(cargo_metadata.workspace_root.as_std_path()).ok()
crates/cargo-wdk/src/actions/mod.rs:147
- The
is_emulated_workspaceearly-return makesfind_workspace_rootreturnNoneeven whencargo metadatasuccessfully identifies a real workspace, solely because the current directory contains non-memberCargo.tomlchildren. That preserves “emulated workspace” behavior, but it also meanscargo wdk build/cleancan still diverge fromcargoinside an actual workspace (cargo would ignore those excluded projects and operate on the workspace it found). If the PR goal is to “match cargo”, consider gating this behavior behind an explicit flag or removing it when a workspace is detected.
This issue also appears on line 149 of the same file.
let is_emulated_workspace = dirs.iter().any(|entry| {
entry.is_dir
&& fs.exists(&entry.path.join("Cargo.toml"))
&& absolute(&entry.path).is_ok_and(|child_dir| {
!member_dirs
.iter()
.any(|member| member.starts_with(&child_dir))
})
});
if is_emulated_workspace {
return None;
}
crates/cargo-wdk/src/actions/build/mod.rs:178
- New workspace-root resolution logic in
BuildAction::runisn’t covered by the existing build action unit tests (there don’t appear to be tests for the “no Cargo.toml in cwd but inside a workspace” path, or for ensuring a member subdirectory builds only the selected package vs the whole workspace). This path is central to #477 and can regress behavior/perf without a test.
// Standalone driver/driver workspace support
if self.fs.exists(&self.working_dir.join("Cargo.toml")) {
return self.run_from_workspace_root(&self.working_dir);
}
let dirs = self.fs.read_dir_entries(&self.working_dir)?;
if let Some(workspace_root) = super::find_workspace_root(
self.metadata,
self.fs,
&self.working_dir,
&dirs,
self.locked,
self.features,
) {
debug!(
"Working directory {} lies inside the workspace rooted at {}; running build from \
workspace root",
self.working_dir.display(),
workspace_root.display()
);
return self.run_from_workspace_root(&workspace_root);
}
TBD
Resolves #477