Browse Source

lib/model: Check for invalid filenames after ignore patterns

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4607
LGTM: calmh, AudriusButkevicius
Simon Frei 8 years ago
parent
commit
841205dbfe
2 changed files with 86 additions and 8 deletions
  1. 81 0
      lib/model/model_test.go
  2. 5 8
      lib/model/rwfolder.go

+ 81 - 0
lib/model/model_test.go

@@ -26,6 +26,7 @@ import (
 	"github.com/d4l3k/messagediff"
 	"github.com/syncthing/syncthing/lib/config"
 	"github.com/syncthing/syncthing/lib/db"
+	"github.com/syncthing/syncthing/lib/events"
 	"github.com/syncthing/syncthing/lib/fs"
 	"github.com/syncthing/syncthing/lib/ignore"
 	"github.com/syncthing/syncthing/lib/protocol"
@@ -2903,6 +2904,86 @@ func TestPausedFolders(t *testing.T) {
 	}
 }
 
+func TestPullInvalid(t *testing.T) {
+	if runtime.GOOS != "windows" {
+		t.Skip("Windows only")
+	}
+
+	tmpDir, err := ioutil.TempDir(".", "_model-")
+	if err != nil {
+		panic("Failed to create temporary testing dir")
+	}
+	defer os.RemoveAll(tmpDir)
+
+	cfg := defaultConfig.RawCopy()
+	cfg.Folders[0] = config.NewFolderConfiguration(protocol.LocalDeviceID, "default", "default", fs.FilesystemTypeBasic, tmpDir)
+	cfg.Folders[0].Devices = []config.FolderDeviceConfiguration{{DeviceID: device1}}
+	w := config.Wrap("/tmp/cfg", cfg)
+
+	db := db.OpenMemory()
+	m := NewModel(w, protocol.LocalDeviceID, "syncthing", "dev", db, nil)
+	m.AddFolder(cfg.Folders[0])
+	m.StartFolder("default")
+	m.ServeBackground()
+	defer m.Stop()
+	m.ScanFolder("default")
+
+	if err := m.SetIgnores("default", []string{"*:ignored"}); err != nil {
+		panic(err)
+	}
+
+	ign := "invalid:ignored"
+	del := "invalid:deleted"
+	var version protocol.Vector
+	version = version.Update(device1.Short())
+
+	m.IndexUpdate(device1, "default", []protocol.FileInfo{
+		{
+			Name:    ign,
+			Size:    1234,
+			Type:    protocol.FileInfoTypeFile,
+			Version: version,
+		},
+		{
+			Name:    del,
+			Size:    1234,
+			Type:    protocol.FileInfoTypeFile,
+			Version: version,
+			Deleted: true,
+		},
+	})
+
+	sub := events.Default.Subscribe(events.FolderErrors)
+	defer events.Default.Unsubscribe(sub)
+
+	timeout := time.NewTimer(5 * time.Second)
+	for {
+		select {
+		case ev := <-sub.C():
+			t.Fatalf("Errors while pulling: %v", ev)
+		case <-timeout.C:
+			t.Fatalf("File wasn't added to index until timeout")
+		default:
+		}
+
+		file, ok := m.CurrentFolderFile("default", ign)
+		if !ok {
+			time.Sleep(100 * time.Millisecond)
+			continue
+		}
+
+		if !file.Invalid {
+			t.Error("Ignored file isn't marked as invalid")
+		}
+
+		if file, ok = m.CurrentFolderFile("default", del); ok {
+			t.Error("Deleted invalid file was added to index")
+		}
+
+		return
+	}
+}
+
 func addFakeConn(m *Model, dev protocol.DeviceID) *fakeConnection {
 	fc := &fakeConnection{id: dev, model: m}
 	m.AddConnection(fc, protocol.HelloResult{})

+ 5 - 8
lib/model/rwfolder.go

@@ -382,14 +382,6 @@ func (f *sendReceiveFolder) pullerIteration(ignores *ignore.Matcher, ignoresChan
 			return true
 		}
 
-		// If filename isn't valid, we can terminate early with an appropriate error.
-		// in case it is deleted, we don't care about the filename, so don't complain.
-		if !intf.IsDeleted() && runtime.GOOS == "windows" && fs.WindowsInvalidFilename(intf.FileName()) {
-			f.newError("need", intf.FileName(), fs.ErrInvalidFilename)
-			changed++
-			return true
-		}
-
 		file := intf.(protocol.FileInfo)
 
 		switch {
@@ -398,6 +390,11 @@ func (f *sendReceiveFolder) pullerIteration(ignores *ignore.Matcher, ignoresChan
 			l.Debugln(f, "Handling ignored file", file)
 			dbUpdateChan <- dbUpdateJob{file, dbUpdateInvalidate}
 
+		case runtime.GOOS == "windows" && fs.WindowsInvalidFilename(file.Name):
+			f.newError("need", file.Name, fs.ErrInvalidFilename)
+			changed++
+			return true
+
 		case file.IsDeleted():
 			processDirectly = append(processDirectly, file)
 			changed++