gui, lib/config, lib/model: Support auto-accepting folders (fixes #2299)
Also introduces a new Waiter interface for config changes and segments the configuration GUI. GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4551
This commit is contained in:
committed by
Jakob Borg
parent
c005b8dcb0
commit
445c4edeca
@@ -33,6 +33,7 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/stats"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
"github.com/syncthing/syncthing/lib/upgrade"
|
||||
"github.com/syncthing/syncthing/lib/util"
|
||||
"github.com/syncthing/syncthing/lib/versioner"
|
||||
"github.com/syncthing/syncthing/lib/weakhash"
|
||||
"github.com/thejerf/suture"
|
||||
@@ -892,6 +893,8 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
|
||||
}
|
||||
|
||||
dbLocation := filepath.Dir(m.db.Location())
|
||||
changed := false
|
||||
deviceCfg := m.cfg.Devices()[deviceID]
|
||||
|
||||
// See issue #3802 - in short, we can't send modern symlink entries to older
|
||||
// clients.
|
||||
@@ -901,6 +904,13 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
|
||||
dropSymlinks = true
|
||||
}
|
||||
|
||||
// Needs to happen outside of the fmut, as can cause CommitConfiguration
|
||||
if deviceCfg.AutoAcceptFolders {
|
||||
for _, folder := range cm.Folders {
|
||||
changed = m.handleAutoAccepts(deviceCfg, folder) || changed
|
||||
}
|
||||
}
|
||||
|
||||
m.fmut.Lock()
|
||||
var paused []string
|
||||
for _, folder := range cm.Folders {
|
||||
@@ -927,6 +937,7 @@ 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)
|
||||
continue
|
||||
}
|
||||
|
||||
if !folder.DisableTempIndexes {
|
||||
tempIndexFolders = append(tempIndexFolders, folder.ID)
|
||||
}
|
||||
@@ -1021,8 +1032,7 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
|
||||
}
|
||||
}
|
||||
|
||||
var changed = false
|
||||
if deviceCfg := m.cfg.Devices()[deviceID]; deviceCfg.Introducer {
|
||||
if deviceCfg.Introducer {
|
||||
foldersDevices, introduced := m.handleIntroductions(deviceCfg, cm)
|
||||
if introduced {
|
||||
changed = true
|
||||
@@ -1063,6 +1073,11 @@ func (m *Model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm
|
||||
// the folder.
|
||||
nextDevice:
|
||||
for _, device := range folder.Devices {
|
||||
// No need to share with self.
|
||||
if device.ID == m.id {
|
||||
continue
|
||||
}
|
||||
|
||||
foldersDevices.set(device.ID, folder.ID)
|
||||
|
||||
if _, ok := m.cfg.Devices()[device.ID]; !ok {
|
||||
@@ -1081,7 +1096,8 @@ func (m *Model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm
|
||||
|
||||
// We don't yet share this folder with this device. Add the device
|
||||
// to sharing list of the folder.
|
||||
m.introduceDeviceToFolder(device, folder, introducerCfg)
|
||||
l.Infof("Sharing folder %s with %v (vouched for by introducer %v)", folder.Description(), device.ID, introducerCfg.DeviceID)
|
||||
m.shareFolderWithDeviceLocked(device.ID, folder.ID, introducerCfg.DeviceID)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
@@ -1089,7 +1105,7 @@ func (m *Model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm
|
||||
return foldersDevices, changed
|
||||
}
|
||||
|
||||
// handleIntroductions 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 {
|
||||
changed := false
|
||||
foldersIntroducedByOthers := make(folderDeviceSet)
|
||||
@@ -1142,6 +1158,51 @@ func (m *Model) handleDeintroductions(introducerCfg config.DeviceConfiguration,
|
||||
return changed
|
||||
}
|
||||
|
||||
// handleAutoAccepts handles adding and sharing folders for devices that have
|
||||
// AutoAcceptFolders set to true.
|
||||
func (m *Model) handleAutoAccepts(deviceCfg config.DeviceConfiguration, folder protocol.Folder) bool {
|
||||
if _, ok := m.cfg.Folder(folder.ID); !ok {
|
||||
defaultPath := m.cfg.Options().DefaultFolderPath
|
||||
defaultPathFs := fs.NewFilesystem(fs.FilesystemTypeBasic, defaultPath)
|
||||
for _, path := range []string{folder.Label, folder.ID} {
|
||||
if _, err := defaultPathFs.Lstat(path); !fs.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
|
||||
fcfg := config.NewFolderConfiguration(m.id, folder.ID, folder.Label, fs.FilesystemTypeBasic, filepath.Join(defaultPath, path))
|
||||
|
||||
// Need to wait for the waiter, as this calls CommitConfiguration,
|
||||
// which sets up the folder and as we return from this call,
|
||||
// ClusterConfig starts poking at m.folderFiles and other things
|
||||
// that might not exist until the config is committed.
|
||||
w, _ := m.cfg.SetFolder(fcfg)
|
||||
w.Wait()
|
||||
|
||||
// This needs to happen under a lock.
|
||||
m.fmut.Lock()
|
||||
w = m.shareFolderWithDeviceLocked(deviceCfg.DeviceID, folder.ID, protocol.DeviceID{})
|
||||
m.fmut.Unlock()
|
||||
w.Wait()
|
||||
l.Infof("Auto-accepted %s folder %s at path %s", deviceCfg.DeviceID, folder.Description(), fcfg.Path)
|
||||
return true
|
||||
}
|
||||
l.Infof("Failed to auto-accept folder %s from %s due to path conflict", folder.Description(), deviceCfg.DeviceID)
|
||||
return false
|
||||
}
|
||||
|
||||
// Folder already exists.
|
||||
if !m.folderSharedWith(folder.ID, deviceCfg.DeviceID) {
|
||||
m.fmut.Lock()
|
||||
w := m.shareFolderWithDeviceLocked(deviceCfg.DeviceID, folder.ID, protocol.DeviceID{})
|
||||
m.fmut.Unlock()
|
||||
w.Wait()
|
||||
l.Infof("Shared %s with %s due to auto-accept", folder.ID, deviceCfg.DeviceID)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *Model) introduceDevice(device protocol.Device, introducerCfg config.DeviceConfiguration) {
|
||||
addresses := []string{"dynamic"}
|
||||
for _, addr := range device.Addresses {
|
||||
@@ -1170,18 +1231,17 @@ func (m *Model) introduceDevice(device protocol.Device, introducerCfg config.Dev
|
||||
m.cfg.SetDevice(newDeviceCfg)
|
||||
}
|
||||
|
||||
func (m *Model) introduceDeviceToFolder(device protocol.Device, folder protocol.Folder, introducerCfg config.DeviceConfiguration) {
|
||||
l.Infof("Sharing folder %s with %v (vouched for by introducer %v)", folder.Description(), device.ID, introducerCfg.DeviceID)
|
||||
func (m *Model) shareFolderWithDeviceLocked(deviceID protocol.DeviceID, folder string, introducer protocol.DeviceID) config.Waiter {
|
||||
m.deviceFolders[deviceID] = append(m.deviceFolders[deviceID], folder)
|
||||
m.folderDevices.set(deviceID, folder)
|
||||
|
||||
m.deviceFolders[device.ID] = append(m.deviceFolders[device.ID], folder.ID)
|
||||
m.folderDevices.set(device.ID, folder.ID)
|
||||
|
||||
folderCfg := m.cfg.Folders()[folder.ID]
|
||||
folderCfg := m.cfg.Folders()[folder]
|
||||
folderCfg.Devices = append(folderCfg.Devices, config.FolderDeviceConfiguration{
|
||||
DeviceID: device.ID,
|
||||
IntroducedBy: introducerCfg.DeviceID,
|
||||
DeviceID: deviceID,
|
||||
IntroducedBy: introducer,
|
||||
})
|
||||
m.cfg.SetFolder(folderCfg)
|
||||
w, _ := m.cfg.SetFolder(folderCfg)
|
||||
return w
|
||||
}
|
||||
|
||||
// Closed is called when a connection has been closed
|
||||
@@ -1486,7 +1546,7 @@ func (m *Model) AddConnection(conn connections.Connection, hello protocol.HelloR
|
||||
conn.ClusterConfig(cm)
|
||||
|
||||
device, ok := m.cfg.Devices()[deviceID]
|
||||
if ok && (device.Name == "" || m.cfg.Options().OverwriteRemoteDevNames) {
|
||||
if ok && (device.Name == "" || m.cfg.Options().OverwriteRemoteDevNames) && hello.DeviceName != "" {
|
||||
device.Name = hello.DeviceName
|
||||
m.cfg.SetDevice(device)
|
||||
m.cfg.Save()
|
||||
@@ -2366,10 +2426,10 @@ func (m *Model) CommitConfiguration(from, to config.Configuration) bool {
|
||||
if _, ok := fromFolders[folderID]; !ok {
|
||||
// A folder was added.
|
||||
if cfg.Paused {
|
||||
l.Infoln(m, "Paused folder", cfg.Description())
|
||||
l.Infoln("Paused folder", cfg.Description())
|
||||
cfg.CreateRoot()
|
||||
} else {
|
||||
l.Infoln(m, "Adding folder", cfg.Description())
|
||||
l.Infoln("Adding folder", cfg.Description())
|
||||
m.AddFolder(cfg)
|
||||
m.StartFolder(folderID)
|
||||
}
|
||||
@@ -2388,8 +2448,12 @@ func (m *Model) CommitConfiguration(from, to config.Configuration) bool {
|
||||
// Check if anything differs, apart from the label.
|
||||
toCfgCopy := toCfg
|
||||
fromCfgCopy := fromCfg
|
||||
fromCfgCopy.Label = ""
|
||||
toCfgCopy.Label = ""
|
||||
util.CopyMatchingTag(&toCfgCopy, &fromCfgCopy, "restart", func(v string) bool {
|
||||
if len(v) > 0 && v != "false" {
|
||||
panic(fmt.Sprintf(`unexpected struct value: %s. expected untagged or "false"`, v))
|
||||
}
|
||||
return v == "false"
|
||||
})
|
||||
|
||||
if !reflect.DeepEqual(fromCfgCopy, toCfgCopy) {
|
||||
m.RestartFolder(toCfg)
|
||||
@@ -2432,17 +2496,15 @@ func (m *Model) CommitConfiguration(from, to config.Configuration) bool {
|
||||
|
||||
// Some options don't require restart as those components handle it fine
|
||||
// by themselves.
|
||||
from.Options.URAccepted = to.Options.URAccepted
|
||||
from.Options.URSeen = to.Options.URSeen
|
||||
from.Options.URUniqueID = to.Options.URUniqueID
|
||||
from.Options.ListenAddresses = to.Options.ListenAddresses
|
||||
from.Options.RelaysEnabled = to.Options.RelaysEnabled
|
||||
from.Options.UnackedNotificationIDs = to.Options.UnackedNotificationIDs
|
||||
from.Options.MaxRecvKbps = to.Options.MaxRecvKbps
|
||||
from.Options.MaxSendKbps = to.Options.MaxSendKbps
|
||||
from.Options.LimitBandwidthInLan = to.Options.LimitBandwidthInLan
|
||||
from.Options.StunKeepaliveS = to.Options.StunKeepaliveS
|
||||
from.Options.StunServers = to.Options.StunServers
|
||||
|
||||
// Copy fields that do not have the field set to true
|
||||
util.CopyMatchingTag(&from.Options, &to.Options, "restart", func(v string) bool {
|
||||
if len(v) > 0 && v != "true" {
|
||||
panic(fmt.Sprintf(`unexpected struct value: %s. expected untagged or "true"`, v))
|
||||
}
|
||||
return v != "true"
|
||||
})
|
||||
|
||||
// All of the other generic options require restart. Or at least they may;
|
||||
// removing this check requires going through those options carefully and
|
||||
// making sure there are individual services that handle them correctly.
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -36,13 +37,14 @@ var device1, device2 protocol.DeviceID
|
||||
var defaultConfig *config.Wrapper
|
||||
var defaultFolderConfig config.FolderConfiguration
|
||||
var defaultFs fs.Filesystem
|
||||
var defaultAutoAcceptCfg config.Configuration
|
||||
|
||||
func init() {
|
||||
device1, _ = protocol.DeviceIDFromString("AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR")
|
||||
device2, _ = protocol.DeviceIDFromString("GYRZZQB-IRNPV4Z-T7TC52W-EQYJ3TT-FDQW6MW-DFLMU42-SSSU6EM-FBK2VAY")
|
||||
defaultFs = fs.NewFilesystem(fs.FilesystemTypeBasic, "testdata")
|
||||
|
||||
defaultFolderConfig = config.NewFolderConfiguration("default", fs.FilesystemTypeBasic, "testdata")
|
||||
defaultFolderConfig = config.NewFolderConfiguration(protocol.LocalDeviceID, "default", "default", fs.FilesystemTypeBasic, "testdata")
|
||||
defaultFolderConfig.Devices = []config.FolderDeviceConfiguration{{DeviceID: device1}}
|
||||
_defaultConfig := config.Configuration{
|
||||
Folders: []config.FolderConfiguration{defaultFolderConfig},
|
||||
@@ -53,6 +55,17 @@ func init() {
|
||||
},
|
||||
}
|
||||
defaultConfig = config.Wrap("/tmp/test", _defaultConfig)
|
||||
defaultAutoAcceptCfg = config.Configuration{
|
||||
Devices: []config.DeviceConfiguration{
|
||||
{
|
||||
DeviceID: device1,
|
||||
AutoAcceptFolders: true,
|
||||
},
|
||||
},
|
||||
Options: config.OptionsConfiguration{
|
||||
DefaultFolderPath: "testdata",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var testDataExpected = map[string]protocol.FileInfo{
|
||||
@@ -87,6 +100,20 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func newState(cfg config.Configuration) (*config.Wrapper, *Model) {
|
||||
db := db.OpenMemory()
|
||||
|
||||
wcfg := config.Wrap("/tmp/test", cfg)
|
||||
|
||||
m := NewModel(wcfg, protocol.LocalDeviceID, "syncthing", "dev", db, nil)
|
||||
for _, folder := range cfg.Folders {
|
||||
m.AddFolder(folder)
|
||||
}
|
||||
m.ServeBackground()
|
||||
m.AddConnection(&fakeConnection{id: device1}, protocol.HelloResult{})
|
||||
return wcfg, m
|
||||
}
|
||||
|
||||
func TestRequest(t *testing.T) {
|
||||
db := db.OpenMemory()
|
||||
|
||||
@@ -609,20 +636,6 @@ func TestIntroducer(t *testing.T) {
|
||||
return false
|
||||
}
|
||||
|
||||
newState := func(cfg config.Configuration) (*config.Wrapper, *Model) {
|
||||
db := db.OpenMemory()
|
||||
|
||||
wcfg := config.Wrap("/tmp/test", cfg)
|
||||
|
||||
m := NewModel(wcfg, protocol.LocalDeviceID, "syncthing", "dev", db, nil)
|
||||
for _, folder := range cfg.Folders {
|
||||
m.AddFolder(folder)
|
||||
}
|
||||
m.ServeBackground()
|
||||
m.AddConnection(&fakeConnection{id: device1}, protocol.HelloResult{})
|
||||
return wcfg, m
|
||||
}
|
||||
|
||||
wcfg, m := newState(config.Configuration{
|
||||
Devices: []config.DeviceConfiguration{
|
||||
{
|
||||
@@ -970,6 +983,237 @@ func TestIntroducer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoAcceptRejected(t *testing.T) {
|
||||
// Nothing happens if AutoAcceptFolders not set
|
||||
tcfg := defaultAutoAcceptCfg.Copy()
|
||||
tcfg.Devices[0].AutoAcceptFolders = false
|
||||
wcfg, m := newState(tcfg)
|
||||
id := srand.String(8)
|
||||
defer os.RemoveAll(filepath.Join("testdata", id))
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: id,
|
||||
Label: id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if _, ok := wcfg.Folder(id); ok || m.folderSharedWith(id, device1) {
|
||||
t.Error("unexpected shared", id)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoAcceptNewFolder(t *testing.T) {
|
||||
// New folder
|
||||
wcfg, m := newState(defaultAutoAcceptCfg)
|
||||
id := srand.String(8)
|
||||
defer os.RemoveAll(filepath.Join("testdata", id))
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: id,
|
||||
Label: id,
|
||||
},
|
||||
},
|
||||
})
|
||||
if _, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) {
|
||||
t.Error("expected shared", id)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoAcceptMultipleFolders(t *testing.T) {
|
||||
// Multiple new folders
|
||||
wcfg, m := newState(defaultAutoAcceptCfg)
|
||||
id1 := srand.String(8)
|
||||
defer os.RemoveAll(filepath.Join("testdata", id1))
|
||||
id2 := srand.String(8)
|
||||
defer os.RemoveAll(filepath.Join("testdata", id2))
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: id1,
|
||||
Label: id1,
|
||||
},
|
||||
{
|
||||
ID: id2,
|
||||
Label: id2,
|
||||
},
|
||||
},
|
||||
})
|
||||
if _, ok := wcfg.Folder(id1); !ok || !m.folderSharedWith(id1, device1) {
|
||||
t.Error("expected shared", id1)
|
||||
}
|
||||
if _, ok := wcfg.Folder(id2); !ok || !m.folderSharedWith(id2, device1) {
|
||||
t.Error("expected shared", id2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoAcceptExistingFolder(t *testing.T) {
|
||||
// Existing folder
|
||||
id := srand.String(8)
|
||||
idOther := srand.String(8) // To check that path does not get changed.
|
||||
defer os.RemoveAll(filepath.Join("testdata", id))
|
||||
|
||||
tcfg := defaultAutoAcceptCfg.Copy()
|
||||
tcfg.Folders = []config.FolderConfiguration{
|
||||
{
|
||||
ID: id,
|
||||
Path: filepath.Join("testdata", idOther), // To check that path does not get changed.
|
||||
},
|
||||
}
|
||||
wcfg, m := newState(tcfg)
|
||||
if _, ok := wcfg.Folder(id); !ok || m.folderSharedWith(id, device1) {
|
||||
t.Error("missing folder, or shared", id)
|
||||
}
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: id,
|
||||
Label: id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if fcfg, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) || fcfg.Path != filepath.Join("testdata", idOther) {
|
||||
t.Error("missing folder, or unshared, or path changed", id)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoAcceptNewAndExistingFolder(t *testing.T) {
|
||||
// New and existing folder
|
||||
id1 := srand.String(8)
|
||||
defer os.RemoveAll(filepath.Join("testdata", id1))
|
||||
id2 := srand.String(8)
|
||||
defer os.RemoveAll(filepath.Join("testdata", id2))
|
||||
|
||||
tcfg := defaultAutoAcceptCfg.Copy()
|
||||
tcfg.Folders = []config.FolderConfiguration{
|
||||
{
|
||||
ID: id1,
|
||||
Path: filepath.Join("testdata", id1), // from previous test case, to verify that path doesn't get changed.
|
||||
},
|
||||
}
|
||||
wcfg, m := newState(tcfg)
|
||||
if _, ok := wcfg.Folder(id1); !ok || m.folderSharedWith(id1, device1) {
|
||||
t.Error("missing folder, or shared", id1)
|
||||
}
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: id1,
|
||||
Label: id1,
|
||||
},
|
||||
{
|
||||
ID: id2,
|
||||
Label: id2,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
for i, id := range []string{id1, id2} {
|
||||
if _, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) {
|
||||
t.Error("missing folder, or unshared", i, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoAcceptAlreadyShared(t *testing.T) {
|
||||
// Already shared
|
||||
id := srand.String(8)
|
||||
defer os.RemoveAll(filepath.Join("testdata", id))
|
||||
tcfg := defaultAutoAcceptCfg.Copy()
|
||||
tcfg.Folders = []config.FolderConfiguration{
|
||||
{
|
||||
ID: id,
|
||||
Path: filepath.Join("testdata", id),
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
{
|
||||
DeviceID: device1,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
wcfg, m := newState(tcfg)
|
||||
if _, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) {
|
||||
t.Error("missing folder, or not shared", id)
|
||||
}
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: id,
|
||||
Label: id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if _, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) {
|
||||
t.Error("missing folder, or not shared", id)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoAcceptNameConflict(t *testing.T) {
|
||||
id := srand.String(8)
|
||||
label := srand.String(8)
|
||||
os.MkdirAll(filepath.Join("testdata", id), 0777)
|
||||
os.MkdirAll(filepath.Join("testdata", label), 0777)
|
||||
defer os.RemoveAll(filepath.Join("testdata", id))
|
||||
defer os.RemoveAll(filepath.Join("testdata", label))
|
||||
wcfg, m := newState(defaultAutoAcceptCfg)
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: id,
|
||||
Label: label,
|
||||
},
|
||||
},
|
||||
})
|
||||
if _, ok := wcfg.Folder(id); ok || m.folderSharedWith(id, device1) {
|
||||
t.Error("unexpected folder", id)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoAcceptPrefersLabel(t *testing.T) {
|
||||
// Prefers label, falls back to ID.
|
||||
wcfg, m := newState(defaultAutoAcceptCfg)
|
||||
id := srand.String(8)
|
||||
label := srand.String(8)
|
||||
defer os.RemoveAll(filepath.Join("testdata", id))
|
||||
defer os.RemoveAll(filepath.Join("testdata", label))
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: id,
|
||||
Label: label,
|
||||
},
|
||||
},
|
||||
})
|
||||
if fcfg, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) || !strings.HasSuffix(fcfg.Path, label) {
|
||||
t.Error("expected shared, or wrong path", id, label, fcfg.Path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoAcceptFallsBackToID(t *testing.T) {
|
||||
// Prefers label, falls back to ID.
|
||||
wcfg, m := newState(defaultAutoAcceptCfg)
|
||||
id := srand.String(8)
|
||||
label := srand.String(8)
|
||||
os.MkdirAll(filepath.Join("testdata", label), 0777)
|
||||
defer os.RemoveAll(filepath.Join("testdata", label))
|
||||
defer os.RemoveAll(filepath.Join("testdata", id))
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: id,
|
||||
Label: label,
|
||||
},
|
||||
},
|
||||
})
|
||||
if fcfg, ok := wcfg.Folder(id); !ok || !m.folderSharedWith(id, device1) || !strings.HasSuffix(fcfg.Path, id) {
|
||||
t.Error("expected shared, or wrong path", id, label, fcfg.Path)
|
||||
}
|
||||
}
|
||||
|
||||
func changeIgnores(t *testing.T, m *Model, expected []string) {
|
||||
arrEqual := func(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
@@ -1920,7 +2164,9 @@ func TestIssue4357(t *testing.T) {
|
||||
defer m.Stop()
|
||||
|
||||
// Force the model to wire itself and add the folders
|
||||
if err := wrapper.ReplaceBlocking(cfg); err != nil {
|
||||
p, err := wrapper.Replace(cfg)
|
||||
p.Wait()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -1931,7 +2177,9 @@ func TestIssue4357(t *testing.T) {
|
||||
newCfg := wrapper.RawCopy()
|
||||
newCfg.Folders[0].Paused = true
|
||||
|
||||
if err := wrapper.ReplaceBlocking(newCfg); err != nil {
|
||||
p, err = wrapper.Replace(newCfg)
|
||||
p.Wait()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -1943,7 +2191,9 @@ func TestIssue4357(t *testing.T) {
|
||||
t.Error("should still have folder in config")
|
||||
}
|
||||
|
||||
if err := wrapper.ReplaceBlocking(config.Configuration{}); err != nil {
|
||||
p, err = wrapper.Replace(config.Configuration{})
|
||||
p.Wait()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -1952,7 +2202,9 @@ func TestIssue4357(t *testing.T) {
|
||||
}
|
||||
|
||||
// Add the folder back, should be running
|
||||
if err := wrapper.ReplaceBlocking(cfg); err != nil {
|
||||
p, err = wrapper.Replace(cfg)
|
||||
p.Wait()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -1964,7 +2216,9 @@ func TestIssue4357(t *testing.T) {
|
||||
}
|
||||
|
||||
// Should not panic when removing a running folder.
|
||||
if err := wrapper.ReplaceBlocking(config.Configuration{}); err != nil {
|
||||
p, err = wrapper.Replace(config.Configuration{})
|
||||
p.Wait()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -2066,7 +2320,7 @@ func TestIssue2782(t *testing.T) {
|
||||
|
||||
db := db.OpenMemory()
|
||||
m := NewModel(defaultConfig, protocol.LocalDeviceID, "syncthing", "dev", db, nil)
|
||||
m.AddFolder(config.NewFolderConfiguration("default", fs.FilesystemTypeBasic, "~/"+testName+"/synclink/"))
|
||||
m.AddFolder(config.NewFolderConfiguration(protocol.LocalDeviceID, "default", "default", fs.FilesystemTypeBasic, "~/"+testName+"/synclink/"))
|
||||
m.StartFolder("default")
|
||||
m.ServeBackground()
|
||||
defer m.Stop()
|
||||
@@ -2111,7 +2365,7 @@ func TestIndexesForUnknownDevicesDropped(t *testing.T) {
|
||||
func TestSharedWithClearedOnDisconnect(t *testing.T) {
|
||||
dbi := db.OpenMemory()
|
||||
|
||||
fcfg := config.NewFolderConfiguration("default", fs.FilesystemTypeBasic, "testdata")
|
||||
fcfg := config.NewFolderConfiguration(protocol.LocalDeviceID, "default", "default", fs.FilesystemTypeBasic, "testdata")
|
||||
fcfg.Devices = []config.FolderDeviceConfiguration{
|
||||
{DeviceID: device1},
|
||||
{DeviceID: device2},
|
||||
@@ -2177,7 +2431,7 @@ func TestSharedWithClearedOnDisconnect(t *testing.T) {
|
||||
cfg = cfg.Copy()
|
||||
cfg.Devices = cfg.Devices[:1]
|
||||
|
||||
if err := wcfg.Replace(cfg); err != nil {
|
||||
if _, err := wcfg.Replace(cfg); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -2350,7 +2604,7 @@ func TestNoRequestsFromPausedDevices(t *testing.T) {
|
||||
|
||||
dbi := db.OpenMemory()
|
||||
|
||||
fcfg := config.NewFolderConfiguration("default", fs.FilesystemTypeBasic, "testdata")
|
||||
fcfg := config.NewFolderConfiguration(protocol.LocalDeviceID, "default", "default", fs.FilesystemTypeBasic, "testdata")
|
||||
fcfg.Devices = []config.FolderDeviceConfiguration{
|
||||
{DeviceID: device1},
|
||||
{DeviceID: device2},
|
||||
|
||||
@@ -216,7 +216,7 @@ func TestRequestVersioningSymlinkAttack(t *testing.T) {
|
||||
panic("Failed to create temporary testing dir")
|
||||
}
|
||||
cfg := defaultConfig.RawCopy()
|
||||
cfg.Folders[0] = config.NewFolderConfiguration("default", fs.FilesystemTypeBasic, tmpFolder)
|
||||
cfg.Folders[0] = config.NewFolderConfiguration(protocol.LocalDeviceID, "default", "default", fs.FilesystemTypeBasic, tmpFolder)
|
||||
cfg.Folders[0].Devices = []config.FolderDeviceConfiguration{
|
||||
{DeviceID: device1},
|
||||
{DeviceID: device2},
|
||||
@@ -292,7 +292,7 @@ func setupModelWithConnection() (*Model, *fakeConnection, string) {
|
||||
panic("Failed to create temporary testing dir")
|
||||
}
|
||||
cfg := defaultConfig.RawCopy()
|
||||
cfg.Folders[0] = config.NewFolderConfiguration("default", fs.FilesystemTypeBasic, tmpFolder)
|
||||
cfg.Folders[0] = config.NewFolderConfiguration(protocol.LocalDeviceID, "default", "default", fs.FilesystemTypeBasic, tmpFolder)
|
||||
cfg.Folders[0].Devices = []config.FolderDeviceConfiguration{
|
||||
{DeviceID: device1},
|
||||
{DeviceID: device2},
|
||||
|
||||
Reference in New Issue
Block a user