Support multiple scan query strings at the same time

This commit is contained in:
Lode Hoste 2015-03-27 09:51:18 +01:00
parent fc0cb704f2
commit 2012ce02e8
4 changed files with 50 additions and 23 deletions

View File

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

View File

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

View File

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

View File

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