lib/config, lib/model: Handle shared with information in config (fixes #4870) (#4974)

This commit is contained in:
Simon Frei
2018-06-06 23:34:11 +02:00
committed by GitHub
parent 53a029a796
commit e2c44f519c
3 changed files with 144 additions and 189 deletions

View File

@@ -261,6 +261,15 @@ func (f FolderConfiguration) RequiresRestartOnly() FolderConfiguration {
return copy return copy
} }
func (f *FolderConfiguration) SharedWith(device protocol.DeviceID) bool {
for _, dev := range f.Devices {
if dev.DeviceID == device {
return true
}
}
return false
}
type FolderDeviceConfigurationList []FolderDeviceConfiguration type FolderDeviceConfigurationList []FolderDeviceConfiguration
func (l FolderDeviceConfigurationList) Less(a, b int) bool { func (l FolderDeviceConfigurationList) Less(a, b int) bool {

View File

@@ -95,8 +95,6 @@ type Model struct {
folderCfgs map[string]config.FolderConfiguration // folder -> cfg folderCfgs map[string]config.FolderConfiguration // folder -> cfg
folderFiles map[string]*db.FileSet // folder -> files folderFiles map[string]*db.FileSet // folder -> files
folderDevices folderDeviceSet // folder -> deviceIDs
deviceFolders map[protocol.DeviceID][]string // deviceID -> folders
deviceStatRefs map[protocol.DeviceID]*stats.DeviceStatisticsReference // deviceID -> statsRef deviceStatRefs map[protocol.DeviceID]*stats.DeviceStatisticsReference // deviceID -> statsRef
folderIgnores map[string]*ignore.Matcher // folder -> matcher object folderIgnores map[string]*ignore.Matcher // folder -> matcher object
folderRunners map[string]service // folder -> puller or scanner folderRunners map[string]service // folder -> puller or scanner
@@ -150,8 +148,6 @@ func NewModel(cfg *config.Wrapper, id protocol.DeviceID, clientName, clientVersi
clientVersion: clientVersion, clientVersion: clientVersion,
folderCfgs: make(map[string]config.FolderConfiguration), folderCfgs: make(map[string]config.FolderConfiguration),
folderFiles: make(map[string]*db.FileSet), folderFiles: make(map[string]*db.FileSet),
folderDevices: make(folderDeviceSet),
deviceFolders: make(map[protocol.DeviceID][]string),
deviceStatRefs: make(map[protocol.DeviceID]*stats.DeviceStatisticsReference), deviceStatRefs: make(map[protocol.DeviceID]*stats.DeviceStatisticsReference),
folderIgnores: make(map[string]*ignore.Matcher), folderIgnores: make(map[string]*ignore.Matcher),
folderRunners: make(map[string]service), folderRunners: make(map[string]service),
@@ -326,11 +322,6 @@ func (m *Model) addFolderLocked(cfg config.FolderConfiguration) {
folderFs := cfg.Filesystem() folderFs := cfg.Filesystem()
m.folderFiles[cfg.ID] = db.NewFileSet(cfg.ID, folderFs, m.db) m.folderFiles[cfg.ID] = db.NewFileSet(cfg.ID, folderFs, m.db)
for _, device := range cfg.Devices {
m.folderDevices.set(device.DeviceID, cfg.ID)
m.deviceFolders[device.DeviceID] = append(m.deviceFolders[device.DeviceID], cfg.ID)
}
ignores := ignore.New(folderFs, ignore.WithCache(m.cacheIgnoredFiles)) ignores := ignore.New(folderFs, ignore.WithCache(m.cacheIgnoredFiles))
if err := ignores.Load(".stignore"); err != nil && !fs.IsNotExist(err) { if err := ignores.Load(".stignore"); err != nil && !fs.IsNotExist(err) {
l.Warnln("Loading ignores:", err) l.Warnln("Loading ignores:", err)
@@ -344,7 +335,7 @@ func (m *Model) RemoveFolder(cfg config.FolderConfiguration) {
// Delete syncthing specific files // Delete syncthing specific files
cfg.Filesystem().RemoveAll(config.DefaultMarkerName) cfg.Filesystem().RemoveAll(config.DefaultMarkerName)
m.tearDownFolderLocked(cfg.ID) m.tearDownFolderLocked(cfg)
// Remove it from the database // Remove it from the database
db.DropFolder(m.db, cfg.ID) db.DropFolder(m.db, cfg.ID)
@@ -352,47 +343,43 @@ func (m *Model) RemoveFolder(cfg config.FolderConfiguration) {
m.fmut.Unlock() m.fmut.Unlock()
} }
func (m *Model) tearDownFolderLocked(folder string) { func (m *Model) tearDownFolderLocked(cfg config.FolderConfiguration) {
// Stop the services running for this folder // Stop the services running for this folder
for _, id := range m.folderRunnerTokens[folder] { for _, id := range m.folderRunnerTokens[cfg.ID] {
m.Remove(id) m.Remove(id)
} }
// Close connections to affected devices // Close connections to affected devices
for dev := range m.folderDevices[folder] { for _, dev := range cfg.Devices {
if conn, ok := m.conn[dev]; ok { if conn, ok := m.conn[dev.DeviceID]; ok {
closeRawConn(conn) closeRawConn(conn)
} }
} }
// Clean up our config maps // Clean up our config maps
delete(m.folderCfgs, folder) delete(m.folderCfgs, cfg.ID)
delete(m.folderFiles, folder) delete(m.folderFiles, cfg.ID)
delete(m.folderDevices, folder) delete(m.folderIgnores, cfg.ID)
delete(m.folderIgnores, folder) delete(m.folderRunners, cfg.ID)
delete(m.folderRunners, folder) delete(m.folderRunnerTokens, cfg.ID)
delete(m.folderRunnerTokens, folder) delete(m.folderStatRefs, cfg.ID)
delete(m.folderStatRefs, folder)
for dev, folders := range m.deviceFolders {
m.deviceFolders[dev] = stringSliceWithout(folders, folder)
}
} }
func (m *Model) RestartFolder(cfg config.FolderConfiguration) { func (m *Model) RestartFolder(from, to config.FolderConfiguration) {
if len(cfg.ID) == 0 { if len(to.ID) == 0 {
panic("cannot add empty folder id") panic("cannot add empty folder id")
} }
m.fmut.Lock() m.fmut.Lock()
m.pmut.Lock() m.pmut.Lock()
m.tearDownFolderLocked(cfg.ID) m.tearDownFolderLocked(from)
if cfg.Paused { if to.Paused {
l.Infoln("Paused folder", cfg.Description()) l.Infoln("Paused folder", to.Description())
} else { } else {
m.addFolderLocked(cfg) m.addFolderLocked(to)
folderType := m.startFolderLocked(cfg.ID) folderType := m.startFolderLocked(to.ID)
l.Infoln("Restarted folder", cfg.Description(), fmt.Sprintf("(%s)", folderType)) l.Infoln("Restarted folder", to.Description(), fmt.Sprintf("(%s)", folderType))
} }
m.pmut.Unlock() m.pmut.Unlock()
@@ -842,8 +829,11 @@ func (m *Model) handleIndex(deviceID protocol.DeviceID, folder string, fs []prot
l.Debugf("%v (in): %s / %q: %d files", op, deviceID, folder, len(fs)) l.Debugf("%v (in): %s / %q: %d files", op, deviceID, folder, len(fs))
if !m.folderSharedWith(folder, deviceID) { if cfg, ok := m.cfg.Folder(folder); !ok || !cfg.SharedWith(deviceID) {
l.Debugf("%v for unexpected folder ID %q sent from device %q; ensure that the folder exists and that this device is selected under \"Share With\" in the folder configuration.", op, folder, deviceID) l.Infof("%v for unexpected folder ID %q sent from device %q; ensure that the folder exists and that this device is selected under \"Share With\" in the folder configuration.", op, folder, deviceID)
return
} else if cfg.Paused {
l.Debugf("%v for paused folder (ID %q) sent from device %q.", op, folder, deviceID)
return return
} }
@@ -881,22 +871,6 @@ func (m *Model) handleIndex(deviceID protocol.DeviceID, folder string, fs []prot
}) })
} }
func (m *Model) folderSharedWith(folder string, deviceID protocol.DeviceID) bool {
m.fmut.RLock()
shared := m.folderSharedWithLocked(folder, deviceID)
m.fmut.RUnlock()
return shared
}
func (m *Model) folderSharedWithLocked(folder string, deviceID protocol.DeviceID) bool {
for _, nfolder := range m.deviceFolders[deviceID] {
if nfolder == folder {
return true
}
}
return false
}
func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterConfig) { func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterConfig) {
// Check the peer device's announced folders against our own. Emits events // Check the peer device's announced folders against our own. Emits events
// for folders that we don't expect (unknown or not shared). // for folders that we don't expect (unknown or not shared).
@@ -935,21 +909,12 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
m.fmut.Lock() m.fmut.Lock()
var paused []string var paused []string
for _, folder := range cm.Folders { for _, folder := range cm.Folders {
if folder.Paused { cfg, ok := m.cfg.Folder(folder.ID)
paused = append(paused, folder.ID) if !ok || !cfg.SharedWith(deviceID) {
continue if m.cfg.IgnoredFolder(folder.ID) {
} l.Infof("Ignoring folder %s from device %s since we are configured to", folder.Description(), deviceID)
continue
if cfg, ok := m.cfg.Folder(folder.ID); ok && cfg.Paused { }
continue
}
if m.cfg.IgnoredFolder(folder.ID) {
l.Infof("Ignoring folder %s from device %s since we are configured to", folder.Description(), deviceID)
continue
}
if !m.folderSharedWithLocked(folder.ID, deviceID) {
events.Default.Log(events.FolderRejected, map[string]string{ events.Default.Log(events.FolderRejected, map[string]string{
"folder": folder.ID, "folder": folder.ID,
"folderLabel": folder.Label, "folderLabel": folder.Label,
@@ -958,6 +923,13 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
l.Infof("Unexpected folder %s sent from device %q; ensure that the folder exists and that this device is selected under \"Share With\" in the folder configuration.", folder.Description(), deviceID) l.Infof("Unexpected folder %s sent from device %q; ensure that the folder exists and that this device is selected under \"Share With\" in the folder configuration.", folder.Description(), deviceID)
continue continue
} }
if folder.Paused {
paused = append(paused, folder.ID)
continue
}
if cfg.Paused {
continue
}
if !folder.DisableTempIndexes { if !folder.DisableTempIndexes {
tempIndexFolders = append(tempIndexFolders, folder.ID) tempIndexFolders = append(tempIndexFolders, folder.ID)
@@ -1094,7 +1066,6 @@ func (m *Model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm
continue continue
} }
nextDevice:
for _, device := range folder.Devices { for _, device := range folder.Devices {
// No need to share with self. // No need to share with self.
if device.ID == m.id { if device.ID == m.id {
@@ -1106,15 +1077,10 @@ func (m *Model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm
if _, ok := m.cfg.Devices()[device.ID]; !ok { if _, ok := m.cfg.Devices()[device.ID]; !ok {
// The device is currently unknown. Add it to the config. // The device is currently unknown. Add it to the config.
m.introduceDevice(device, introducerCfg) m.introduceDevice(device, introducerCfg)
changed = true } else if fcfg.SharedWith(device.ID) {
} else { // We already share the folder with this device, so
for _, dev := range fcfg.DeviceIDs() { // nothing to do.
if dev == device.ID { continue
// We already share the folder with this device, so
// nothing to do.
continue nextDevice
}
}
} }
// We don't yet share this folder with this device. Add the device // We don't yet share this folder with this device. Add the device
@@ -1138,51 +1104,54 @@ func (m *Model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm
// handleDeintroductions handles removals of devices/shares that are removed by an introducer device // handleDeintroductions handles removals of devices/shares that are removed by an introducer device
func (m *Model) handleDeintroductions(introducerCfg config.DeviceConfiguration, cm protocol.ClusterConfig, foldersDevices folderDeviceSet) bool { func (m *Model) handleDeintroductions(introducerCfg config.DeviceConfiguration, cm protocol.ClusterConfig, foldersDevices folderDeviceSet) bool {
changed := false changed := false
foldersIntroducedByOthers := make(folderDeviceSet) devicesNotIntroduced := make(map[protocol.DeviceID]struct{})
folders := m.cfg.FolderList()
// Check if we should unshare some folders, if the introducer has unshared them. // Check if we should unshare some folders, if the introducer has unshared them.
for _, folderCfg := range m.cfg.Folders() { for i := range folders {
folderChanged := false for k := 0; k < len(folders[i].Devices); k++ {
for i := 0; i < len(folderCfg.Devices); i++ { if folders[i].Devices[k].IntroducedBy != introducerCfg.DeviceID {
if folderCfg.Devices[i].IntroducedBy == introducerCfg.DeviceID { devicesNotIntroduced[folders[i].Devices[k].DeviceID] = struct{}{}
if !foldersDevices.has(folderCfg.Devices[i].DeviceID, folderCfg.ID) { continue
// We could not find that folder shared on the }
// introducer with the device that was introduced to us. if !foldersDevices.has(folders[i].Devices[k].DeviceID, folders[i].ID) {
// We should follow and unshare as well. // We could not find that folder shared on the
l.Infof("Unsharing folder %s with %v as introducer %v no longer shares the folder with that device", folderCfg.Description(), folderCfg.Devices[i].DeviceID, folderCfg.Devices[i].IntroducedBy) // introducer with the device that was introduced to us.
folderCfg.Devices = append(folderCfg.Devices[:i], folderCfg.Devices[i+1:]...) // We should follow and unshare as well.
i-- l.Infof("Unsharing folder %s with %v as introducer %v no longer shares the folder with that device", folders[i].Description(), folders[i].Devices[k].DeviceID, folders[i].Devices[k].IntroducedBy)
folderChanged = true folders[i].Devices = append(folders[i].Devices[:k], folders[i].Devices[k+1:]...)
} k--
} else { changed = true
foldersIntroducedByOthers.set(folderCfg.Devices[i].DeviceID, folderCfg.ID)
} }
}
// We've modified the folder, hence update it.
if folderChanged {
m.cfg.SetFolder(folderCfg)
changed = true
} }
} }
// Check if we should remove some devices, if the introducer no longer // Check if we should remove some devices, if the introducer no longer
// shares any folder with them. Yet do not remove if we share other // shares any folder with them. Yet do not remove if we share other
// folders that haven't been introduced by the introducer. // folders that haven't been introduced by the introducer.
for _, device := range m.cfg.Devices() { devMap := m.cfg.Devices()
devices := make([]config.DeviceConfiguration, 0, len(devMap))
for deviceID, device := range devMap {
if device.IntroducedBy == introducerCfg.DeviceID { if device.IntroducedBy == introducerCfg.DeviceID {
if !foldersDevices.hasDevice(device.DeviceID) { if !foldersDevices.hasDevice(deviceID) {
if foldersIntroducedByOthers.hasDevice(device.DeviceID) { if _, ok := devicesNotIntroduced[deviceID]; !ok {
l.Infof("Would have removed %v as %v no longer shares any folders, yet there are other folders that are shared with this device that haven't been introduced by this introducer.", device.DeviceID, device.IntroducedBy) // The introducer no longer shares any folder with the
// device, remove the device.
l.Infof("Removing device %v as introducer %v no longer shares any folders with that device", deviceID, device.IntroducedBy)
changed = true
continue continue
} }
// The introducer no longer shares any folder with the l.Infof("Would have removed %v as %v no longer shares any folders, yet there are other folders that are shared with this device that haven't been introduced by this introducer.", deviceID, device.IntroducedBy)
// device, remove the device.
l.Infof("Removing device %v as introducer %v no longer shares any folders with that device", device.DeviceID, device.IntroducedBy)
m.cfg.RemoveDevice(device.DeviceID)
changed = true
} }
} }
devices = append(devices, device)
}
if changed {
cfg := m.cfg.RawCopy()
cfg.Folders = folders
cfg.Devices = devices
m.cfg.Replace(cfg)
} }
return changed return changed
@@ -1310,26 +1279,26 @@ func (m *Model) Request(deviceID protocol.DeviceID, folder, name string, offset
return protocol.ErrInvalid return protocol.ErrInvalid
} }
// Make sure the path is valid and in canonical form
var err error
if name, err = fs.Canonicalize(name); err != nil {
l.Debugf("Request from %s in paused folder %q for invalid filename %s", deviceID, folder, name)
return protocol.ErrInvalid
}
m.fmut.RLock() m.fmut.RLock()
folderCfg := m.folderCfgs[folder]
folderIgnores := m.folderIgnores[folder]
m.fmut.RUnlock()
if folderCfg.Paused { if cfg, ok := m.cfg.Folder(folder); !ok || !cfg.SharedWith(deviceID) {
l.Warnf("Request from %s for file %s in unshared folder %q", deviceID, name, folder)
return protocol.ErrNoSuchFile
} else if cfg.Paused {
l.Debugf("Request from %s for file %s in paused folder %q", deviceID, name, folder) l.Debugf("Request from %s for file %s in paused folder %q", deviceID, name, folder)
return protocol.ErrInvalid return protocol.ErrInvalid
} }
if !m.folderSharedWith(folder, deviceID) { folderCfg := m.folderCfgs[folder]
l.Warnf("Request from %s for file %s in unshared folder %q", deviceID, name, folder) folderIgnores := m.folderIgnores[folder]
return protocol.ErrNoSuchFile
m.fmut.RUnlock()
// Make sure the path is valid and in canonical form
var err error
if name, err = fs.Canonicalize(name); err != nil {
l.Debugf("Request from %s in folder %q for invalid filename %s", deviceID, folder, name)
return protocol.ErrInvalid
} }
if deviceID != protocol.LocalDeviceID { if deviceID != protocol.LocalDeviceID {
@@ -1639,15 +1608,11 @@ func (m *Model) AddConnection(conn connections.Connection, hello protocol.HelloR
} }
func (m *Model) DownloadProgress(device protocol.DeviceID, folder string, updates []protocol.FileDownloadProgressUpdate) { func (m *Model) DownloadProgress(device protocol.DeviceID, folder string, updates []protocol.FileDownloadProgressUpdate) {
if !m.folderSharedWith(folder, device) {
return
}
m.fmut.RLock() m.fmut.RLock()
cfg, ok := m.folderCfgs[folder] cfg, ok := m.folderCfgs[folder]
m.fmut.RUnlock() m.fmut.RUnlock()
if !ok || cfg.Type == config.FolderTypeSendOnly || cfg.DisableTempIndexes { if !ok || cfg.Type == config.FolderTypeSendOnly || cfg.DisableTempIndexes || !cfg.SharedWith(device) {
return return
} }
@@ -2210,15 +2175,7 @@ func (m *Model) generateClusterConfig(device protocol.DeviceID) protocol.Cluster
defer m.fmut.RUnlock() defer m.fmut.RUnlock()
for _, folderCfg := range m.cfg.FolderList() { for _, folderCfg := range m.cfg.FolderList() {
isShared := false if !folderCfg.SharedWith(device) {
for _, sharedWith := range folderCfg.Devices {
if sharedWith.DeviceID == device {
isShared = true
break
}
}
if !isShared {
continue continue
} }
@@ -2342,6 +2299,7 @@ func (m *Model) RemoteSequence(folder string) (int64, bool) {
defer m.fmut.RUnlock() defer m.fmut.RUnlock()
fs, ok := m.folderFiles[folder] fs, ok := m.folderFiles[folder]
cfg := m.folderCfgs[folder]
if !ok { if !ok {
// The folder might not exist, since this can be called with a user // The folder might not exist, since this can be called with a user
// specified folder name from the REST interface. // specified folder name from the REST interface.
@@ -2349,8 +2307,8 @@ func (m *Model) RemoteSequence(folder string) (int64, bool) {
} }
var ver int64 var ver int64
for device := range m.folderDevices[folder] { for _, device := range cfg.Devices {
ver += fs.Sequence(device) ver += fs.Sequence(device.DeviceID)
} }
return ver, true return ver, true
@@ -2556,7 +2514,7 @@ func (m *Model) Availability(folder string, file protocol.FileInfo, block protoc
defer m.pmut.RUnlock() defer m.pmut.RUnlock()
fs, ok := m.folderFiles[folder] fs, ok := m.folderFiles[folder]
devices := m.folderDevices[folder] cfg := m.folderCfgs[folder]
m.fmut.RUnlock() m.fmut.RUnlock()
if !ok { if !ok {
@@ -2577,9 +2535,9 @@ next:
} }
} }
for device := range devices { for _, device := range cfg.Devices {
if m.deviceDownloads[device].Has(folder, file.Name, file.Version, int32(block.Offset/int64(file.BlockSize()))) { if m.deviceDownloads[device.DeviceID].Has(folder, file.Name, file.Version, int32(block.Offset/int64(file.BlockSize()))) {
availabilities = append(availabilities, Availability{ID: device, FromTemporary: true}) availabilities = append(availabilities, Availability{ID: device.DeviceID, FromTemporary: true})
} }
} }
@@ -2641,7 +2599,7 @@ func (m *Model) CommitConfiguration(from, to config.Configuration) bool {
// This folder exists on both sides. Settings might have changed. // This folder exists on both sides. Settings might have changed.
// Check if anything differs that requires a restart. // Check if anything differs that requires a restart.
if !reflect.DeepEqual(fromCfg.RequiresRestartOnly(), toCfg.RequiresRestartOnly()) { if !reflect.DeepEqual(fromCfg.RequiresRestartOnly(), toCfg.RequiresRestartOnly()) {
m.RestartFolder(toCfg) m.RestartFolder(fromCfg, toCfg)
} }
// Emit the folder pause/resume event // Emit the folder pause/resume event
@@ -2726,7 +2684,7 @@ func (m *Model) checkDeviceFolderConnectedLocked(device protocol.DeviceID, folde
return errors.New("device is not connected") return errors.New("device is not connected")
} }
if !m.folderDevices.has(device, folder) { if cfg, ok := m.cfg.Folder(folder); !ok || !cfg.SharedWith(device) {
return errors.New("folder is not shared with device") return errors.New("folder is not shared with device")
} }
return nil return nil
@@ -2882,13 +2840,3 @@ func (s folderDeviceSet) hasDevice(dev protocol.DeviceID) bool {
} }
return false return false
} }
// sortedDevices returns the list of devices for a given folder, sorted
func (s folderDeviceSet) sortedDevices(folder string) []protocol.DeviceID {
devs := make([]protocol.DeviceID, 0, len(s[folder]))
for dev := range s[folder] {
devs = append(devs, dev)
}
sort.Sort(protocol.DeviceIDs(devs))
return devs
}

View File

@@ -1084,7 +1084,7 @@ func TestAutoAcceptRejected(t *testing.T) {
for i := range tcfg.Devices { for i := range tcfg.Devices {
tcfg.Devices[i].AutoAcceptFolders = false tcfg.Devices[i].AutoAcceptFolders = false
} }
wcfg, m := newState(tcfg) _, m := newState(tcfg)
id := srand.String(8) id := srand.String(8)
defer os.RemoveAll(filepath.Join("testdata", id)) defer os.RemoveAll(filepath.Join("testdata", id))
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
@@ -1096,7 +1096,7 @@ func TestAutoAcceptRejected(t *testing.T) {
}, },
}) })
if _, ok := wcfg.Folder(id); ok || m.folderSharedWith(id, device1) { if cfg, ok := m.cfg.Folder(id); ok && cfg.SharedWith(device1) {
t.Error("unexpected shared", id) t.Error("unexpected shared", id)
} }
} }
@@ -1114,7 +1114,7 @@ func TestAutoAcceptNewFolder(t *testing.T) {
}, },
}, },
}) })
if _, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
t.Error("expected shared", id) t.Error("expected shared", id)
} }
} }
@@ -1138,10 +1138,10 @@ func TestAutoAcceptMultipleFolders(t *testing.T) {
}, },
}, },
}) })
if _, ok := wcfg.Folder(id1); !ok || !m.folderSharedWith(id1, device1) { if fcfg, ok := wcfg.Folder(id1); !ok || !fcfg.SharedWith(device1) {
t.Error("expected shared", id1) t.Error("expected shared", id1)
} }
if _, ok := wcfg.Folder(id2); !ok || !m.folderSharedWith(id2, device1) { if fcfg, ok := wcfg.Folder(id2); !ok || !fcfg.SharedWith(device1) {
t.Error("expected shared", id2) t.Error("expected shared", id2)
} }
} }
@@ -1161,7 +1161,7 @@ func TestAutoAcceptExistingFolder(t *testing.T) {
}, },
} }
wcfg, m := newState(tcfg) wcfg, m := newState(tcfg)
if _, ok := wcfg.Folder(id); !ok || m.folderSharedWith(id, device1) { if fcfg, ok := wcfg.Folder(id); !ok || fcfg.SharedWith(device1) {
t.Error("missing folder, or shared", id) t.Error("missing folder, or shared", id)
} }
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
@@ -1173,7 +1173,7 @@ func TestAutoAcceptExistingFolder(t *testing.T) {
}, },
}) })
if fcfg, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) || fcfg.Path != filepath.Join("testdata", idOther) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) || fcfg.Path != filepath.Join("testdata", idOther) {
t.Error("missing folder, or unshared, or path changed", id) t.Error("missing folder, or unshared, or path changed", id)
} }
} }
@@ -1193,7 +1193,7 @@ func TestAutoAcceptNewAndExistingFolder(t *testing.T) {
}, },
} }
wcfg, m := newState(tcfg) wcfg, m := newState(tcfg)
if _, ok := wcfg.Folder(id1); !ok || m.folderSharedWith(id1, device1) { if fcfg, ok := wcfg.Folder(id1); !ok || fcfg.SharedWith(device1) {
t.Error("missing folder, or shared", id1) t.Error("missing folder, or shared", id1)
} }
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
@@ -1210,7 +1210,7 @@ func TestAutoAcceptNewAndExistingFolder(t *testing.T) {
}) })
for i, id := range []string{id1, id2} { for i, id := range []string{id1, id2} {
if _, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
t.Error("missing folder, or unshared", i, id) t.Error("missing folder, or unshared", i, id)
} }
} }
@@ -1233,7 +1233,7 @@ func TestAutoAcceptAlreadyShared(t *testing.T) {
}, },
} }
wcfg, m := newState(tcfg) wcfg, m := newState(tcfg)
if _, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
t.Error("missing folder, or not shared", id) t.Error("missing folder, or not shared", id)
} }
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
@@ -1245,7 +1245,7 @@ func TestAutoAcceptAlreadyShared(t *testing.T) {
}, },
}) })
if _, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
t.Error("missing folder, or not shared", id) t.Error("missing folder, or not shared", id)
} }
} }
@@ -1266,7 +1266,7 @@ func TestAutoAcceptNameConflict(t *testing.T) {
}, },
}, },
}) })
if _, ok := wcfg.Folder(id); ok || m.folderSharedWith(id, device1) { if fcfg, ok := wcfg.Folder(id); ok && fcfg.SharedWith(device1) {
t.Error("unexpected folder", id) t.Error("unexpected folder", id)
} }
} }
@@ -1286,7 +1286,7 @@ func TestAutoAcceptPrefersLabel(t *testing.T) {
}, },
}, },
}) })
if fcfg, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) || !strings.HasSuffix(fcfg.Path, label) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) || !strings.HasSuffix(fcfg.Path, label) {
t.Error("expected shared, or wrong path", id, label, fcfg.Path) t.Error("expected shared, or wrong path", id, label, fcfg.Path)
} }
} }
@@ -1307,7 +1307,7 @@ func TestAutoAcceptFallsBackToID(t *testing.T) {
}, },
}, },
}) })
if fcfg, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) || !strings.HasSuffix(fcfg.Path, id) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) || !strings.HasSuffix(fcfg.Path, id) {
t.Error("expected shared, or wrong path", id, label, fcfg.Path) t.Error("expected shared, or wrong path", id, label, fcfg.Path)
} }
} }
@@ -1330,8 +1330,8 @@ func TestAutoAcceptPausedWhenFolderConfigChanged(t *testing.T) {
}) })
tcfg.Folders = []config.FolderConfiguration{fcfg} tcfg.Folders = []config.FolderConfiguration{fcfg}
wcfg, m := newState(tcfg) wcfg, m := newState(tcfg)
if _, ok := wcfg.Folder(id); !ok || m.folderSharedWith(id, device1) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
t.Error("missing folder, or shared", id) t.Error("missing folder, or not shared", id)
} }
if _, ok := m.folderRunners[id]; ok { if _, ok := m.folderRunners[id]; ok {
t.Fatal("folder running?") t.Fatal("folder running?")
@@ -1360,7 +1360,7 @@ func TestAutoAcceptPausedWhenFolderConfigChanged(t *testing.T) {
t.Error("device missing") t.Error("device missing")
} }
if _, ok := m.folderDevices[id]; ok { if _, ok := m.folderRunners[id]; ok {
t.Error("folder started") t.Error("folder started")
} }
} }
@@ -1386,8 +1386,8 @@ func TestAutoAcceptPausedWhenFolderConfigNotChanged(t *testing.T) {
}, fcfg.Devices...) // Need to ensure this device order to avoid folder restart. }, fcfg.Devices...) // Need to ensure this device order to avoid folder restart.
tcfg.Folders = []config.FolderConfiguration{fcfg} tcfg.Folders = []config.FolderConfiguration{fcfg}
wcfg, m := newState(tcfg) wcfg, m := newState(tcfg)
if _, ok := wcfg.Folder(id); !ok || m.folderSharedWith(id, device1) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
t.Error("missing folder, or shared", id) t.Error("missing folder, or not shared", id)
} }
if _, ok := m.folderRunners[id]; ok { if _, ok := m.folderRunners[id]; ok {
t.Fatal("folder running?") t.Fatal("folder running?")
@@ -1416,7 +1416,7 @@ func TestAutoAcceptPausedWhenFolderConfigNotChanged(t *testing.T) {
t.Error("device missing") t.Error("device missing")
} }
if _, ok := m.folderDevices[id]; ok { if _, ok := m.folderRunners[id]; ok {
t.Error("folder started") t.Error("folder started")
} }
} }
@@ -1536,7 +1536,7 @@ func TestIgnores(t *testing.T) {
pausedDefaultFolderConfig := defaultFolderConfig pausedDefaultFolderConfig := defaultFolderConfig
pausedDefaultFolderConfig.Paused = true pausedDefaultFolderConfig.Paused = true
m.RestartFolder(pausedDefaultFolderConfig) m.RestartFolder(defaultFolderConfig, pausedDefaultFolderConfig)
// Here folder initialization is not an issue as a paused folder isn't // Here folder initialization is not an issue as a paused folder isn't
// added to the model and thus there is no initial scan happening. // added to the model and thus there is no initial scan happening.
@@ -2623,10 +2623,10 @@ func TestSharedWithClearedOnDisconnect(t *testing.T) {
}, },
}) })
if !m.folderSharedWith("default", device1) { if fcfg, ok := m.cfg.Folder("default"); !ok || !fcfg.SharedWith(device1) {
t.Error("not shared with device1") t.Error("not shared with device1")
} }
if !m.folderSharedWith("default", device2) { if fcfg, ok := m.cfg.Folder("default"); !ok || !fcfg.SharedWith(device2) {
t.Error("not shared with device2") t.Error("not shared with device2")
} }
@@ -2643,12 +2643,21 @@ func TestSharedWithClearedOnDisconnect(t *testing.T) {
time.Sleep(100 * time.Millisecond) // Committer notification happens in a separate routine time.Sleep(100 * time.Millisecond) // Committer notification happens in a separate routine
if !m.folderSharedWith("default", device1) { fcfg, ok := m.cfg.Folder("default")
if !ok {
t.Fatal("default folder missing")
}
if !fcfg.SharedWith(device1) {
t.Error("not shared with device1") t.Error("not shared with device1")
} }
if m.folderSharedWith("default", device2) { // checks m.deviceFolders if fcfg.SharedWith(device2) {
t.Error("shared with device2") t.Error("shared with device2")
} }
for _, dev := range fcfg.Devices {
if dev.DeviceID == device2 {
t.Error("still there")
}
}
if !conn2.Closed() { if !conn2.Closed() {
t.Error("connection not closed") t.Error("connection not closed")
@@ -2658,17 +2667,6 @@ func TestSharedWithClearedOnDisconnect(t *testing.T) {
t.Error("device still in config") t.Error("device still in config")
} }
fdevs, ok := m.folderDevices["default"]
if !ok {
t.Error("folder missing?")
}
for id := range fdevs {
if id == device2 {
t.Error("still there")
}
}
if _, ok := m.conn[device2]; !ok { if _, ok := m.conn[device2]; !ok {
t.Error("conn missing early") t.Error("conn missing early")
} }
@@ -3250,7 +3248,7 @@ func TestIssue4475(t *testing.T) {
conn := addFakeConn(m, device1) conn := addFakeConn(m, device1)
conn.folder = "default" conn.folder = "default"
if !m.folderSharedWith("default", device1) { if fcfg, ok := m.cfg.Folder("default"); !ok || !fcfg.SharedWith(device1) {
t.Fatal("not shared with device1") t.Fatal("not shared with device1")
} }