mirror of
https://github.com/octoleo/syncthing.git
synced 2025-02-02 11:58:28 +00:00
Implement external scan request (fixes #9)
This commit is contained in:
parent
279693078a
commit
9752ea9ac3
@ -126,6 +126,7 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro
|
|||||||
postRestMux.HandleFunc("/rest/restart", restPostRestart)
|
postRestMux.HandleFunc("/rest/restart", restPostRestart)
|
||||||
postRestMux.HandleFunc("/rest/shutdown", restPostShutdown)
|
postRestMux.HandleFunc("/rest/shutdown", restPostShutdown)
|
||||||
postRestMux.HandleFunc("/rest/upgrade", restPostUpgrade)
|
postRestMux.HandleFunc("/rest/upgrade", restPostUpgrade)
|
||||||
|
postRestMux.HandleFunc("/rest/scan", withModel(m, restPostScan))
|
||||||
|
|
||||||
// A handler that splits requests between the two above and disables
|
// A handler that splits requests between the two above and disables
|
||||||
// caching
|
// caching
|
||||||
@ -530,6 +531,16 @@ func restPostUpgrade(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func restPostScan(m *model.Model, w http.ResponseWriter, r *http.Request) {
|
||||||
|
qs := r.URL.Query()
|
||||||
|
repo := qs.Get("repo")
|
||||||
|
sub := qs.Get("sub")
|
||||||
|
err := m.ScanRepoSub(repo, sub)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getQR(w http.ResponseWriter, r *http.Request) {
|
func getQR(w http.ResponseWriter, r *http.Request) {
|
||||||
var qs = r.URL.Query()
|
var qs = r.URL.Query()
|
||||||
var text = qs.Get("text")
|
var text = qs.Get("text")
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -744,12 +745,21 @@ func (m *Model) CleanRepos() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) ScanRepo(repo string) error {
|
func (m *Model) ScanRepo(repo string) error {
|
||||||
|
return m.ScanRepoSub(repo, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Model) ScanRepoSub(repo, sub string) error {
|
||||||
|
if p := filepath.Clean(filepath.Join(repo, sub)); !strings.HasPrefix(p, repo) {
|
||||||
|
return errors.New("invalid subpath")
|
||||||
|
}
|
||||||
|
|
||||||
m.rmut.RLock()
|
m.rmut.RLock()
|
||||||
fs := m.repoFiles[repo]
|
fs, ok := m.repoFiles[repo]
|
||||||
dir := m.repoCfgs[repo].Directory
|
dir := m.repoCfgs[repo].Directory
|
||||||
|
|
||||||
w := &scanner.Walker{
|
w := &scanner.Walker{
|
||||||
Dir: dir,
|
Dir: dir,
|
||||||
|
Sub: sub,
|
||||||
IgnoreFile: ".stignore",
|
IgnoreFile: ".stignore",
|
||||||
BlockSize: scanner.StandardBlockSize,
|
BlockSize: scanner.StandardBlockSize,
|
||||||
TempNamer: defTempNamer,
|
TempNamer: defTempNamer,
|
||||||
@ -758,6 +768,9 @@ func (m *Model) ScanRepo(repo string) error {
|
|||||||
IgnorePerms: m.repoCfgs[repo].IgnorePerms,
|
IgnorePerms: m.repoCfgs[repo].IgnorePerms,
|
||||||
}
|
}
|
||||||
m.rmut.RUnlock()
|
m.rmut.RUnlock()
|
||||||
|
if !ok {
|
||||||
|
return errors.New("no such repo")
|
||||||
|
}
|
||||||
|
|
||||||
m.setState(repo, RepoScanning)
|
m.setState(repo, RepoScanning)
|
||||||
fchan, _, err := w.Walk()
|
fchan, _, err := w.Walk()
|
||||||
@ -786,7 +799,13 @@ func (m *Model) ScanRepo(repo string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
batch = batch[:0]
|
batch = batch[:0]
|
||||||
|
// TODO: We should limit the Have scanning to start at sub
|
||||||
|
seenPrefix := false
|
||||||
fs.WithHave(protocol.LocalNodeID, func(f protocol.FileInfo) bool {
|
fs.WithHave(protocol.LocalNodeID, func(f protocol.FileInfo) bool {
|
||||||
|
if !strings.HasPrefix(f.Name, sub) {
|
||||||
|
return !seenPrefix
|
||||||
|
}
|
||||||
|
seenPrefix = true
|
||||||
if !protocol.IsDeleted(f.Flags) {
|
if !protocol.IsDeleted(f.Flags) {
|
||||||
if len(batch) == batchSize {
|
if len(batch) == batchSize {
|
||||||
fs.Update(protocol.LocalNodeID, batch)
|
fs.Update(protocol.LocalNodeID, batch)
|
||||||
|
@ -22,6 +22,8 @@ import (
|
|||||||
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
|
||||||
|
Sub 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 IgnoreFile is not empty, it is the name used for the file that holds ignore patterns.
|
// If IgnoreFile is not empty, it is the name used for the file that holds ignore patterns.
|
||||||
@ -61,7 +63,7 @@ type CurrentFiler interface {
|
|||||||
// file system. Files are blockwise hashed.
|
// file system. Files are blockwise hashed.
|
||||||
func (w *Walker) Walk() (chan protocol.FileInfo, map[string][]string, error) {
|
func (w *Walker) Walk() (chan protocol.FileInfo, map[string][]string, error) {
|
||||||
if debug {
|
if debug {
|
||||||
l.Debugln("Walk", w.Dir, w.BlockSize, w.IgnoreFile)
|
l.Debugln("Walk", w.Dir, w.Sub, w.BlockSize, w.IgnoreFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := checkDir(w.Dir)
|
err := checkDir(w.Dir)
|
||||||
@ -77,7 +79,7 @@ func (w *Walker) Walk() (chan protocol.FileInfo, map[string][]string, error) {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
filepath.Walk(w.Dir, w.loadIgnoreFiles(w.Dir, ignore))
|
filepath.Walk(w.Dir, w.loadIgnoreFiles(w.Dir, ignore))
|
||||||
filepath.Walk(w.Dir, hashFiles)
|
filepath.Walk(filepath.Join(w.Dir, w.Sub), hashFiles)
|
||||||
close(files)
|
close(files)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -29,6 +29,30 @@ var correctIgnores = map[string][]string{
|
|||||||
".": {".*", "quux"},
|
".": {".*", "quux"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWalkSub(t *testing.T) {
|
||||||
|
w := Walker{
|
||||||
|
Dir: "testdata",
|
||||||
|
Sub: "foo",
|
||||||
|
BlockSize: 128 * 1024,
|
||||||
|
IgnoreFile: ".stignore",
|
||||||
|
}
|
||||||
|
fchan, _, err := w.Walk()
|
||||||
|
var files []protocol.FileInfo
|
||||||
|
for f := range fchan {
|
||||||
|
files = append(files, f)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(files) != 1 {
|
||||||
|
t.Fatalf("Incorrect length %d != 1", len(files))
|
||||||
|
}
|
||||||
|
if files[0].Name != "foo" {
|
||||||
|
t.Errorf("Incorrect file %v != foo", files[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestWalk(t *testing.T) {
|
func TestWalk(t *testing.T) {
|
||||||
w := Walker{
|
w := Walker{
|
||||||
Dir: "testdata",
|
Dir: "testdata",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user