all: Convert folders to use filesystem abstraction
GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4228
This commit is contained in:
committed by
Jakob Borg
parent
ab8c2fb5c7
commit
3d8b4a42b7
@@ -12,13 +12,13 @@ import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
)
|
||||
@@ -77,6 +77,7 @@ type ChangeDetector interface {
|
||||
}
|
||||
|
||||
type Matcher struct {
|
||||
fs fs.Filesystem
|
||||
lines []string // exact lines read from .stignore
|
||||
patterns []Pattern // patterns including those from included files
|
||||
withCache bool
|
||||
@@ -105,8 +106,9 @@ func WithChangeDetector(cd ChangeDetector) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func New(opts ...Option) *Matcher {
|
||||
func New(fs fs.Filesystem, opts ...Option) *Matcher {
|
||||
m := &Matcher{
|
||||
fs: fs,
|
||||
stop: make(chan struct{}),
|
||||
mut: sync.NewMutex(),
|
||||
}
|
||||
@@ -114,7 +116,7 @@ func New(opts ...Option) *Matcher {
|
||||
opt(m)
|
||||
}
|
||||
if m.changeDetector == nil {
|
||||
m.changeDetector = newModtimeChecker()
|
||||
m.changeDetector = newModtimeChecker(fs)
|
||||
}
|
||||
if m.withCache {
|
||||
go m.clean(2 * time.Hour)
|
||||
@@ -130,7 +132,7 @@ func (m *Matcher) Load(file string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
fd, err := os.Open(file)
|
||||
fd, err := m.fs.Open(file)
|
||||
if err != nil {
|
||||
m.parseLocked(&bytes.Buffer{}, file)
|
||||
return err
|
||||
@@ -156,7 +158,7 @@ func (m *Matcher) Parse(r io.Reader, file string) error {
|
||||
}
|
||||
|
||||
func (m *Matcher) parseLocked(r io.Reader, file string) error {
|
||||
lines, patterns, err := parseIgnoreFile(r, file, m.changeDetector)
|
||||
lines, patterns, err := parseIgnoreFile(m.fs, r, file, m.changeDetector)
|
||||
// Error is saved and returned at the end. We process the patterns
|
||||
// (possibly blank) anyway.
|
||||
|
||||
@@ -298,12 +300,12 @@ func hashPatterns(patterns []Pattern) string {
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
||||
|
||||
func loadIgnoreFile(file string, cd ChangeDetector) ([]string, []Pattern, error) {
|
||||
func loadIgnoreFile(fs fs.Filesystem, file string, cd ChangeDetector) ([]string, []Pattern, error) {
|
||||
if cd.Seen(file) {
|
||||
return nil, nil, fmt.Errorf("multiple include of ignore file %q", file)
|
||||
}
|
||||
|
||||
fd, err := os.Open(file)
|
||||
fd, err := fs.Open(file)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -316,10 +318,10 @@ func loadIgnoreFile(file string, cd ChangeDetector) ([]string, []Pattern, error)
|
||||
|
||||
cd.Remember(file, info.ModTime())
|
||||
|
||||
return parseIgnoreFile(fd, file, cd)
|
||||
return parseIgnoreFile(fs, fd, file, cd)
|
||||
}
|
||||
|
||||
func parseIgnoreFile(fd io.Reader, currentFile string, cd ChangeDetector) ([]string, []Pattern, error) {
|
||||
func parseIgnoreFile(fs fs.Filesystem, fd io.Reader, currentFile string, cd ChangeDetector) ([]string, []Pattern, error) {
|
||||
var lines []string
|
||||
var patterns []Pattern
|
||||
|
||||
@@ -386,7 +388,7 @@ func parseIgnoreFile(fd io.Reader, currentFile string, cd ChangeDetector) ([]str
|
||||
} else if strings.HasPrefix(line, "#include ") {
|
||||
includeRel := line[len("#include "):]
|
||||
includeFile := filepath.Join(filepath.Dir(currentFile), includeRel)
|
||||
_, includePatterns, err := loadIgnoreFile(includeFile, cd)
|
||||
_, includePatterns, err := loadIgnoreFile(fs, includeFile, cd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("include of %q: %v", includeRel, err)
|
||||
}
|
||||
@@ -450,7 +452,7 @@ func parseIgnoreFile(fd io.Reader, currentFile string, cd ChangeDetector) ([]str
|
||||
// path must be clean (i.e., in canonical shortest form).
|
||||
func IsInternal(file string) bool {
|
||||
internals := []string{".stfolder", ".stignore", ".stversions"}
|
||||
pathSep := string(os.PathSeparator)
|
||||
pathSep := string(fs.PathSeparator)
|
||||
for _, internal := range internals {
|
||||
if file == internal {
|
||||
return true
|
||||
@@ -463,8 +465,8 @@ func IsInternal(file string) bool {
|
||||
}
|
||||
|
||||
// WriteIgnores is a convenience function to avoid code duplication
|
||||
func WriteIgnores(path string, content []string) error {
|
||||
fd, err := osutil.CreateAtomic(path)
|
||||
func WriteIgnores(filesystem fs.Filesystem, path string, content []string) error {
|
||||
fd, err := osutil.CreateAtomicFilesystem(filesystem, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -476,18 +478,20 @@ func WriteIgnores(path string, content []string) error {
|
||||
if err := fd.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
osutil.HideFile(path)
|
||||
filesystem.Hide(path)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// modtimeChecker is the default implementation of ChangeDetector
|
||||
type modtimeChecker struct {
|
||||
fs fs.Filesystem
|
||||
modtimes map[string]time.Time
|
||||
}
|
||||
|
||||
func newModtimeChecker() *modtimeChecker {
|
||||
func newModtimeChecker(fs fs.Filesystem) *modtimeChecker {
|
||||
return &modtimeChecker{
|
||||
fs: fs,
|
||||
modtimes: map[string]time.Time{},
|
||||
}
|
||||
}
|
||||
@@ -507,7 +511,7 @@ func (c *modtimeChecker) Reset() {
|
||||
|
||||
func (c *modtimeChecker) Changed() bool {
|
||||
for name, modtime := range c.modtimes {
|
||||
info, err := os.Stat(name)
|
||||
info, err := c.fs.Stat(name)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user