Skip to content

Commit

Permalink
Auto merge of #8453 - sourcefrog:name-length-limit-8452, r=alexcrichton
Browse files Browse the repository at this point in the history
Write GNU tar files, supporting long names.

Fixes #8452

If I understand the previous bugs correctly, long trees packaged using Cargo with this patch will be misinterpreted by Cargo from before Jan 2016. (Without this patch, they can't be written at all.)

To me that seems like long enough ago that it's safe to land this now.

- [x] Add a test.
  • Loading branch information
bors committed Jul 6, 2020
2 parents c95c0b1 + 0dfd4a8 commit 548eea7
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 26 deletions.
32 changes: 6 additions & 26 deletions src/cargo/ops/cargo_package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,28 +501,7 @@ fn tar(
config
.shell()
.verbose(|shell| shell.status("Archiving", &rel_str))?;
// The `tar::Builder` type by default will build GNU archives, but
// unfortunately we force it here to use UStar archives instead. The
// UStar format has more limitations on the length of path name that it
// can encode, so it's not quite as nice to use.
//
// Older cargos, however, had a bug where GNU archives were interpreted
// as UStar archives. This bug means that if we publish a GNU archive
// which has fully filled out metadata it'll be corrupt when unpacked by
// older cargos.
//
// Hopefully in the future after enough cargos have been running around
// with the bugfixed tar-rs library we'll be able to switch this over to
// GNU archives, but for now we'll just say that you can't encode paths
// in archives that are *too* long.
//
// For an instance of this in the wild, use the tar-rs 0.3.3 library to
// unpack the selectors 0.4.0 crate on crates.io. Either that or take a
// look at rust-lang/cargo#2326.
let mut header = Header::new_ustar();
header
.set_path(&ar_path)
.chain_err(|| format!("failed to add to archive: `{}`", rel_str))?;
let mut header = Header::new_gnu();
match contents {
FileContents::OnDisk(disk_path) => {
let mut file = File::open(&disk_path).chain_err(|| {
Expand All @@ -533,9 +512,10 @@ fn tar(
})?;
header.set_metadata(&metadata);
header.set_cksum();
ar.append(&header, &mut file).chain_err(|| {
format!("could not archive source file `{}`", disk_path.display())
})?;
ar.append_data(&mut header, &ar_path, &mut file)
.chain_err(|| {
format!("could not archive source file `{}`", disk_path.display())
})?;
}
FileContents::Generated(generated_kind) => {
let contents = match generated_kind {
Expand All @@ -553,7 +533,7 @@ fn tar(
);
header.set_size(contents.len() as u64);
header.set_cksum();
ar.append(&header, contents.as_bytes())
ar.append_data(&mut header, &ar_path, contents.as_bytes())
.chain_err(|| format!("could not archive source file `{}`", rel_str))?;
}
}
Expand Down
44 changes: 44 additions & 0 deletions tests/testsuite/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1845,3 +1845,47 @@ dependency `bar` does not specify a version.
)
.run();
}

#[cargo_test]
fn long_file_names() {
// Filenames over 100 characters require a GNU extension tarfile.
// See #8453.

registry::init();
let long_name = concat!(
"012345678901234567890123456789012345678901234567890123456789",
"012345678901234567890123456789012345678901234567890123456789",
"012345678901234567890123456789012345678901234567890123456789"
);
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
license = "MIT"
description = "foo"
homepage = "foo"
[dependencies]
"#,
)
.file(long_name, "something")
.file("src/main.rs", "fn main() {}")
.build();

p.cargo("package").run();
p.cargo("package --list")
.with_stdout(&format!(
"\
{}
Cargo.lock
Cargo.toml
Cargo.toml.orig
src/main.rs
",
long_name
))
.run();
}

0 comments on commit 548eea7

Please sign in to comment.