mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-14 01:04:14 +00:00
lib/model: Scan conflicts after creation (#5511)
Also unflakes and improve TestRequestRemoteRenameChanged.
This commit is contained in:
parent
5fd2cab102
commit
225c0dda80
@ -196,7 +196,7 @@ func (f *sendReceiveFolder) pull() bool {
|
|||||||
|
|
||||||
changed := f.pullerIteration(ignores, folderFiles, scanChan)
|
changed := f.pullerIteration(ignores, folderFiles, scanChan)
|
||||||
|
|
||||||
l.Debugln(f, "changed", changed, "on try", tries)
|
l.Debugln(f, "changed", changed, "on try", tries+1)
|
||||||
|
|
||||||
if changed == 0 {
|
if changed == 0 {
|
||||||
// No files were changed by the puller, so we are in
|
// 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
|
|||||||
// we have resolved the conflict.
|
// we have resolved the conflict.
|
||||||
file.Version = file.Version.Merge(cur.Version)
|
file.Version = file.Version.Merge(cur.Version)
|
||||||
err = osutil.InWritableDir(func(name string) error {
|
err = osutil.InWritableDir(func(name string) error {
|
||||||
return f.moveForConflict(name, file.ModifiedBy.String())
|
return f.moveForConflict(name, file.ModifiedBy.String(), scanChan)
|
||||||
}, f.fs, file.Name)
|
}, f.fs, file.Name)
|
||||||
} else if f.versioner != nil && !cur.IsSymlink() {
|
} else if f.versioner != nil && !cur.IsSymlink() {
|
||||||
err = osutil.InWritableDir(f.versioner.Archive, f.fs, file.Name)
|
err = osutil.InWritableDir(f.versioner.Archive, f.fs, file.Name)
|
||||||
@ -1512,7 +1512,7 @@ func (f *sendReceiveFolder) performFinish(ignores *ignore.Matcher, file, curFile
|
|||||||
|
|
||||||
file.Version = file.Version.Merge(curFile.Version)
|
file.Version = file.Version.Merge(curFile.Version)
|
||||||
err = osutil.InWritableDir(func(name string) error {
|
err = osutil.InWritableDir(func(name string) error {
|
||||||
return f.moveForConflict(name, file.ModifiedBy.String())
|
return f.moveForConflict(name, file.ModifiedBy.String(), scanChan)
|
||||||
}, f.fs, file.Name)
|
}, f.fs, file.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -1736,7 +1736,7 @@ func removeAvailability(availabilities []Availability, availability Availability
|
|||||||
return availabilities
|
return availabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *sendReceiveFolder) moveForConflict(name string, lastModBy string) error {
|
func (f *sendReceiveFolder) moveForConflict(name string, lastModBy string, scanChan chan<- string) error {
|
||||||
if strings.Contains(filepath.Base(name), ".sync-conflict-") {
|
if strings.Contains(filepath.Base(name), ".sync-conflict-") {
|
||||||
l.Infoln("Conflict for", name, "which is already a conflict copy; not copying again.")
|
l.Infoln("Conflict for", name, "which is already a conflict copy; not copying again.")
|
||||||
if err := f.fs.Remove(name); err != nil && !fs.IsNotExist(err) {
|
if err := f.fs.Remove(name); err != nil && !fs.IsNotExist(err) {
|
||||||
@ -1777,6 +1777,9 @@ func (f *sendReceiveFolder) moveForConflict(name string, lastModBy string) error
|
|||||||
l.Debugln(f, "globbing for conflicts", gerr)
|
l.Debugln(f, "globbing for conflicts", gerr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err == nil {
|
||||||
|
scanChan <- newName
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -792,17 +792,6 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
|
|||||||
fc.sendIndexUpdate()
|
fc.sendIndexUpdate()
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
done = make(chan struct{})
|
|
||||||
fc.mut.Lock()
|
|
||||||
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
|
|
||||||
select {
|
|
||||||
case <-done:
|
|
||||||
t.Fatalf("More than one index update sent")
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
close(done)
|
|
||||||
}
|
|
||||||
fc.mut.Unlock()
|
|
||||||
case <-time.After(10 * time.Second):
|
case <-time.After(10 * time.Second):
|
||||||
t.Fatal("timed out")
|
t.Fatal("timed out")
|
||||||
}
|
}
|
||||||
@ -813,6 +802,42 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var gotA, gotB, gotConfl bool
|
||||||
|
done = make(chan struct{})
|
||||||
|
fc.mut.Lock()
|
||||||
|
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
t.Fatalf("Received more index updates than expected")
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
for _, f := range fs {
|
||||||
|
switch {
|
||||||
|
case f.Name == a:
|
||||||
|
if gotA {
|
||||||
|
t.Error("Got more than one index update for", f.Name)
|
||||||
|
}
|
||||||
|
gotA = true
|
||||||
|
case f.Name == b:
|
||||||
|
if gotB {
|
||||||
|
t.Error("Got more than one index update for", f.Name)
|
||||||
|
}
|
||||||
|
gotB = true
|
||||||
|
case strings.HasPrefix(f.Name, "b.sync-conflict-"):
|
||||||
|
if gotConfl {
|
||||||
|
t.Error("Got more than one index update for conflicts of", f.Name)
|
||||||
|
}
|
||||||
|
gotConfl = true
|
||||||
|
default:
|
||||||
|
t.Error("Got unexpected file in index update", f.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if gotA && gotB && gotConfl {
|
||||||
|
close(done)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fc.mut.Unlock()
|
||||||
|
|
||||||
fd, err := tfs.OpenFile(b, fs.OptReadWrite, 0644)
|
fd, err := tfs.OpenFile(b, fs.OptReadWrite, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -826,11 +851,20 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
|
|||||||
// rename
|
// rename
|
||||||
fc.deleteFile(a)
|
fc.deleteFile(a)
|
||||||
fc.updateFile(b, 0644, protocol.FileInfoTypeFile, data[a])
|
fc.updateFile(b, 0644, protocol.FileInfoTypeFile, data[a])
|
||||||
|
// Make sure the remote file for b is newer and thus stays global -> local conflict
|
||||||
|
fc.mut.Lock()
|
||||||
|
for i := range fc.files {
|
||||||
|
if fc.files[i].Name == b {
|
||||||
|
fc.files[i].ModifiedS += 100
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fc.mut.Unlock()
|
||||||
fc.sendIndexUpdate()
|
fc.sendIndexUpdate()
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
case <-time.After(10 * time.Second):
|
case <-time.After(10 * time.Second):
|
||||||
t.Fatal("timed out")
|
t.Errorf("timed out without receiving all expected index updates")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check outcome
|
// Check outcome
|
||||||
@ -839,9 +873,16 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
|
|||||||
case path == a:
|
case path == a:
|
||||||
t.Errorf(`File "a" was not removed`)
|
t.Errorf(`File "a" was not removed`)
|
||||||
case path == b:
|
case path == b:
|
||||||
if err := equalContents(filepath.Join(tmpDir, b), otherData); err != nil {
|
if err := equalContents(filepath.Join(tmpDir, b), data[a]); err != nil {
|
||||||
t.Errorf(`Modified file "b" was overwritten`)
|
t.Error(`File "b" has unexpected content (renamed from a on remote)`)
|
||||||
}
|
}
|
||||||
|
case strings.HasPrefix(path, b+".sync-conflict-"):
|
||||||
|
if err := equalContents(filepath.Join(tmpDir, path), otherData); err != nil {
|
||||||
|
t.Error(`Sync conflict of "b" has unexptected content`)
|
||||||
|
}
|
||||||
|
case path == "." || strings.HasPrefix(path, ".stfolder"):
|
||||||
|
default:
|
||||||
|
t.Error("Found unexpected file", path)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user