Skip to content

Commit

Permalink
Auto merge of #4180 - pnkfelix:issue-4135, r=alexcrichton
Browse files Browse the repository at this point in the history
Issue 4135: include = [...] should override git file list

Fix #4135: if theres `include = [...]`, then do not prepopulate file list via git.
  • Loading branch information
bors committed Jun 21, 2017
2 parents 402d845 + 749ec6e commit d23510c
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 3 deletions.
26 changes: 23 additions & 3 deletions src/cargo/sources/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,23 @@ impl<'cfg> PathSource<'cfg> {
}
};

// attempt git-prepopulate only if no `include` (rust-lang/cargo#4135)
if include.is_empty() {
if let Some(result) = self.discover_git_and_list_files(pkg, root, &mut filter) {
return result;
}
}

self.list_files_walk(pkg, &mut filter)
}

// Returns Some(_) if found sibling Cargo.toml and .git folder;
// otherwise caller should fall back on full file list.
fn discover_git_and_list_files(&self,
pkg: &Package,
root: &Path,
filter: &mut FnMut(&Path) -> bool)
-> Option<CargoResult<Vec<PathBuf>>> {
// If this package is in a git repository, then we really do want to
// query the git repository as it takes into account items such as
// .gitignore. We're not quite sure where the git repository is,
Expand All @@ -129,11 +146,14 @@ impl<'cfg> PathSource<'cfg> {
// check to see if we are indeed part of the index. If not, then
// this is likely an unrelated git repo, so keep going.
if let Ok(repo) = git2::Repository::open(cur) {
let index = repo.index()?;
let index = match repo.index() {
Ok(index) => index,
Err(err) => return Some(Err(err.into())),
};
let path = util::without_prefix(root, cur)
.unwrap().join("Cargo.toml");
if index.get_path(&path, 0).is_some() {
return self.list_files_git(pkg, repo, &mut filter);
return Some(self.list_files_git(pkg, repo, filter));
}
}
}
Expand All @@ -146,7 +166,7 @@ impl<'cfg> PathSource<'cfg> {
None => break,
}
}
self.list_files_walk(pkg, &mut filter)
return None;
}

fn list_files_git(&self, pkg: &Package, repo: git2::Repository,
Expand Down
113 changes: 113 additions & 0 deletions tests/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1984,3 +1984,116 @@ fn two_at_rev_instead_of_tag() {
assert_that(p.cargo_process("generate-lockfile"), execs().with_status(0));
assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
}

#[test]
fn include_overrides_gitignore() {
let p = git::new("reduction", |repo| {
repo.file("Cargo.toml", r#"
[package]
name = "reduction"
version = "0.5.0"
authors = ["pnkfelix"]
build = "tango-build.rs"
include = ["src/lib.rs", "src/incl.rs", "src/mod.md", "tango-build.rs", "Cargo.toml"]
[build-dependencies]
filetime = "0.1"
"#)
.file(".gitignore", r#"
target
Cargo.lock
# Below files represent generated code, thus not managed by `git`
src/incl.rs
src/not_incl.rs
"#)
.file("tango-build.rs", r#"
extern crate filetime;
use filetime::FileTime;
use std::fs::{self, File};
fn main() {
// generate files, or bring their timestamps into sync.
let source = "src/mod.md";
let metadata = fs::metadata(source).unwrap();
let mtime = FileTime::from_last_modification_time(&metadata);
let atime = FileTime::from_last_access_time(&metadata);
// sync time stamps for generated files with time stamp of source file.
let files = ["src/not_incl.rs", "src/incl.rs"];
for file in files.iter() {
File::create(file).unwrap();
filetime::set_file_times(file, atime, mtime).unwrap();
}
}
"#)
.file("src/lib.rs", r#"
mod not_incl;
mod incl;
"#)
.file("src/mod.md", r#"
(The content of this file does not matter since we are not doing real codegen.)
"#)
}).unwrap();

println!("build 1: all is new");
assert_that(p.cargo("build").arg("-v"),
execs().with_status(0)
.with_stderr("\
[UPDATING] registry `[..]`
[DOWNLOADING] filetime [..]
[DOWNLOADING] libc [..]
[COMPILING] libc [..]
[RUNNING] `rustc --crate-name libc [..]`
[COMPILING] filetime [..]
[RUNNING] `rustc --crate-name filetime [..]`
[COMPILING] reduction [..]
[RUNNING] `rustc --crate-name build_script_tango_build tango-build.rs --crate-type bin [..]`
[RUNNING] `[..][/]build-script-tango-build`
[RUNNING] `rustc --crate-name reduction src[/]lib.rs --crate-type lib [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
"));

println!("build 2: nothing changed; file timestamps reset by build script");
assert_that(p.cargo("build").arg("-v"),
execs().with_status(0)
.with_stderr("\
[FRESH] libc [..]
[FRESH] filetime [..]
[FRESH] reduction [..]
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
"));

println!("build 3: touch `src/not_incl.rs`; expect build script *not* re-run");
sleep_ms(1000);
File::create(p.root().join("src").join("not_incl.rs")).unwrap();

assert_that(p.cargo("build").arg("-v"),
execs().with_status(0)
.with_stderr("\
[FRESH] libc [..]
[FRESH] filetime [..]
[COMPILING] reduction [..]
[RUNNING] `rustc --crate-name reduction src[/]lib.rs --crate-type lib [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
"));

// This final case models the bug from rust-lang/cargo#4135: an
// explicitly included file should cause a build-script re-run,
// even if that same file is matched by `.gitignore`.
println!("build 4: touch `src/incl.rs`; expect build script re-run");
sleep_ms(1000);
File::create(p.root().join("src").join("incl.rs")).unwrap();

assert_that(p.cargo("build").arg("-v"),
execs().with_status(0)
.with_stderr("\
[FRESH] libc [..]
[FRESH] filetime [..]
[COMPILING] reduction [..]
[RUNNING] `[..][/]build-script-tango-build`
[RUNNING] `rustc --crate-name reduction src[/]lib.rs --crate-type lib [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
"));
}

0 comments on commit d23510c

Please sign in to comment.