Skip to content

Commit 0356306

Browse files
committed
Resolve crates.io workspace dependencies
1 parent 8564be1 commit 0356306

File tree

4 files changed

+71
-4
lines changed

4 files changed

+71
-4
lines changed

src/source_distribution.rs

+64-4
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,19 @@ const LOCAL_DEPENDENCIES_FOLDER: &str = "local_dependencies";
1919
/// This method is rather frail, but unfortunately I don't know a better solution.
2020
fn rewrite_cargo_toml(
2121
manifest_path: impl AsRef<Path>,
22+
workspace_manifest: &toml_edit::Document,
2223
known_path_deps: &HashMap<String, PathBuf>,
2324
local_deps_folder: String,
2425
root_crate: bool,
2526
) -> Result<String> {
27+
let manifest_path = manifest_path.as_ref();
2628
let text = fs::read_to_string(&manifest_path).context(format!(
2729
"Can't read Cargo.toml at {}",
28-
manifest_path.as_ref().display(),
30+
manifest_path.display(),
2931
))?;
3032
let mut data = text.parse::<toml_edit::Document>().context(format!(
3133
"Failed to parse Cargo.toml at {}",
32-
manifest_path.as_ref().display()
34+
manifest_path.display()
3335
))?;
3436
let mut rewritten = false;
3537
// ˇˇˇˇˇˇˇˇˇˇˇˇ dep_category
@@ -39,6 +41,10 @@ fn rewrite_cargo_toml(
3941
// ^^^^^^^^^^^^^ dep_name
4042
for dep_category in &["dependencies", "dev-dependencies", "build-dependencies"] {
4143
if let Some(table) = data.get_mut(*dep_category).and_then(|x| x.as_table_mut()) {
44+
let workspace_deps = workspace_manifest
45+
.get("workspace")
46+
.and_then(|x| x.get(dep_category))
47+
.and_then(|x| x.as_table());
4248
let dep_names: Vec<_> = table.iter().map(|(key, _)| key.to_string()).collect();
4349
for dep_name in dep_names {
4450
let workspace_inherit = table
@@ -55,19 +61,63 @@ fn rewrite_cargo_toml(
5561
if !table[&dep_name]["path"].is_str() {
5662
bail!(
5763
"In {}, {} {} has a path value that is not a string",
58-
manifest_path.as_ref().display(),
64+
manifest_path.display(),
5965
dep_category,
6066
dep_name
6167
)
6268
}
69+
} else {
70+
// If a workspace inherited dependency isn't a path dep,
71+
// we need to replace `workspace = true` with its full requirement spec.
72+
if !known_path_deps.contains_key(&dep_name) {
73+
if let Some(workspace_dep) = workspace_deps.and_then(|x| x.get(&dep_name)) {
74+
let mut workspace_dep = workspace_dep.clone();
75+
// Merge optional and features from the current Cargo.toml
76+
if table[&dep_name].get("optional").is_some() {
77+
workspace_dep["optional"] = table[&dep_name]["optional"].clone();
78+
}
79+
if let Some(features) =
80+
table[&dep_name].get("features").and_then(|x| x.as_array())
81+
{
82+
let existing_features = workspace_dep
83+
.as_table_like_mut()
84+
.unwrap()
85+
.entry("features")
86+
.or_insert_with(|| {
87+
toml_edit::Item::Value(toml_edit::Array::new().into())
88+
})
89+
.as_array_mut()
90+
.with_context(|| {
91+
format!(
92+
"In {}, {} {} has a features value that is not an array",
93+
manifest_path.display(),
94+
dep_category,
95+
dep_name
96+
)
97+
})?;
98+
existing_features.extend(features);
99+
}
100+
table[&dep_name] = workspace_dep;
101+
rewritten = true;
102+
} else {
103+
bail!(
104+
"In {}, {} {} is marked as `workspace = true`, but it is found neither in \
105+
the workspace manifest nor in the known path dependencies",
106+
manifest_path.display(),
107+
dep_category,
108+
dep_name
109+
)
110+
}
111+
continue;
112+
}
63113
}
64114
if !known_path_deps.contains_key(&dep_name) {
65115
bail!(
66116
"cargo metadata does not know about the path for {}.{} present in {}, \
67117
which should never happen ಠ_ಠ",
68118
dep_category,
69119
dep_name,
70-
manifest_path.as_ref().display()
120+
manifest_path.display()
71121
);
72122
}
73123
// This is the location of the targeted crate in the source distribution
@@ -136,6 +186,7 @@ fn add_crate_to_source_distribution(
136186
writer: &mut SDistWriter,
137187
pyproject_toml_path: impl AsRef<Path>,
138188
manifest_path: impl AsRef<Path>,
189+
workspace_manifest: &toml_edit::Document,
139190
prefix: impl AsRef<Path>,
140191
known_path_deps: &HashMap<String, PathBuf>,
141192
root_crate: bool,
@@ -230,6 +281,7 @@ fn add_crate_to_source_distribution(
230281
};
231282
let rewritten_cargo_toml = rewrite_cargo_toml(
232283
&manifest_path,
284+
workspace_manifest,
233285
known_path_deps,
234286
local_deps_folder,
235287
root_crate,
@@ -296,6 +348,12 @@ pub fn source_distribution(
296348
let metadata21 = &build_context.metadata21;
297349
let manifest_path = &build_context.manifest_path;
298350
let pyproject_toml_path = fs::canonicalize(&build_context.pyproject_toml_path)?;
351+
let workspace_manifest_path = build_context
352+
.cargo_metadata
353+
.workspace_root
354+
.join("Cargo.toml");
355+
let workspace_manifest: toml_edit::Document =
356+
fs::read_to_string(&workspace_manifest_path)?.parse()?;
299357

300358
let known_path_deps = find_path_deps(&build_context.cargo_metadata)?;
301359

@@ -312,6 +370,7 @@ pub fn source_distribution(
312370
&mut writer,
313371
&pyproject_toml_path,
314372
&path_dep,
373+
&workspace_manifest,
315374
&root_dir.join(LOCAL_DEPENDENCIES_FOLDER).join(name),
316375
&known_path_deps,
317376
false,
@@ -328,6 +387,7 @@ pub fn source_distribution(
328387
&mut writer,
329388
&pyproject_toml_path,
330389
&manifest_path,
390+
&workspace_manifest,
331391
&root_dir,
332392
&known_path_deps,
333393
true,

test-crates/workspace-inheritance/Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test-crates/workspace-inheritance/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ members = [
55
]
66

77
[workspace.dependencies]
8+
libc = { version = "0.2", features = ["std"] }
89
generic_lib = { path = "generic_lib" }

test-crates/workspace-inheritance/python/Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,8 @@ crate-type = ["cdylib"]
1111
[dependencies]
1212
pyo3 = { version = "0.16.5", features = ["extension-module"] }
1313
generic_lib.workspace = true
14+
15+
[dependencies.libc]
16+
workspace = true
17+
optional = true
18+
features = ["extra_traits"]

0 commit comments

Comments
 (0)