Skip to content

Commit 3c64b29

Browse files
authored
Merge pull request #8805 from rust-lang/revert-8788-duplicate-paths
Revert "crates_io_tarball: Disallow paths differing only by case"
2 parents 0b33b66 + 767823e commit 3c64b29

File tree

3 files changed

+30
-45
lines changed

3 files changed

+30
-45
lines changed

crates/crates_io_tarball/src/lib.rs

+13-38
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::manifest::validate_manifest;
99
pub use crate::vcs_info::CargoVcsInfo;
1010
pub use cargo_manifest::{Manifest, StringOrBool};
1111
use flate2::read::GzDecoder;
12-
use std::collections::{BTreeMap, HashSet};
12+
use std::collections::BTreeMap;
1313
use std::io::Read;
1414
use std::path::{Path, PathBuf};
1515
use std::str::FromStr;
@@ -33,8 +33,6 @@ pub enum TarballError {
3333
Malformed(#[source] std::io::Error),
3434
#[error("invalid path found: {0}")]
3535
InvalidPath(String),
36-
#[error("duplicate path found: {0}")]
37-
DuplicatePath(String),
3836
#[error("unexpected symlink or hard link found: {0}")]
3937
UnexpectedSymlink(String),
4038
#[error("Cargo.toml manifest is missing")]
@@ -43,6 +41,8 @@ pub enum TarballError {
4341
InvalidManifest(#[from] cargo_manifest::Error),
4442
#[error("Cargo.toml manifest is incorrectly cased: {0:?}")]
4543
IncorrectlyCasedManifest(PathBuf),
44+
#[error("more than one Cargo.toml manifest in tarball: {0:?}")]
45+
TooManyManifests(Vec<PathBuf>),
4646
#[error(transparent)]
4747
IO(#[from] std::io::Error),
4848
}
@@ -67,7 +67,6 @@ pub fn process_tarball<R: Read>(
6767

6868
let mut vcs_info = None;
6969
let mut manifests = BTreeMap::new();
70-
let mut paths = HashSet::new();
7170

7271
for entry in archive.entries()? {
7372
let mut entry = entry.map_err(TarballError::Malformed)?;
@@ -94,13 +93,6 @@ pub fn process_tarball<R: Read>(
9493
));
9594
}
9695

97-
let lowercase_path = entry_path.as_os_str().to_ascii_lowercase();
98-
if !paths.insert(lowercase_path) {
99-
return Err(TarballError::DuplicatePath(
100-
entry_path.display().to_string(),
101-
));
102-
}
103-
10496
// Let's go hunting for the VCS info and crate manifest. The only valid place for these is
10597
// in the package root in the tarball.
10698
if entry_path.parent() == Some(pkg_root) {
@@ -124,6 +116,13 @@ pub fn process_tarball<R: Read>(
124116
}
125117
}
126118

119+
if manifests.len() > 1 {
120+
// There are no scenarios where we want to accept a crate file with multiple manifests.
121+
return Err(TarballError::TooManyManifests(
122+
manifests.into_keys().collect(),
123+
));
124+
}
125+
127126
// Although we're interested in all possible cases of `Cargo.toml` above to protect users
128127
// on case-insensitive filesystems, to match the behaviour of cargo we should only actually
129128
// accept `Cargo.toml` and (the now deprecated) `cargo.toml` as valid options for the
@@ -302,36 +301,12 @@ mod tests {
302301
};
303302

304303
let err = assert_err!(process(vec!["cargo.toml", "Cargo.toml"]));
305-
assert_snapshot!(err, @"duplicate path found: foo-0.0.1/Cargo.toml");
304+
assert_snapshot!(err, @r###"more than one Cargo.toml manifest in tarball: ["foo-0.0.1/Cargo.toml", "foo-0.0.1/cargo.toml"]"###);
306305

307306
let err = assert_err!(process(vec!["Cargo.toml", "Cargo.Toml"]));
308-
assert_snapshot!(err, @"duplicate path found: foo-0.0.1/Cargo.Toml");
307+
assert_snapshot!(err, @r###"more than one Cargo.toml manifest in tarball: ["foo-0.0.1/Cargo.Toml", "foo-0.0.1/Cargo.toml"]"###);
309308

310309
let err = assert_err!(process(vec!["Cargo.toml", "cargo.toml", "CARGO.TOML"]));
311-
assert_snapshot!(err, @"duplicate path found: foo-0.0.1/cargo.toml");
312-
}
313-
314-
#[test]
315-
fn test_duplicate_paths() {
316-
let tarball = TarballBuilder::new()
317-
.add_file("foo-0.0.1/Cargo.toml", MANIFEST)
318-
.add_file("foo-0.0.1/foo.rs", b"")
319-
.add_file("foo-0.0.1/foo.rs", b"")
320-
.build();
321-
322-
let err = assert_err!(process_tarball("foo-0.0.1", &*tarball, MAX_SIZE));
323-
assert_snapshot!(err, @"duplicate path found: foo-0.0.1/foo.rs")
324-
}
325-
326-
#[test]
327-
fn test_case_insensitivity() {
328-
let tarball = TarballBuilder::new()
329-
.add_file("foo-0.0.1/Cargo.toml", MANIFEST)
330-
.add_file("foo-0.0.1/foo.rs", b"")
331-
.add_file("foo-0.0.1/FOO.rs", b"")
332-
.build();
333-
334-
let err = assert_err!(process_tarball("foo-0.0.1", &*tarball, MAX_SIZE));
335-
assert_snapshot!(err, @"duplicate path found: foo-0.0.1/FOO.rs")
310+
assert_snapshot!(err, @r###"more than one Cargo.toml manifest in tarball: ["foo-0.0.1/CARGO.TOML", "foo-0.0.1/Cargo.toml", "foo-0.0.1/cargo.toml"]"###);
336311
}
337312
}

src/controllers/krate/publish.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -714,11 +714,6 @@ impl From<TarballError> for BoxedAppError {
714714
"uploaded tarball is malformed or too large when decompressed",
715715
),
716716
TarballError::InvalidPath(path) => bad_request(format!("invalid path found: {path}")),
717-
TarballError::DuplicatePath(path) => {
718-
bad_request(format!(
719-
"uploaded tarball contains more than one file with the same path: `{path}`"
720-
))
721-
}
722717
TarballError::UnexpectedSymlink(path) => {
723718
bad_request(format!("unexpected symlink or hard link found: {path}"))
724719
}
@@ -732,6 +727,21 @@ impl From<TarballError> for BoxedAppError {
732727
name = name.to_string_lossy(),
733728
))
734729
}
730+
TarballError::TooManyManifests(paths) => {
731+
let paths = paths
732+
.into_iter()
733+
.map(|path| {
734+
path.file_name()
735+
.unwrap_or_default()
736+
.to_string_lossy()
737+
.into_owned()
738+
})
739+
.collect::<Vec<_>>()
740+
.join("`, `");
741+
bad_request(format!(
742+
"uploaded tarball contains more than one `Cargo.toml` manifest file; found `{paths}`"
743+
))
744+
}
735745
TarballError::InvalidManifest(err) => bad_request(format!(
736746
"failed to parse `Cargo.toml` manifest file\n\n{err}"
737747
)),
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
22
source: src/tests/krate/publish/manifest.rs
3-
expression: response.json()
3+
expression: response.into_json()
44
---
55
{
66
"errors": [
77
{
8-
"detail": "uploaded tarball contains more than one file with the same path: `foo-1.0.0/cargo.toml`"
8+
"detail": "uploaded tarball contains more than one `Cargo.toml` manifest file; found `Cargo.toml`, `cargo.toml`"
99
}
1010
]
1111
}

0 commit comments

Comments
 (0)