Skip to content

Commit 07b9c33

Browse files
committed
fix(package): Normalize path separators
A windows user could use `\` and no Linux or Mac user could use the package. This normalizes the separator to what works on all platforms.
1 parent 9394ecf commit 07b9c33

File tree

2 files changed

+59
-27
lines changed

2 files changed

+59
-27
lines changed

src/cargo/util/toml/mod.rs

+51-19
Original file line numberDiff line numberDiff line change
@@ -2338,11 +2338,11 @@ fn prepare_toml_for_publish(
23382338
package.workspace = None;
23392339
if let Some(StringOrBool::String(path)) = &package.build {
23402340
let path = paths::normalize_path(Path::new(path));
2341-
package.build = Some(StringOrBool::String(
2341+
package.build = Some(StringOrBool::String(normalize_path_string_sep(
23422342
path.into_os_string()
23432343
.into_string()
23442344
.map_err(|_err| anyhow::format_err!("non-UTF8 `package.build`"))?,
2345-
));
2345+
)));
23462346
}
23472347
let current_resolver = package
23482348
.resolver
@@ -2372,10 +2372,12 @@ fn prepare_toml_for_publish(
23722372
let abs_license_path = paths::normalize_path(&package_root.join(license_path));
23732373
if let Ok(license_file) = abs_license_path.strip_prefix(package_root) {
23742374
package.license_file = Some(manifest::InheritableField::Value(
2375-
license_file
2376-
.to_str()
2377-
.ok_or_else(|| anyhow::format_err!("non-UTF8 `package.license-file`"))?
2378-
.to_owned(),
2375+
normalize_path_string_sep(
2376+
license_file
2377+
.to_str()
2378+
.ok_or_else(|| anyhow::format_err!("non-UTF8 `package.license-file`"))?
2379+
.to_owned(),
2380+
),
23792381
));
23802382
} else {
23812383
// This path points outside of the package root. `cargo package`
@@ -2401,10 +2403,14 @@ fn prepare_toml_for_publish(
24012403
let abs_readme_path = paths::normalize_path(&package_root.join(readme_path));
24022404
if let Ok(readme_path) = abs_readme_path.strip_prefix(package_root) {
24032405
package.readme = Some(manifest::InheritableField::Value(StringOrBool::String(
2404-
readme_path
2405-
.to_str()
2406-
.ok_or_else(|| anyhow::format_err!("non-UTF8 `package.license-file`"))?
2407-
.to_owned(),
2406+
normalize_path_string_sep(
2407+
readme_path
2408+
.to_str()
2409+
.ok_or_else(|| {
2410+
anyhow::format_err!("non-UTF8 `package.license-file`")
2411+
})?
2412+
.to_owned(),
2413+
),
24082414
)));
24092415
} else {
24102416
// This path points outside of the package root. `cargo package`
@@ -2427,16 +2433,19 @@ fn prepare_toml_for_publish(
24272433

24282434
let lib = if let Some(mut target) = me.lib.clone() {
24292435
if let Some(path) = target.path {
2430-
target.path = Some(manifest::PathValue(normalize_path(&path.0)));
2436+
target.path = Some(manifest::PathValue(normalize_path_sep(
2437+
normalize_path(&path.0),
2438+
"lib",
2439+
)?));
24312440
}
24322441
Some(target)
24332442
} else {
24342443
None
24352444
};
2436-
let bin = prepare_targets_for_publish(me.bin.as_ref());
2437-
let example = prepare_targets_for_publish(me.example.as_ref());
2438-
let test = prepare_targets_for_publish(me.test.as_ref());
2439-
let bench = prepare_targets_for_publish(me.bench.as_ref());
2445+
let bin = prepare_targets_for_publish(me.bin.as_ref(), "bin")?;
2446+
let example = prepare_targets_for_publish(me.example.as_ref(), "example")?;
2447+
let test = prepare_targets_for_publish(me.test.as_ref(), "test")?;
2448+
let bench = prepare_targets_for_publish(me.bench.as_ref(), "bench")?;
24402449

24412450
let all = |_d: &manifest::TomlDependency| true;
24422451
let mut manifest = manifest::TomlManifest {
@@ -2594,17 +2603,40 @@ fn prepare_toml_for_publish(
25942603

25952604
fn prepare_targets_for_publish(
25962605
targets: Option<&Vec<manifest::TomlTarget>>,
2597-
) -> Option<Vec<manifest::TomlTarget>> {
2598-
let targets = targets?;
2606+
context: &str,
2607+
) -> CargoResult<Option<Vec<manifest::TomlTarget>>> {
2608+
let Some(targets) = targets else {
2609+
return Ok(None);
2610+
};
25992611

26002612
let mut prepared = Vec::with_capacity(targets.len());
26012613
for target in targets {
26022614
let mut target = target.clone();
26032615
if let Some(path) = target.path {
2604-
target.path = Some(manifest::PathValue(normalize_path(&path.0)));
2616+
target.path = Some(manifest::PathValue(normalize_path_sep(
2617+
normalize_path(&path.0),
2618+
context,
2619+
)?));
26052620
}
26062621
prepared.push(target);
26072622
}
26082623

2609-
Some(prepared)
2624+
Ok(Some(prepared))
2625+
}
2626+
2627+
fn normalize_path_sep(path: PathBuf, context: &str) -> CargoResult<PathBuf> {
2628+
let path = path
2629+
.into_os_string()
2630+
.into_string()
2631+
.map_err(|_err| anyhow::format_err!("non-UTF8 path for {context}"))?;
2632+
let path = normalize_path_string_sep(path);
2633+
Ok(path.into())
2634+
}
2635+
2636+
fn normalize_path_string_sep(path: String) -> String {
2637+
if std::path::MAIN_SEPARATOR != '/' {
2638+
path.replace(std::path::MAIN_SEPARATOR, "/")
2639+
} else {
2640+
path
2641+
}
26102642
}

tests/testsuite/package.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -3637,30 +3637,30 @@ edition = "2015"
36373637
name = "foo"
36383638
version = "0.0.1"
36393639
authors = []
3640-
build = 'src/build.rs'
3640+
build = "src/build.rs"
36413641
description = "foo"
36423642
documentation = "docs.rs/foo"
3643-
readme = 'docs/README.md'
3644-
license-file = 'docs/LICENSE'
3643+
readme = "docs/README.md"
3644+
license-file = "docs/LICENSE"
36453645
36463646
[lib]
3647-
path = 'src/lib.rs'
3647+
path = "src/lib.rs"
36483648
36493649
[[bin]]
36503650
name = "foo"
3651-
path = 'src/bin/foo/main.rs'
3651+
path = "src/bin/foo/main.rs"
36523652
36533653
[[example]]
36543654
name = "example_foo"
3655-
path = 'examples/example_foo.rs'
3655+
path = "examples/example_foo.rs"
36563656
36573657
[[test]]
36583658
name = "test_foo"
3659-
path = 'tests/test_foo.rs'
3659+
path = "tests/test_foo.rs"
36603660
36613661
[[bench]]
36623662
name = "bench_foo"
3663-
path = 'benches/bench_foo.rs'
3663+
path = "benches/bench_foo.rs"
36643664
"#,
36653665
)],
36663666
);

0 commit comments

Comments
 (0)