[+] Conflict resolution (#4)

* [+] Conflict resolution

* [F] Fix conflict resolution branches being synched
This commit is contained in:
2026-05-08 01:16:13 -04:00
committed by GitHub
parent 67dd55a1cf
commit ebeb045c51
13 changed files with 1370 additions and 37 deletions
+100
View File
@@ -180,6 +180,83 @@ fn branch_decisions_force_selects_newest_divergent_tip() {
assert_eq!(main.target_remotes, vec!["a".to_string()]);
}
#[test]
fn auto_rebase_branch_conflict_replays_later_tip_and_marks_force_targets() {
let fixture = GitFixture::new();
let base = fixture.commit("base", "base", 1_700_000_000);
fixture.push_head(&fixture.remote_a, "main");
fixture.push_head(&fixture.remote_b, "main");
let a_tip = fixture.commit_file("a", "a.txt", "a\n", 1_700_000_100);
fixture.push_head(&fixture.remote_a, "main");
fixture.reset_hard(&base);
let b_tip = fixture.commit_file("b", "b.txt", "b\n", 1_700_000_200);
fixture.push_head(&fixture.remote_b, "main");
let mirror = fixture.mirror();
fixture.fetch_all(&mirror);
let (_, conflicts) = mirror.branch_decisions(&fixture.remotes(), false).unwrap();
let decision = mirror
.auto_rebase_branch_conflict(&fixture.remotes(), "main", &conflicts[0].tips)
.unwrap();
assert_eq!(decision.branch, "main");
assert_ne!(decision.sha, a_tip);
assert_ne!(decision.sha, b_tip);
assert_eq!(decision.updates.len(), 2);
let a_update = decision
.updates
.iter()
.find(|update| update.target_remote == "a")
.unwrap();
assert!(!a_update.force);
let b_update = decision
.updates
.iter()
.find(|update| update.target_remote == "b")
.unwrap();
assert!(b_update.force);
mirror
.push_branch_updates(&fixture.remotes(), &decision.updates)
.unwrap();
assert_eq!(
fixture.remote_ref(&fixture.remote_a, "refs/heads/main"),
decision.sha
);
assert_eq!(
fixture.remote_ref(&fixture.remote_b, "refs/heads/main"),
decision.sha
);
}
#[test]
fn auto_rebase_branch_conflict_fails_on_file_conflict() {
let fixture = GitFixture::new();
fixture.commit_file("base", "file.txt", "base\n", 1_700_000_000);
let base = fixture.head();
fixture.push_head(&fixture.remote_a, "main");
fixture.push_head(&fixture.remote_b, "main");
fixture.commit_file("a", "file.txt", "a\n", 1_700_000_100);
fixture.push_head(&fixture.remote_a, "main");
fixture.reset_hard(&base);
fixture.commit_file("b", "file.txt", "b\n", 1_700_000_200);
fixture.push_head(&fixture.remote_b, "main");
let mirror = fixture.mirror();
fixture.fetch_all(&mirror);
let (_, conflicts) = mirror.branch_decisions(&fixture.remotes(), false).unwrap();
let error = mirror
.auto_rebase_branch_conflict(&fixture.remotes(), "main", &conflicts[0].tips)
.unwrap_err()
.to_string();
assert!(error.contains("auto-rebase failed"));
}
#[test]
fn push_branches_creates_missing_branch_on_other_remotes() {
let fixture = GitFixture::new();
@@ -369,6 +446,29 @@ impl GitFixture {
self.head()
}
fn commit_file(
&self,
message: &str,
file_name: &str,
contents: &str,
timestamp: i64,
) -> String {
let path = self.work.join(file_name);
fs::write(path, contents).unwrap();
git(Some(&self.work), ["add", file_name]);
let date = format!("@{timestamp} +0000");
let output = Command::new("git")
.current_dir(&self.work)
.env("GIT_AUTHOR_DATE", &date)
.env("GIT_COMMITTER_DATE", &date)
.args(["commit", "-m", message])
.output()
.unwrap();
assert_success(&output, "git commit");
self.head()
}
fn head(&self) -> String {
git_output(Some(&self.work), ["rev-parse", "HEAD"])
}