From e46c8ab9eebb06f07c397037936f7c11ded84484 Mon Sep 17 00:00:00 2001 From: Simon Frei Date: Thu, 30 Jul 2020 13:41:45 +0200 Subject: [PATCH] lib/model: Detect deleted RO items scanning on non-RO (fixes #6864) (#6865) --- lib/model/folder.go | 31 +++++++++++++++++-------------- lib/model/model_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/lib/model/folder.go b/lib/model/folder.go index 808b7d7d4..6e55bba20 100644 --- a/lib/model/folder.go +++ b/lib/model/folder.go @@ -557,6 +557,8 @@ func (f *folder) scanSubdirs(subDirs []string) error { } switch ignored := f.ignores.Match(file.Name).IsIgnored(); { + case file.IsIgnored() && ignored: + return true case !file.IsIgnored() && ignored: // File was not ignored at last pass but has been ignored. if file.IsDirectory() { @@ -600,24 +602,25 @@ func (f *folder) scanSubdirs(subDirs []string) error { // sure the file gets in sync on the following pull. nf.Version = protocol.Vector{} } - + // Check for deleted, locally changed items that noone else has. + if f.localFlags&protocol.FlagLocalReceiveOnly != 0 && len(snap.Availability(file.Name)) == 0 { + file.LocalFlags &^= protocol.FlagLocalReceiveOnly + } batchAppend(nf, snap) changes++ + case file.IsDeleted() && file.IsReceiveOnlyChanged() && f.localFlags&protocol.FlagLocalReceiveOnly != 0 && len(snap.Availability(file.Name)) == 0: + file.Version = protocol.Vector{} + file.LocalFlags &^= protocol.FlagLocalReceiveOnly + batchAppend(file.ConvertDeletedToFileInfo(), snap) + changes++ + case file.IsDeleted() && file.LocalFlags != f.localFlags: + // No need to bump the version for a file that was + // and is deleted and just the local flags changed. + file.LocalFlags = f.localFlags + batchAppend(file.ConvertDeletedToFileInfo(), snap) + changes++ } - // Check for deleted, locally changed items that noone else has. - if f.localFlags&protocol.FlagLocalReceiveOnly == 0 { - return true - } - if !fi.IsDeleted() || !fi.IsReceiveOnlyChanged() || len(snap.Availability(fi.FileName())) > 0 { - return true - } - nf := fi.(db.FileInfoTruncated).ConvertDeletedToFileInfo() - nf.LocalFlags = 0 - nf.Version = protocol.Vector{} - batchAppend(nf, snap) - changes++ - return true }) diff --git a/lib/model/model_test.go b/lib/model/model_test.go index 242db0a07..f6df87692 100644 --- a/lib/model/model_test.go +++ b/lib/model/model_test.go @@ -3943,6 +3943,47 @@ func TestAddFolderCompletion(t *testing.T) { } } +func TestScanDeletedROChangedOnSR(t *testing.T) { + w, fcfg := tmpDefaultWrapper() + fcfg.Type = config.FolderTypeReceiveOnly + waiter, _ := w.SetFolder(fcfg) + waiter.Wait() + m := setupModel(w) + defer cleanupModel(m) + name := "foo" + ffs := fcfg.Filesystem() + + must(t, writeFile(ffs, name, []byte(name), 0644)) + m.ScanFolders() + + file, ok := m.CurrentFolderFile(fcfg.ID, name) + if !ok { + t.Fatal("file missing in db") + } + // A remote must have the file, otherwise the deletion below is + // automatically resolved as not a ro-changed item. + m.IndexUpdate(device1, fcfg.ID, []protocol.FileInfo{file}) + + must(t, ffs.Remove(name)) + m.ScanFolders() + + if receiveOnlyChangedSize(t, m, fcfg.ID).Deleted != 1 { + t.Fatal("expected one receive only changed deleted item") + } + + fcfg.Type = config.FolderTypeSendReceive + waiter, _ = w.SetFolder(fcfg) + waiter.Wait() + m.ScanFolders() + + if receiveOnlyChangedSize(t, m, fcfg.ID).Deleted != 0 { + t.Fatal("expected no receive only changed deleted item") + } + if localSize(t, m, fcfg.ID).Deleted != 1 { + t.Fatal("expected one local deleted item") + } +} + func testConfigChangeClosesConnections(t *testing.T, expectFirstClosed, expectSecondClosed bool, pre func(config.Wrapper), fn func(config.Wrapper)) { t.Helper() wcfg, _ := tmpDefaultWrapper()