diff --git a/lib/model/folder.go b/lib/model/folder.go index c90b9e3b..a0a7bb75 100644 --- a/lib/model/folder.go +++ b/lib/model/folder.go @@ -13,6 +13,7 @@ import ( "time" "github.com/syncthing/syncthing/lib/config" + "github.com/syncthing/syncthing/lib/db" "github.com/syncthing/syncthing/lib/ignore" "github.com/syncthing/syncthing/lib/protocol" "github.com/syncthing/syncthing/lib/sync" @@ -167,6 +168,8 @@ func (f *folder) Serve() { func (f *folder) BringToFront(string) {} +func (f *folder) Override(fs *db.FileSet, updateFn func([]protocol.FileInfo)) {} + func (f *folder) DelayScan(next time.Duration) { f.Delay(next) } diff --git a/lib/model/folder_sendonly.go b/lib/model/folder_sendonly.go index 4a5f9111..448ad09a 100644 --- a/lib/model/folder_sendonly.go +++ b/lib/model/folder_sendonly.go @@ -100,3 +100,43 @@ func (f *sendOnlyFolder) pull() bool { return true } + +func (f *sendOnlyFolder) Override(fs *db.FileSet, updateFn func([]protocol.FileInfo)) { + f.setState(FolderScanning) + batch := make([]protocol.FileInfo, 0, maxBatchSizeFiles) + batchSizeBytes := 0 + fs.WithNeed(protocol.LocalDeviceID, func(fi db.FileIntf) bool { + need := fi.(protocol.FileInfo) + if len(batch) == maxBatchSizeFiles || batchSizeBytes > maxBatchSizeBytes { + updateFn(batch) + batch = batch[:0] + batchSizeBytes = 0 + } + + have, ok := fs.Get(protocol.LocalDeviceID, need.Name) + // Don't override files that are in a bad state (ignored, + // unsupported, must rescan, ...). + if ok && have.IsInvalid() { + return true + } + if !ok || have.Name != need.Name { + // We are missing the file + need.Deleted = true + need.Blocks = nil + need.Version = need.Version.Update(f.shortID) + need.Size = 0 + } else { + // We have the file, replace with our version + have.Version = have.Version.Merge(need.Version).Update(f.shortID) + need = have + } + need.Sequence = 0 + batch = append(batch, need) + batchSizeBytes += need.ProtoSize() + return true + }) + if len(batch) > 0 { + updateFn(batch) + } + f.setState(FolderIdle) +} diff --git a/lib/model/model.go b/lib/model/model.go index 15861347..70f6c511 100644 --- a/lib/model/model.go +++ b/lib/model/model.go @@ -56,6 +56,7 @@ const ( type service interface { BringToFront(string) + Override(*db.FileSet, func([]protocol.FileInfo)) DelayScan(d time.Duration) IgnoresUpdated() // ignore matcher was updated notification SchedulePull() // something relevant changed, we should try a pull @@ -2300,50 +2301,21 @@ func (m *Model) WatchError(folder string) error { } func (m *Model) Override(folder string) { + // Grab the runner and the file set. + m.fmut.RLock() - fs, ok := m.folderFiles[folder] - runner := m.folderRunners[folder] + fs, fsOK := m.folderFiles[folder] + runner, runnerOK := m.folderRunners[folder] m.fmut.RUnlock() - if !ok { + if !fsOK || !runnerOK { return } - runner.setState(FolderScanning) - batch := make([]protocol.FileInfo, 0, maxBatchSizeFiles) - batchSizeBytes := 0 - fs.WithNeed(protocol.LocalDeviceID, func(fi db.FileIntf) bool { - need := fi.(protocol.FileInfo) - if len(batch) == maxBatchSizeFiles || batchSizeBytes > maxBatchSizeBytes { - m.updateLocalsFromScanning(folder, batch) - batch = batch[:0] - batchSizeBytes = 0 - } + // Run the override, taking updates as if they came from scanning. - have, ok := fs.Get(protocol.LocalDeviceID, need.Name) - // Don't override invalid (e.g. ignored) files - if ok && have.Invalid { - return true - } - if !ok || have.Name != need.Name { - // We are missing the file - need.Deleted = true - need.Blocks = nil - need.Version = need.Version.Update(m.shortID) - need.Size = 0 - } else { - // We have the file, replace with our version - have.Version = have.Version.Merge(need.Version).Update(m.shortID) - need = have - } - need.Sequence = 0 - batch = append(batch, need) - batchSizeBytes += need.ProtoSize() - return true + runner.Override(fs, func(files []protocol.FileInfo) { + m.updateLocalsFromScanning(folder, files) }) - if len(batch) > 0 { - m.updateLocalsFromScanning(folder, batch) - } - runner.setState(FolderIdle) } // CurrentSequence returns the change version for the given folder.