Skip to content

Commit 5c0c213

Browse files
committed
Build UStar archives by default
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. Closes #2326
1 parent f104538 commit 5c0c213

File tree

1 file changed

+31
-2
lines changed

1 file changed

+31
-2
lines changed

src/cargo/ops/cargo_package.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::io::prelude::*;
22
use std::fs::{self, File};
33
use std::path::{self, Path, PathBuf};
44

5-
use tar::{Archive, Builder};
5+
use tar::{Archive, Builder, Header};
66
use flate2::{GzBuilder, Compression};
77
use flate2::read::GzDecoder;
88

@@ -135,7 +135,36 @@ fn tar(pkg: &Package,
135135
}));
136136
let path = format!("{}-{}{}{}", pkg.name(), pkg.version(),
137137
path::MAIN_SEPARATOR, relative);
138-
try!(ar.append_file(&path, &mut file).chain_error(|| {
138+
139+
// The tar::Builder type by default will build GNU archives, but
140+
// unfortunately we force it here to use UStar archives instead. The
141+
// UStar format has more limitations on the length of path name that it
142+
// can encode, so it's not quite as nice to use.
143+
//
144+
// Older cargos, however, had a bug where GNU archives were interpreted
145+
// as UStar archives. This bug means that if we publish a GNU archive
146+
// which has fully filled out metadata it'll be corrupt when unpacked by
147+
// older cargos.
148+
//
149+
// Hopefully in the future after enough cargos have been running around
150+
// with the bugfixed tar-rs library we'll be able to switch this over to
151+
// GNU archives, but for now we'll just say that you can't encode paths
152+
// in archives that are *too* long.
153+
//
154+
// For an instance of this in the wild, use the tar-rs 0.3.3 library to
155+
// unpack the selectors 0.4.0 crate on crates.io. Either that or take a
156+
// look at rust-lang/cargo#2326
157+
let mut header = Header::new_ustar();
158+
let metadata = try!(file.metadata().chain_error(|| {
159+
human(format!("could not learn metadata for: `{}`", relative))
160+
}));
161+
try!(header.set_path(&path).chain_error(|| {
162+
human(format!("failed to add to archive: `{}`", relative))
163+
}));
164+
header.set_metadata(&metadata);
165+
header.set_cksum();
166+
167+
try!(ar.append(&header, &mut file).chain_error(|| {
139168
internal(format!("could not archive source file `{}`", relative))
140169
}));
141170
}

0 commit comments

Comments
 (0)