mirror of
https://github.com/rust-lang/cargo
synced 2024-10-01 05:23:56 +00:00
Auto merge of #9988 - ehuss:beta-git-fetch-force, r=alexcrichton
[beta] Fix fetching git repos after a force push. Beta backport of #9979.
This commit is contained in:
commit
b2e52d7cab
|
@ -785,29 +785,32 @@ pub fn fetch(
|
||||||
// which need to get fetched. Additionally record if we're fetching tags.
|
// which need to get fetched. Additionally record if we're fetching tags.
|
||||||
let mut refspecs = Vec::new();
|
let mut refspecs = Vec::new();
|
||||||
let mut tags = false;
|
let mut tags = false;
|
||||||
|
// The `+` symbol on the refspec means to allow a forced (fast-forward)
|
||||||
|
// update which is needed if there is ever a force push that requires a
|
||||||
|
// fast-forward.
|
||||||
match reference {
|
match reference {
|
||||||
// For branches and tags we can fetch simply one reference and copy it
|
// For branches and tags we can fetch simply one reference and copy it
|
||||||
// locally, no need to fetch other branches/tags.
|
// locally, no need to fetch other branches/tags.
|
||||||
GitReference::Branch(b) => {
|
GitReference::Branch(b) => {
|
||||||
refspecs.push(format!("refs/heads/{0}:refs/remotes/origin/{0}", b));
|
refspecs.push(format!("+refs/heads/{0}:refs/remotes/origin/{0}", b));
|
||||||
}
|
}
|
||||||
GitReference::Tag(t) => {
|
GitReference::Tag(t) => {
|
||||||
refspecs.push(format!("refs/tags/{0}:refs/remotes/origin/tags/{0}", t));
|
refspecs.push(format!("+refs/tags/{0}:refs/remotes/origin/tags/{0}", t));
|
||||||
}
|
}
|
||||||
|
|
||||||
GitReference::DefaultBranch => {
|
GitReference::DefaultBranch => {
|
||||||
refspecs.push(String::from("HEAD:refs/remotes/origin/HEAD"));
|
refspecs.push(String::from("+HEAD:refs/remotes/origin/HEAD"));
|
||||||
}
|
}
|
||||||
|
|
||||||
GitReference::Rev(rev) => {
|
GitReference::Rev(rev) => {
|
||||||
if rev.starts_with("refs/") {
|
if rev.starts_with("refs/") {
|
||||||
refspecs.push(format!("{0}:{0}", rev));
|
refspecs.push(format!("+{0}:{0}", rev));
|
||||||
} else {
|
} else {
|
||||||
// We don't know what the rev will point to. To handle this
|
// We don't know what the rev will point to. To handle this
|
||||||
// situation we fetch all branches and tags, and then we pray
|
// situation we fetch all branches and tags, and then we pray
|
||||||
// it's somewhere in there.
|
// it's somewhere in there.
|
||||||
refspecs.push(String::from("refs/heads/*:refs/remotes/origin/*"));
|
refspecs.push(String::from("+refs/heads/*:refs/remotes/origin/*"));
|
||||||
refspecs.push(String::from("HEAD:refs/remotes/origin/HEAD"));
|
refspecs.push(String::from("+HEAD:refs/remotes/origin/HEAD"));
|
||||||
tags = true;
|
tags = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3280,3 +3280,105 @@ fn metadata_master_consistency() {
|
||||||
let bar_source = format!("git+{}", git_project.url());
|
let bar_source = format!("git+{}", git_project.url());
|
||||||
p.cargo("metadata").with_json(&metadata(&bar_source)).run();
|
p.cargo("metadata").with_json(&metadata(&bar_source)).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cargo_test]
|
||||||
|
fn git_with_force_push() {
|
||||||
|
// Checks that cargo can handle force-pushes to git repos.
|
||||||
|
// This works by having a git dependency that is updated with an amend
|
||||||
|
// commit, and tries with various forms (default branch, branch, rev,
|
||||||
|
// tag).
|
||||||
|
let main = |text| format!(r#"pub fn f() {{ println!("{}"); }}"#, text);
|
||||||
|
let (git_project, repo) = git::new_repo("dep1", |project| {
|
||||||
|
project
|
||||||
|
.file("Cargo.toml", &basic_lib_manifest("dep1"))
|
||||||
|
.file("src/lib.rs", &main("one"))
|
||||||
|
});
|
||||||
|
let manifest = |extra| {
|
||||||
|
format!(
|
||||||
|
r#"
|
||||||
|
[project]
|
||||||
|
name = "foo"
|
||||||
|
version = "0.0.1"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
dep1 = {{ git = "{}"{} }}
|
||||||
|
"#,
|
||||||
|
git_project.url(),
|
||||||
|
extra
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let p = project()
|
||||||
|
.file("Cargo.toml", &manifest(""))
|
||||||
|
.file("src/main.rs", "fn main() { dep1::f(); }")
|
||||||
|
.build();
|
||||||
|
// Download the original and make sure it is OK.
|
||||||
|
p.cargo("build").run();
|
||||||
|
p.rename_run("foo", "foo1").with_stdout("one").run();
|
||||||
|
|
||||||
|
let find_head = || t!(t!(repo.head()).peel_to_commit());
|
||||||
|
|
||||||
|
let amend_commit = |text| {
|
||||||
|
// commit --amend a change that will require a force fetch.
|
||||||
|
git_project.change_file("src/lib.rs", &main(text));
|
||||||
|
git::add(&repo);
|
||||||
|
let commit = find_head();
|
||||||
|
let tree_id = t!(t!(repo.index()).write_tree());
|
||||||
|
t!(commit.amend(
|
||||||
|
Some("HEAD"),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(&t!(repo.find_tree(tree_id)))
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut rename_annoyance = 1;
|
||||||
|
|
||||||
|
let mut verify = |text: &str| {
|
||||||
|
// Perform the fetch.
|
||||||
|
p.cargo("update").run();
|
||||||
|
p.cargo("build").run();
|
||||||
|
rename_annoyance += 1;
|
||||||
|
p.rename_run("foo", &format!("foo{}", rename_annoyance))
|
||||||
|
.with_stdout(text)
|
||||||
|
.run();
|
||||||
|
};
|
||||||
|
|
||||||
|
amend_commit("two");
|
||||||
|
verify("two");
|
||||||
|
|
||||||
|
// Try with a rev.
|
||||||
|
let head1 = find_head().id().to_string();
|
||||||
|
let extra = format!(", rev = \"{}\"", head1);
|
||||||
|
p.change_file("Cargo.toml", &manifest(&extra));
|
||||||
|
verify("two");
|
||||||
|
amend_commit("three");
|
||||||
|
let head2 = find_head().id().to_string();
|
||||||
|
assert_ne!(&head1, &head2);
|
||||||
|
let extra = format!(", rev = \"{}\"", head2);
|
||||||
|
p.change_file("Cargo.toml", &manifest(&extra));
|
||||||
|
verify("three");
|
||||||
|
|
||||||
|
// Try with a tag.
|
||||||
|
git::tag(&repo, "my-tag");
|
||||||
|
p.change_file("Cargo.toml", &manifest(", tag = \"my-tag\""));
|
||||||
|
verify("three");
|
||||||
|
amend_commit("tag-three");
|
||||||
|
let head = t!(t!(repo.head()).peel(git2::ObjectType::Commit));
|
||||||
|
t!(repo.tag("my-tag", &head, &t!(repo.signature()), "move tag", true));
|
||||||
|
verify("tag-three");
|
||||||
|
|
||||||
|
// Try with a branch.
|
||||||
|
let br = t!(repo.branch("awesome-stuff", &find_head(), false));
|
||||||
|
t!(repo.checkout_tree(&t!(br.get().peel(git2::ObjectType::Tree)), None));
|
||||||
|
t!(repo.set_head("refs/heads/awesome-stuff"));
|
||||||
|
git_project.change_file("src/lib.rs", &main("awesome-three"));
|
||||||
|
git::add(&repo);
|
||||||
|
git::commit(&repo);
|
||||||
|
p.change_file("Cargo.toml", &manifest(", branch = \"awesome-stuff\""));
|
||||||
|
verify("awesome-three");
|
||||||
|
amend_commit("awesome-four");
|
||||||
|
verify("awesome-four");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue