diff --git a/src/cargo/ops/vendor.rs b/src/cargo/ops/vendor.rs index 6733656dcec7..a351e7b0faa4 100644 --- a/src/cargo/ops/vendor.rs +++ b/src/cargo/ops/vendor.rs @@ -60,14 +60,13 @@ struct VendorConfig { } #[derive(Serialize)] -#[serde(rename_all = "lowercase", untagged)] +#[serde(rename_all = "kebab-case", rename_all_fields = "kebab-case", untagged)] enum VendorSource { Directory { directory: String, }, Registry { registry: Option, - #[serde(rename = "replace-with")] replace_with: String, }, Git { @@ -75,7 +74,10 @@ enum VendorSource { branch: Option, tag: Option, rev: Option, - #[serde(rename = "replace-with")] + replace_with: String, + }, + Path { + path: String, replace_with: String, }, } @@ -147,6 +149,10 @@ fn sync( // Next up let's actually download all crates and start storing internal // tables about them. + let members: BTreeSet<_> = workspaces + .iter() + .flat_map(|ws| ws.members().map(|p| p.package_id())) + .collect(); for ws in workspaces { let (packages, resolve) = ops::resolve_ws(ws).with_context(|| "failed to load pkg lockfile")?; @@ -156,9 +162,8 @@ fn sync( .with_context(|| "failed to download packages")?; for pkg in resolve.iter() { - // No need to vendor path crates since they're already in the - // repository - if pkg.source_id().is_path() { + // Don't vendor path deps unless it is outside any of the given workspaces. + if pkg.source_id().is_path() && !members.contains(&pkg) { continue; } ids.insert( @@ -293,6 +298,16 @@ fn sync( rev, replace_with: merged_source_name.to_string(), } + } else if source_id.is_path() { + VendorSource::Path { + path: source_id + .url() + .to_file_path() + .unwrap() + .to_string_lossy() + .replace("\\", "/"), + replace_with: merged_source_name.to_string(), + } } else { panic!("Invalid source ID: {}", source_id) }; diff --git a/src/cargo/sources/config.rs b/src/cargo/sources/config.rs index 4a0332eca605..e4ddf40c79dd 100644 --- a/src/cargo/sources/config.rs +++ b/src/cargo/sources/config.rs @@ -33,6 +33,8 @@ pub struct SourceConfigMap<'cfg> { struct SourceConfigDef { /// Indicates this source should be replaced with another of the given name. replace_with: OptValue, + /// A path source. + path: Option, /// A directory source. directory: Option, /// A registry source. Value is a URL. @@ -249,6 +251,10 @@ restore the source replacement configuration to continue the build let path = directory.resolve_path(self.config); srcs.push(SourceId::for_directory(&path)?); } + if let Some(path) = def.path { + let path = path.resolve_path(self.config); + srcs.push(SourceId::for_path(&path)?); + } if let Some(git) = def.git { let url = url(&git, &format!("source.{}.git", name))?; let reference = match def.branch {