Browse Source

Merge pull request #1530 from Zillode/multi-scan

Support multiple scan query strings at the same time
Jakob Borg 10 years ago
parent
commit
ba575f55ec
4 changed files with 50 additions and 23 deletions
  1. 2 2
      cmd/syncthing/gui.go
  2. 37 16
      internal/model/model.go
  3. 10 4
      internal/scanner/walk.go
  4. 1 1
      internal/scanner/walk_test.go

+ 2 - 2
cmd/syncthing/gui.go

@@ -685,8 +685,8 @@ func restPostScan(m *model.Model, w http.ResponseWriter, r *http.Request) {
 	qs := r.URL.Query()
 	folder := qs.Get("folder")
 	if folder != "" {
-		sub := qs.Get("sub")
-		err := m.ScanFolderSub(folder, sub)
+		subs := qs["sub"]
+		err := m.ScanFolderSubs(folder, subs)
 		if err != nil {
 			http.Error(w, err.Error(), 500)
 		}

+ 37 - 16
internal/model/model.go

@@ -1114,13 +1114,16 @@ func (m *Model) ScanFolders() map[string]error {
 }
 
 func (m *Model) ScanFolder(folder string) error {
-	return m.ScanFolderSub(folder, "")
+	return m.ScanFolderSubs(folder, nil)
 }
 
-func (m *Model) ScanFolderSub(folder, sub string) error {
-	sub = osutil.NativeFilename(sub)
-	if p := filepath.Clean(filepath.Join(folder, sub)); !strings.HasPrefix(p, folder) {
-		return errors.New("invalid subpath")
+func (m *Model) ScanFolderSubs(folder string, subs []string) error {
+	for i, sub := range subs {
+		sub = osutil.NativeFilename(sub)
+		if p := filepath.Clean(filepath.Join(folder, sub)); !strings.HasPrefix(p, folder) {
+			return errors.New("invalid subpath")
+		}
+		subs[i] = sub
 	}
 
 	m.fmut.Lock()
@@ -1141,19 +1144,30 @@ func (m *Model) ScanFolderSub(folder, sub string) error {
 
 	// Required to make sure that we start indexing at a directory we're already
 	// aware off.
-	for sub != "" {
-		if _, ok = fs.Get(protocol.LocalDeviceID, sub); ok {
-			break
+	var unifySubs []string
+nextSub:
+	for _, sub := range subs {
+		for sub != "" {
+			if _, ok = fs.Get(protocol.LocalDeviceID, sub); ok {
+				break
+			}
+			sub = filepath.Dir(sub)
+			if sub == "." || sub == string(filepath.Separator) {
+				sub = ""
+			}
 		}
-		sub = filepath.Dir(sub)
-		if sub == "." || sub == string(filepath.Separator) {
-			sub = ""
+		for _, us := range unifySubs {
+			if strings.HasPrefix(sub, us) {
+				continue nextSub
+			}
 		}
+		unifySubs = append(unifySubs, sub)
 	}
+	subs = unifySubs
 
 	w := &scanner.Walker{
 		Dir:           folderCfg.Path,
-		Sub:           sub,
+		Subs:          subs,
 		Matcher:       ignores,
 		BlockSize:     protocol.BlockSize,
 		TempNamer:     defTempNamer,
@@ -1196,10 +1210,17 @@ func (m *Model) ScanFolderSub(folder, sub string) error {
 	seenPrefix := false
 	fs.WithHaveTruncated(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
 		f := fi.(db.FileInfoTruncated)
-		if !strings.HasPrefix(f.Name, sub) {
-			// Return true so that we keep iterating, until we get to the part
-			// of the tree we are interested in. Then return false so we stop
-			// iterating when we've passed the end of the subtree.
+		hasPrefix := len(subs) == 0
+		for _, sub := range subs {
+			if strings.HasPrefix(f.Name, sub) {
+				hasPrefix = true
+				break
+			}
+		}
+		// Return true so that we keep iterating, until we get to the part
+		// of the tree we are interested in. Then return false so we stop
+		// iterating when we've passed the end of the subtree.
+		if !hasPrefix {
 			return !seenPrefix
 		}
 

+ 10 - 4
internal/scanner/walk.go

@@ -39,8 +39,8 @@ func init() {
 type Walker struct {
 	// Dir is the base directory for the walk
 	Dir string
-	// Limit walking to this path within Dir, or no limit if Sub is blank
-	Sub string
+	// Limit walking to these paths within Dir, or no limit if Sub is empty
+	Subs []string
 	// BlockSize controls the size of the block used when hashing.
 	BlockSize int
 	// If Matcher is not nil, it is used to identify files to ignore which were specified by the user.
@@ -80,7 +80,7 @@ type CurrentFiler interface {
 // file system. Files are blockwise hashed.
 func (w *Walker) Walk() (chan protocol.FileInfo, error) {
 	if debug {
-		l.Debugln("Walk", w.Dir, w.Sub, w.BlockSize, w.Matcher)
+		l.Debugln("Walk", w.Dir, w.Subs, w.BlockSize, w.Matcher)
 	}
 
 	err := checkDir(w.Dir)
@@ -99,7 +99,13 @@ func (w *Walker) Walk() (chan protocol.FileInfo, error) {
 
 	go func() {
 		hashFiles := w.walkAndHashFiles(files)
-		filepath.Walk(filepath.Join(w.Dir, w.Sub), hashFiles)
+		if len(w.Subs) == 0 {
+			filepath.Walk(w.Dir, hashFiles)
+		} else {
+			for _, sub := range w.Subs {
+				filepath.Walk(filepath.Join(w.Dir, sub), hashFiles)
+			}
+		}
 		close(files)
 	}()
 

+ 1 - 1
internal/scanner/walk_test.go

@@ -60,7 +60,7 @@ func TestWalkSub(t *testing.T) {
 
 	w := Walker{
 		Dir:       "testdata",
-		Sub:       "dir2",
+		Subs:      []string{"dir2"},
 		BlockSize: 128 * 1024,
 		Matcher:   ignores,
 	}