Skip to content

Commit 225c0dd

Browse files
imsodincalmh
authored andcommitted
lib/model: Scan conflicts after creation (syncthing#5511)
Also unflakes and improve TestRequestRemoteRenameChanged.
1 parent 5fd2cab commit 225c0dd

File tree

2 files changed

+62
-18
lines changed

2 files changed

+62
-18
lines changed

lib/model/folder_sendrecv.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ func (f *sendReceiveFolder) pull() bool {
196196

197197
changed := f.pullerIteration(ignores, folderFiles, scanChan)
198198

199-
l.Debugln(f, "changed", changed, "on try", tries)
199+
l.Debugln(f, "changed", changed, "on try", tries+1)
200200

201201
if changed == 0 {
202202
// No files were changed by the puller, so we are in
@@ -795,7 +795,7 @@ func (f *sendReceiveFolder) deleteFile(file protocol.FileInfo, scanChan chan<- s
795795
// we have resolved the conflict.
796796
file.Version = file.Version.Merge(cur.Version)
797797
err = osutil.InWritableDir(func(name string) error {
798-
return f.moveForConflict(name, file.ModifiedBy.String())
798+
return f.moveForConflict(name, file.ModifiedBy.String(), scanChan)
799799
}, f.fs, file.Name)
800800
} else if f.versioner != nil && !cur.IsSymlink() {
801801
err = osutil.InWritableDir(f.versioner.Archive, f.fs, file.Name)
@@ -1512,7 +1512,7 @@ func (f *sendReceiveFolder) performFinish(ignores *ignore.Matcher, file, curFile
15121512

15131513
file.Version = file.Version.Merge(curFile.Version)
15141514
err = osutil.InWritableDir(func(name string) error {
1515-
return f.moveForConflict(name, file.ModifiedBy.String())
1515+
return f.moveForConflict(name, file.ModifiedBy.String(), scanChan)
15161516
}, f.fs, file.Name)
15171517
if err != nil {
15181518
return err
@@ -1736,7 +1736,7 @@ func removeAvailability(availabilities []Availability, availability Availability
17361736
return availabilities
17371737
}
17381738

1739-
func (f *sendReceiveFolder) moveForConflict(name string, lastModBy string) error {
1739+
func (f *sendReceiveFolder) moveForConflict(name string, lastModBy string, scanChan chan<- string) error {
17401740
if strings.Contains(filepath.Base(name), ".sync-conflict-") {
17411741
l.Infoln("Conflict for", name, "which is already a conflict copy; not copying again.")
17421742
if err := f.fs.Remove(name); err != nil && !fs.IsNotExist(err) {
@@ -1777,6 +1777,9 @@ func (f *sendReceiveFolder) moveForConflict(name string, lastModBy string) error
17771777
l.Debugln(f, "globbing for conflicts", gerr)
17781778
}
17791779
}
1780+
if err == nil {
1781+
scanChan <- newName
1782+
}
17801783
return err
17811784
}
17821785

lib/model/requests_test.go

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -792,17 +792,6 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
792792
fc.sendIndexUpdate()
793793
select {
794794
case <-done:
795-
done = make(chan struct{})
796-
fc.mut.Lock()
797-
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
798-
select {
799-
case <-done:
800-
t.Fatalf("More than one index update sent")
801-
default:
802-
}
803-
close(done)
804-
}
805-
fc.mut.Unlock()
806795
case <-time.After(10 * time.Second):
807796
t.Fatal("timed out")
808797
}
@@ -813,6 +802,42 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
813802
}
814803
}
815804

805+
var gotA, gotB, gotConfl bool
806+
done = make(chan struct{})
807+
fc.mut.Lock()
808+
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
809+
select {
810+
case <-done:
811+
t.Fatalf("Received more index updates than expected")
812+
default:
813+
}
814+
for _, f := range fs {
815+
switch {
816+
case f.Name == a:
817+
if gotA {
818+
t.Error("Got more than one index update for", f.Name)
819+
}
820+
gotA = true
821+
case f.Name == b:
822+
if gotB {
823+
t.Error("Got more than one index update for", f.Name)
824+
}
825+
gotB = true
826+
case strings.HasPrefix(f.Name, "b.sync-conflict-"):
827+
if gotConfl {
828+
t.Error("Got more than one index update for conflicts of", f.Name)
829+
}
830+
gotConfl = true
831+
default:
832+
t.Error("Got unexpected file in index update", f.Name)
833+
}
834+
}
835+
if gotA && gotB && gotConfl {
836+
close(done)
837+
}
838+
}
839+
fc.mut.Unlock()
840+
816841
fd, err := tfs.OpenFile(b, fs.OptReadWrite, 0644)
817842
if err != nil {
818843
t.Fatal(err)
@@ -826,11 +851,20 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
826851
// rename
827852
fc.deleteFile(a)
828853
fc.updateFile(b, 0644, protocol.FileInfoTypeFile, data[a])
854+
// Make sure the remote file for b is newer and thus stays global -> local conflict
855+
fc.mut.Lock()
856+
for i := range fc.files {
857+
if fc.files[i].Name == b {
858+
fc.files[i].ModifiedS += 100
859+
break
860+
}
861+
}
862+
fc.mut.Unlock()
829863
fc.sendIndexUpdate()
830864
select {
831865
case <-done:
832866
case <-time.After(10 * time.Second):
833-
t.Fatal("timed out")
867+
t.Errorf("timed out without receiving all expected index updates")
834868
}
835869

836870
// Check outcome
@@ -839,9 +873,16 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
839873
case path == a:
840874
t.Errorf(`File "a" was not removed`)
841875
case path == b:
842-
if err := equalContents(filepath.Join(tmpDir, b), otherData); err != nil {
843-
t.Errorf(`Modified file "b" was overwritten`)
876+
if err := equalContents(filepath.Join(tmpDir, b), data[a]); err != nil {
877+
t.Error(`File "b" has unexpected content (renamed from a on remote)`)
878+
}
879+
case strings.HasPrefix(path, b+".sync-conflict-"):
880+
if err := equalContents(filepath.Join(tmpDir, path), otherData); err != nil {
881+
t.Error(`Sync conflict of "b" has unexptected content`)
844882
}
883+
case path == "." || strings.HasPrefix(path, ".stfolder"):
884+
default:
885+
t.Error("Found unexpected file", path)
845886
}
846887
return nil
847888
})

0 commit comments

Comments
 (0)