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()
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)
}

View File

@ -1102,13 +1102,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()
@ -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
// 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,
@ -1184,10 +1198,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
}

View File

@ -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)
}()

View File

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