-
Notifications
You must be signed in to change notification settings - Fork 440
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
feat: Add workspace_cargo_toml attribute #3060
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -326,6 +326,14 @@ def _crates_vendor_impl(ctx): | |
]) | ||
cargo_bazel_runfiles.extend([ctx.file.cargo_lockfile]) | ||
|
||
# Add an optional `Cargo.toml` file. | ||
if ctx.attr.workspace_cargo_toml: | ||
args.extend([ | ||
"--workspace-cargo-toml", | ||
_runfiles_path(ctx.file.workspace_cargo_toml, is_windows), | ||
]) | ||
cargo_bazel_runfiles.extend([ctx.file.workspace_cargo_toml]) | ||
|
||
# Optionally include buildifier | ||
if ctx.attr.buildifier: | ||
args.extend(["--buildifier", _runfiles_path(ctx.executable.buildifier, is_windows)]) | ||
|
@@ -462,6 +470,10 @@ CRATES_VENDOR_ATTRS = { | |
doc = "The path to a directory to write files into. Absolute paths will be treated as relative to the workspace root", | ||
default = "crates", | ||
), | ||
"workspace_cargo_toml": attr.label( | ||
doc = "The path to the workspace's `Cargo.toml` file", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you document the default behaviour if this is not specified? |
||
allow_single_file = True, | ||
), | ||
} | ||
|
||
crates_vendor = rule( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,6 +60,10 @@ pub struct SpliceOptions { | |
|
||
#[clap(long)] | ||
pub nonhermetic_root_bazel_workspace_dir: PathBuf, | ||
|
||
// The path to the workspace cargo toml file | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you document the default behaviour if this is not specified? |
||
#[clap(long)] | ||
pub workspace_cargo_toml: Option<Utf8PathBuf>, | ||
} | ||
|
||
/// Combine a set of disjoint manifests into a single workspace. | ||
|
@@ -86,7 +90,10 @@ pub fn splice(opt: SpliceOptions) -> Result<()> { | |
|
||
// Splice together the manifest | ||
let manifest_path = splicer | ||
.splice_workspace(&opt.nonhermetic_root_bazel_workspace_dir) | ||
.splice_workspace( | ||
&opt.nonhermetic_root_bazel_workspace_dir, | ||
opt.workspace_cargo_toml.as_deref(), | ||
) | ||
.context("Failed to splice workspace")?; | ||
|
||
// Generate a lockfile | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -82,6 +82,10 @@ pub struct VendorOptions { | |
/// You basically never want to use this value. | ||
#[clap(long)] | ||
pub nonhermetic_root_bazel_workspace_dir: Utf8PathBuf, | ||
|
||
/// The path to the workspace cargo toml file | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you document the default behaviour if this is not specified? |
||
#[clap(long)] | ||
pub workspace_cargo_toml: Option<Utf8PathBuf>, | ||
} | ||
|
||
/// Run buildifier on a given file. | ||
|
@@ -141,7 +145,10 @@ pub fn vendor(opt: VendorOptions) -> Result<()> { | |
|
||
// Splice together the manifest | ||
let manifest_path = splicer | ||
.splice_workspace(opt.nonhermetic_root_bazel_workspace_dir.as_std_path()) | ||
.splice_workspace( | ||
opt.nonhermetic_root_bazel_workspace_dir.as_std_path(), | ||
opt.workspace_cargo_toml.as_deref(), | ||
) | ||
.context("Failed to splice workspace")?; | ||
|
||
// Gather a cargo lockfile | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,8 +92,10 @@ fn discover_workspaces_with_cache( | |
true | ||
}) | ||
{ | ||
let entry = | ||
entry.context("Failed to walk filesystem finding workspace Cargo.toml files")?; | ||
let Ok(entry) = entry else { | ||
// Skip errors. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a surprise - what kind of errors are you running into? |
||
continue; | ||
}; | ||
|
||
if entry.file_name() != "Cargo.toml" { | ||
continue; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,7 +47,19 @@ impl<'a> SplicerKind<'a> { | |
manifests: &'a BTreeMap<Utf8PathBuf, Manifest>, | ||
splicing_manifest: &'a SplicingManifest, | ||
nonhermetic_root_bazel_workspace_dir: &Path, | ||
workspace_cargo_toml: Option<&Utf8Path>, | ||
) -> Result<Self> { | ||
if let Some((path, manifies)) = workspace_cargo_toml | ||
.and_then(|path| manifests.get_key_value(path)) | ||
.and_then(|(path, manifest)| manifest.workspace.as_ref().map(|_| (path, manifest))) | ||
{ | ||
return Ok(Self::Workspace { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This currently skips the "identify any member Cargo.toml files which aren't listed in the manifests" step, which is important for correctness, otherwise we may give false cache hits when those files change. Can we add in that pass (perhaps by giving |
||
path, | ||
manifest: manifies, | ||
splicing_manifest, | ||
}); | ||
} | ||
|
||
let workspaces = discover_workspaces( | ||
manifests.keys().cloned().collect(), | ||
manifests, | ||
|
@@ -503,11 +515,13 @@ impl Splicer { | |
pub(crate) fn splice_workspace( | ||
&self, | ||
nonhermetic_root_bazel_workspace_dir: &Path, | ||
workspace_cargo_toml: Option<&Utf8Path>, | ||
) -> Result<SplicedManifest> { | ||
SplicerKind::new( | ||
&self.manifests, | ||
&self.splicing_manifest, | ||
nonhermetic_root_bazel_workspace_dir, | ||
workspace_cargo_toml, | ||
)? | ||
.splice(&self.workspace_dir) | ||
} | ||
|
@@ -980,7 +994,7 @@ mod test { | |
let workspace_manifest = | ||
Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")) | ||
.splice_workspace(Path::new("/doesnotexist"), None) | ||
.unwrap(); | ||
|
||
// Locate cargo | ||
|
@@ -1023,7 +1037,7 @@ mod test { | |
let workspace_manifest = | ||
Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")) | ||
.splice_workspace(Path::new("/doesnotexist"), None) | ||
.unwrap(); | ||
|
||
// Locate cargo | ||
|
@@ -1074,7 +1088,7 @@ mod test { | |
splicing_manifest, | ||
) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")); | ||
.splice_workspace(Path::new("/doesnotexist"), None); | ||
|
||
assert!(workspace_manifest.is_err()); | ||
|
||
|
@@ -1104,7 +1118,7 @@ mod test { | |
splicing_manifest, | ||
) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")); | ||
.splice_workspace(Path::new("/doesnotexist"), None); | ||
|
||
assert!(workspace_manifest.is_err()); | ||
|
||
|
@@ -1172,7 +1186,7 @@ mod test { | |
let workspace_manifest = | ||
Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")); | ||
.splice_workspace(Path::new("/doesnotexist"), None); | ||
|
||
assert!(workspace_manifest.is_err()); | ||
|
||
|
@@ -1209,7 +1223,7 @@ mod test { | |
let workspace_manifest = | ||
Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")) | ||
.splice_workspace(Path::new("/doesnotexist"), None) | ||
.unwrap(); | ||
|
||
let metadata = generate_metadata(workspace_manifest.as_path_buf()); | ||
|
@@ -1234,7 +1248,7 @@ mod test { | |
let workspace_manifest = | ||
Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")) | ||
.splice_workspace(Path::new("/doesnotexist"), None) | ||
.unwrap(); | ||
|
||
// Locate cargo | ||
|
@@ -1271,7 +1285,7 @@ mod test { | |
let workspace_manifest = | ||
Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")) | ||
.splice_workspace(Path::new("/doesnotexist"), None) | ||
.unwrap(); | ||
|
||
// Check the default resolver version | ||
|
@@ -1321,7 +1335,7 @@ mod test { | |
let workspace_manifest = | ||
Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")) | ||
.splice_workspace(Path::new("/doesnotexist"), None) | ||
.unwrap(); | ||
|
||
// Check the specified resolver version | ||
|
@@ -1381,7 +1395,7 @@ mod test { | |
let workspace_manifest = | ||
Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")) | ||
.splice_workspace(Path::new("/doesnotexist"), None) | ||
.unwrap(); | ||
|
||
// Check the default resolver version | ||
|
@@ -1423,7 +1437,7 @@ mod test { | |
let workspace_manifest = | ||
Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")) | ||
.splice_workspace(Path::new("/doesnotexist"), None) | ||
.unwrap(); | ||
|
||
// Ensure the patches match the expected value | ||
|
@@ -1486,7 +1500,7 @@ mod test { | |
let workspace_manifest = | ||
Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")) | ||
.splice_workspace(Path::new("/doesnotexist"), None) | ||
.unwrap(); | ||
|
||
// Ensure the patches match the expected value | ||
|
@@ -1537,7 +1551,7 @@ mod test { | |
let workspace_manifest = | ||
Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")) | ||
.splice_workspace(Path::new("/doesnotexist"), None) | ||
.unwrap(); | ||
|
||
// Ensure the patches match the expected value | ||
|
@@ -1579,7 +1593,7 @@ mod test { | |
let workspace_root = tempfile::tempdir().unwrap(); | ||
let result = Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")); | ||
.splice_workspace(Path::new("/doesnotexist"), None); | ||
|
||
// Confirm conflicting patches have been detected | ||
assert!(result.is_err()); | ||
|
@@ -1601,7 +1615,7 @@ mod test { | |
let workspace_root = tempfile::tempdir().unwrap(); | ||
Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")) | ||
.splice_workspace(Path::new("/doesnotexist"), None) | ||
.unwrap(); | ||
|
||
let cargo_config = workspace_root.as_ref().join(".cargo").join("config.toml"); | ||
|
@@ -1634,7 +1648,7 @@ mod test { | |
let workspace_root = tempfile::tempdir().unwrap(); | ||
Splicer::new(tempdir_utf8pathbuf(&workspace_root), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")) | ||
.splice_workspace(Path::new("/doesnotexist"), None) | ||
.unwrap(); | ||
|
||
let cargo_config = workspace_root.as_ref().join(".cargo").join("config.toml"); | ||
|
@@ -1661,7 +1675,7 @@ mod test { | |
let workspace_root = tempdir_utf8pathbuf(&temp_dir).join("workspace_root"); | ||
let splicing_result = Splicer::new(workspace_root.clone(), splicing_manifest) | ||
.unwrap() | ||
.splice_workspace(Path::new("/doesnotexist")); | ||
.splice_workspace(Path::new("/doesnotexist"), None); | ||
|
||
// Ensure cargo config files in parent directories lead to errors | ||
assert!(splicing_result.is_err()); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
[workspace] | ||
members = [ | ||
"child", | ||
] | ||
resolver = "2" | ||
|
||
[package] | ||
name = "parent" | ||
version = "0.1.0" | ||
edition = "2018" | ||
|
||
# Required to satisfy cargo but no `lib.rs` is expected to | ||
# exist within test data. | ||
[lib] | ||
path = "lib.rs" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you document the default behaviour if this is not specified?