mirror of
https://github.com/rust-lang/cargo
synced 2024-10-01 05:23:56 +00:00
auto merge of #139 : tomjakubowski/cargo/fix-symlink-blowup, r=alexcrichton
Fingerprinting will fail at an `fs::stat()` call if there is a symlink in a package's directory pointing to a non-existent file or directory. This commit recovers from an `fs::stat(`) error on these bogus symlinks by faking an mtime of 0, which should not affect the overall fingerprint. Fix #135
This commit is contained in:
commit
6248ebe5b2
|
@ -106,7 +106,12 @@ impl Source for PathSource {
|
|||
|
||||
fn walk(path: &Path, is_root: bool) -> CargoResult<u64> {
|
||||
if !path.is_dir() {
|
||||
return Ok(try!(fs::stat(path)).modified)
|
||||
// An fs::stat error here is either because path is a
|
||||
// broken symlink, a permissions error, or a race
|
||||
// condition where this path was rm'ed - either way,
|
||||
// we can ignore the error and treat the path's mtime
|
||||
// as 0.
|
||||
return Ok(fs::stat(path).map(|s| s.modified).unwrap_or(0))
|
||||
}
|
||||
// Don't recurse into any sub-packages that we have
|
||||
if !is_root && path.join("Cargo.toml").exists() { return Ok(0) }
|
||||
|
|
|
@ -51,11 +51,36 @@ impl FileBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
#[deriving(PartialEq,Clone)]
|
||||
struct SymlinkBuilder {
|
||||
dst: Path,
|
||||
src: Path
|
||||
}
|
||||
|
||||
impl SymlinkBuilder {
|
||||
pub fn new(dst: Path, src: Path) -> SymlinkBuilder {
|
||||
SymlinkBuilder { dst: dst, src: src }
|
||||
}
|
||||
|
||||
fn mk(&self) -> Result<(), String> {
|
||||
try!(mkdir_recursive(&self.dirname()));
|
||||
|
||||
fs::symlink(&self.dst, &self.src)
|
||||
.with_err_msg(format!("Could not create symlink; dst={} src={}",
|
||||
self.dst.display(), self.src.display()))
|
||||
}
|
||||
|
||||
fn dirname(&self) -> Path {
|
||||
Path::new(self.src.dirname())
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(PartialEq,Clone)]
|
||||
pub struct ProjectBuilder {
|
||||
name: String,
|
||||
root: Path,
|
||||
files: Vec<FileBuilder>
|
||||
files: Vec<FileBuilder>,
|
||||
symlinks: Vec<SymlinkBuilder>
|
||||
}
|
||||
|
||||
impl ProjectBuilder {
|
||||
|
@ -63,7 +88,8 @@ impl ProjectBuilder {
|
|||
ProjectBuilder {
|
||||
name: name.to_str(),
|
||||
root: root,
|
||||
files: vec!()
|
||||
files: vec!(),
|
||||
symlinks: vec!()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,6 +119,13 @@ impl ProjectBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn symlink<T: BytesContainer>(mut self, dst: T,
|
||||
src: T) -> ProjectBuilder {
|
||||
self.symlinks.push(SymlinkBuilder::new(self.root.join(dst),
|
||||
self.root.join(src)));
|
||||
self
|
||||
}
|
||||
|
||||
// TODO: return something different than a ProjectBuilder
|
||||
pub fn build<'a>(&'a self) -> &'a ProjectBuilder {
|
||||
match self.build_with_result() {
|
||||
|
@ -112,6 +145,10 @@ impl ProjectBuilder {
|
|||
try!(file.mk());
|
||||
}
|
||||
|
||||
for symlink in self.symlinks.iter() {
|
||||
try!(symlink.mk());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -751,3 +751,18 @@ test!(self_dependency {
|
|||
assert_that(p.cargo_process("cargo-build"),
|
||||
execs().with_status(0));
|
||||
})
|
||||
|
||||
#[cfg(not(windows))]
|
||||
test!(ignore_broken_symlinks {
|
||||
let p = project("foo")
|
||||
.file("Cargo.toml", basic_bin_manifest("foo").as_slice())
|
||||
.file("src/foo.rs", main_file(r#""i am foo""#, []).as_slice())
|
||||
.symlink("Notafile", "bar");
|
||||
|
||||
assert_that(p.cargo_process("cargo-build"), execs());
|
||||
assert_that(&p.bin("foo"), existing_file());
|
||||
|
||||
assert_that(
|
||||
process(p.bin("foo")),
|
||||
execs().with_stdout("i am foo\n"));
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue