diff --git a/lib/model/model.go b/lib/model/model.go index ab043aa7d..879102cde 100644 --- a/lib/model/model.go +++ b/lib/model/model.go @@ -1505,7 +1505,18 @@ func (m *Model) GetIgnores(folder string) ([]string, []string, error) { func (m *Model) SetIgnores(folder string, content []string) error { cfg, ok := m.cfg.Folders()[folder] if !ok { - return fmt.Errorf("Folder %s does not exist", folder) + return fmt.Errorf("folder %s does not exist", cfg.Description()) + } + + err := cfg.CheckPath() + if err == config.ErrPathMissing { + if err = cfg.CreateRoot(); err != nil { + return fmt.Errorf("failed to create folder root: %v", err) + } + err = cfg.CheckPath() + } + if err != nil && err != config.ErrMarkerMissing { + return err } if err := ignore.WriteIgnores(cfg.Filesystem(), ".stignore", content); err != nil { @@ -2629,7 +2640,6 @@ func (m *Model) CommitConfiguration(from, to config.Configuration) bool { // A folder was added. if cfg.Paused { l.Infoln("Paused folder", cfg.Description()) - cfg.CreateRoot() } else { l.Infoln("Adding folder", cfg.Description()) m.AddFolder(cfg) diff --git a/lib/model/model_test.go b/lib/model/model_test.go index 749756a28..01a9889e6 100644 --- a/lib/model/model_test.go +++ b/lib/model/model_test.go @@ -3527,6 +3527,80 @@ func TestPausedFolders(t *testing.T) { } } +func TestIssue4094(t *testing.T) { + db := db.OpenMemory() + // Create a separate wrapper not to pollute other tests. + wrapper, path := createTmpWrapper(config.Configuration{}) + defer os.Remove(path) + m := NewModel(wrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil) + m.ServeBackground() + defer m.Stop() + + // Force the model to wire itself and add the folders + folderPath := "testdata/nonexistent" + defer os.RemoveAll(folderPath) + cfg := defaultCfgWrapper.RawCopy() + fcfg := config.FolderConfiguration{ + ID: "folder1", + Path: folderPath, + Paused: true, + Devices: []config.FolderDeviceConfiguration{ + {DeviceID: device1}, + }, + } + cfg.Folders = []config.FolderConfiguration{fcfg} + p, err := wrapper.Replace(cfg) + if err != nil { + t.Fatal(err) + } + p.Wait() + + if err := m.SetIgnores(fcfg.ID, []string{"foo"}); err != nil { + t.Fatalf("failed setting ignores: %v", err) + } + + if _, err := fcfg.Filesystem().Lstat(".stignore"); err != nil { + t.Fatalf("failed stating .stignore: %v", err) + } +} + +func TestIssue4903(t *testing.T) { + db := db.OpenMemory() + // Create a separate wrapper not to pollute other tests. + wrapper, path := createTmpWrapper(config.Configuration{}) + defer os.Remove(path) + m := NewModel(wrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil) + m.ServeBackground() + defer m.Stop() + + // Force the model to wire itself and add the folders + folderPath := "testdata/nonexistent" + defer os.RemoveAll(folderPath) + cfg := defaultCfgWrapper.RawCopy() + fcfg := config.FolderConfiguration{ + ID: "folder1", + Path: folderPath, + Paused: true, + Devices: []config.FolderDeviceConfiguration{ + {DeviceID: device1}, + }, + } + cfg.Folders = []config.FolderConfiguration{fcfg} + p, err := wrapper.Replace(cfg) + if err != nil { + t.Fatal(err) + } + p.Wait() + + if err := fcfg.CheckPath(); err != config.ErrPathMissing { + t.Fatalf("expected path missing error, got: %v", err) + } + + if _, err := fcfg.Filesystem().Lstat("."); !fs.IsNotExist(err) { + t.Fatalf("Expected missing path error, got: %v", err) + } +} + func addFakeConn(m *Model, dev protocol.DeviceID) *fakeConnection { fc := &fakeConnection{id: dev, model: m} m.AddConnection(fc, protocol.HelloResult{})