Explorar o código

lib/model: Detect deleted RO items scanning on non-RO (fixes #6864) (#6865)

Simon Frei %!s(int64=5) %!d(string=hai) anos
pai
achega
e46c8ab9ee
Modificáronse 2 ficheiros con 58 adicións e 14 borrados
  1. 17 14
      lib/model/folder.go
  2. 41 0
      lib/model/model_test.go

+ 17 - 14
lib/model/folder.go

@@ -557,6 +557,8 @@ func (f *folder) scanSubdirs(subDirs []string) error {
 			}
 			}
 
 
 			switch ignored := f.ignores.Match(file.Name).IsIgnored(); {
 			switch ignored := f.ignores.Match(file.Name).IsIgnored(); {
+			case file.IsIgnored() && ignored:
+				return true
 			case !file.IsIgnored() && ignored:
 			case !file.IsIgnored() && ignored:
 				// File was not ignored at last pass but has been ignored.
 				// File was not ignored at last pass but has been ignored.
 				if file.IsDirectory() {
 				if file.IsDirectory() {
@@ -600,24 +602,25 @@ func (f *folder) scanSubdirs(subDirs []string) error {
 					// sure the file gets in sync on the following pull.
 					// sure the file gets in sync on the following pull.
 					nf.Version = protocol.Vector{}
 					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)
 				batchAppend(nf, snap)
 				changes++
 				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
 			return true
 		})
 		})
 
 

+ 41 - 0
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)) {
 func testConfigChangeClosesConnections(t *testing.T, expectFirstClosed, expectSecondClosed bool, pre func(config.Wrapper), fn func(config.Wrapper)) {
 	t.Helper()
 	t.Helper()
 	wcfg, _ := tmpDefaultWrapper()
 	wcfg, _ := tmpDefaultWrapper()