fix(client): three-way merge when a file changed on both sides
This commit is contained in:
1 parent
e89cf7864a
commit
30cd772f08
3 files changed
+123
-2
No files matched your search
@@ -203,6 +203,73 @@ func TestLaterEditWinsAndLoserStaysInHistory(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestConcurrentEditsOfDifferentLinesMerge(t *testing.T) {
|
||||
mac, dell := setup(t)
|
||||
path := "docs/agents/plan.md"
|
||||
write(t, mac.root, path, "# plan\n\n## todo\n- a\n\n## notes\n- x\n")
|
||||
mac.sync()
|
||||
dell.sync()
|
||||
|
||||
write(t, mac.root, path, "# plan\n\n## todo\n- a\n- from mac\n\n## notes\n- x\n")
|
||||
write(t, dell.root, path, "# plan\n\n## todo\n- a\n\n## notes\n- x\n- from dell\n")
|
||||
dell.sync()
|
||||
mac.sync()
|
||||
dell.sync()
|
||||
|
||||
merged := "# plan\n\n## todo\n- a\n- from mac\n\n## notes\n- x\n- from dell\n"
|
||||
mac.expect(path, merged)
|
||||
dell.expect(path, merged)
|
||||
state, err := mac.client.State(context.Background(), repoKey(t, mac), "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, _ := mac.client.Blob(context.Background(), state.Spaces[protocol.SharedSpace][path].Hash); string(got) != merged {
|
||||
t.Fatalf("server has %q, want %q", got, merged)
|
||||
}
|
||||
for _, m := range []*machine{mac, dell, mac} {
|
||||
if res := m.sync(); res.Pushed != 0 || res.Pulled != 0 {
|
||||
t.Fatalf("merged file keeps syncing: %+v", res)
|
||||
}
|
||||
}
|
||||
revisions, err := mac.client.Revisions(context.Background(), repoKey(t, mac), path)
|
||||
if err != nil || len(revisions) != 3 {
|
||||
t.Fatalf("want base, dell and one merged revision, got %d (%v)", len(revisions), err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConflictingOrBinaryEditsFallBackToLaterWins(t *testing.T) {
|
||||
for name, versions := range map[string][3]string{
|
||||
"same line": {"1\n2\n3\n4\n5\n", "mac\n2\n3\n4\n5\n", "dell\n2\n3\n4\n5\n"},
|
||||
"nul byte": {"1\n2\n3\n4\n5\n\x00\n", "mac\n2\n3\n4\n5\n\x00\n", "1\n2\n3\n4\ndell\n\x00\n"},
|
||||
"invalid utf8": {"1\n2\n3\n4\n5\n\xff\n", "mac\n2\n3\n4\n5\n\xff\n", "1\n2\n3\n4\ndell\n\xff\n"},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
mac, dell := setup(t)
|
||||
path := "docs/agents/plan.md"
|
||||
write(t, mac.root, path, versions[0])
|
||||
mac.sync()
|
||||
dell.sync()
|
||||
|
||||
write(t, mac.root, path, versions[1])
|
||||
old := time.Now().Add(-time.Hour)
|
||||
if err := os.Chtimes(filepath.Join(mac.root, path), old, old); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
write(t, dell.root, path, versions[2])
|
||||
dell.sync()
|
||||
mac.sync()
|
||||
dell.sync()
|
||||
|
||||
mac.expect(path, versions[2])
|
||||
dell.expect(path, versions[2])
|
||||
revisions, err := mac.client.Revisions(context.Background(), repoKey(t, mac), path)
|
||||
if err != nil || len(revisions) != 4 {
|
||||
t.Fatalf("want base, dell, losing mac and restored dell revisions, got %d (%v)", len(revisions), err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRulesFileTravelsAndHostileServerPathsAreIgnored(t *testing.T) {
|
||||
mac, dell := setup(t)
|
||||
write(t, mac.root, RulesFile, "shared notes\n")
|
||||
|
||||
Reference in new issue
Block a user