Never use templates when managing git repos

This commit disables usage of git templates whenever Cargo manages
repositories in its internal git database. Templates don't want to be
used at all in these situations and have been known to cause usability
bugs.

Closes #6240
This commit is contained in:
Alex Crichton 2018-11-02 07:46:11 -07:00
parent 6026fc3cf2
commit 2a4cdc677c
2 changed files with 59 additions and 8 deletions

View file

@ -146,7 +146,7 @@ impl GitRemote {
paths::remove_dir_all(dst)?;
}
fs::create_dir_all(dst)?;
let mut repo = git2::Repository::init_bare(dst)?;
let mut repo = init(dst, true)?;
fetch(
&mut repo,
&self.url,
@ -385,7 +385,7 @@ impl<'a> GitCheckout<'a> {
Err(..) => {
let path = parent.workdir().unwrap().join(child.path());
let _ = paths::remove_dir_all(&path);
git2::Repository::init(&path)?
init(&path, false)?
}
};
@ -833,7 +833,7 @@ fn reinitialize(repo: &mut git2::Repository) -> CargoResult<()> {
debug!("reinitializing git repo at {:?}", path);
let tmp = path.join("tmp");
let bare = !repo.path().ends_with(".git");
*repo = git2::Repository::init(&tmp)?;
*repo = init(&tmp, false)?;
for entry in path.read_dir()? {
let entry = entry?;
if entry.file_name().to_str() == Some("tmp") {
@ -842,15 +842,21 @@ fn reinitialize(repo: &mut git2::Repository) -> CargoResult<()> {
let path = entry.path();
drop(paths::remove_file(&path).or_else(|_| paths::remove_dir_all(&path)));
}
if bare {
*repo = git2::Repository::init_bare(path)?;
} else {
*repo = git2::Repository::init(path)?;
}
*repo = init(&path, bare)?;
paths::remove_dir_all(&tmp)?;
Ok(())
}
fn init(path: &Path, bare: bool) -> CargoResult<git2::Repository> {
let mut opts = git2::RepositoryInitOptions::new();
// Skip anyting related to templates, they just call all sorts of issues as
// we really don't want to use them yet they insist on being used. See #6240
// for an example issue that comes up.
opts.external_template(false);
opts.bare(bare);
Ok(git2::Repository::init_opts(&path, &opts)?)
}
/// Updating the index is done pretty regularly so we want it to be as fast as
/// possible. For registries hosted on GitHub (like the crates.io index) there's
/// a fast path available to use [1] to tell us that there's no updates to be

View file

@ -2625,3 +2625,48 @@ fn use_the_cli() {
project.cargo("build -v").with_stderr(stderr).run();
}
#[test]
fn templatedir_doesnt_cause_problems() {
let git_project2 = git::new("dep2", |project| {
project
.file("Cargo.toml", &basic_manifest("dep2", "0.5.0"))
.file("src/lib.rs", "")
}).unwrap();
let git_project = git::new("dep1", |project| {
project
.file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
.file("src/lib.rs", "")
}).unwrap();
let p = project()
.file(
"Cargo.toml",
&format!(r#"
[project]
name = "fo"
version = "0.5.0"
authors = []
[dependencies]
dep1 = {{ git = '{}' }}
"#, git_project.url()),
).file("src/main.rs", "fn main() {}")
.build();
File::create(paths::home().join(".gitconfig"))
.unwrap()
.write_all(
&format!(r#"
[init]
templatedir = {}
"#, git_project2.url()
.to_file_path()
.unwrap()
.to_str()
.unwrap()
.replace("\\", "/")
).as_bytes(),
).unwrap();
p.cargo("build").run();
}