chore: remove ignore file caching entirely (#10813)

Effectively nobody uses it, it cost more than it was worth, the code
doesn't carry its weight. Remove it and let any similar mechanism in the
future be an internal implementation detail.

Closes #10812

Signed-off-by: Jakob Borg <jakob@kastelo.net>
This commit is contained in:
Jakob Borg
2026-07-25 09:43:22 +02:00
committed by GitHub
parent 2f81bf5d34
commit b15ff42d52
20 changed files with 52 additions and 452 deletions
-1
View File
@@ -116,7 +116,6 @@
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
<upgradeToPreReleases>false</upgradeToPreReleases>
<keepTemporariesH>24</keepTemporariesH>
<cacheIgnoredFiles>false</cacheIgnoredFiles>
<progressUpdateIntervalS>5</progressUpdateIntervalS>
<limitBandwidthInLan>false</limitBandwidthInLan>
<minHomeDiskFree unit="%">1</minHomeDiskFree>
-2
View File
@@ -72,7 +72,6 @@ func TestDefaultValues(t *testing.T) {
NATTimeoutS: 10,
AutoUpgradeIntervalH: 12,
KeepTemporariesH: 24,
CacheIgnoredFiles: false,
ProgressUpdateIntervalS: 5,
LimitBandwidthInLan: false,
MinHomeDiskFree: Size{1, "%"},
@@ -278,7 +277,6 @@ func TestOverriddenValues(t *testing.T) {
NATTimeoutS: 15,
AutoUpgradeIntervalH: 24,
KeepTemporariesH: 48,
CacheIgnoredFiles: true,
ProgressUpdateIntervalS: 10,
LimitBandwidthInLan: true,
MinHomeDiskFree: Size{5.2, "%"},
-4
View File
@@ -320,10 +320,6 @@ func migrateToConfigV15(cfg *Configuration) {
}
func migrateToConfigV14(cfg *Configuration) {
// Not using the ignore cache is the new default. Disable it on existing
// configurations.
cfg.Options.CacheIgnoredFiles = false
// Migrate UPnP -> NAT options
cfg.Options.NATEnabled = cfg.Options.DeprecatedUPnPEnabled
cfg.Options.DeprecatedUPnPEnabled = false
-1
View File
@@ -45,7 +45,6 @@ type OptionsConfiguration struct {
AutoUpgradeIntervalH int `json:"autoUpgradeIntervalH" xml:"autoUpgradeIntervalH" default:"12"`
UpgradeToPreReleases bool `json:"upgradeToPreReleases" xml:"upgradeToPreReleases"`
KeepTemporariesH int `json:"keepTemporariesH" xml:"keepTemporariesH" default:"24"`
CacheIgnoredFiles bool `json:"cacheIgnoredFiles" xml:"cacheIgnoredFiles" default:"false"`
ProgressUpdateIntervalS int `json:"progressUpdateIntervalS" xml:"progressUpdateIntervalS" default:"5"`
LimitBandwidthInLan bool `json:"limitBandwidthInLan" xml:"limitBandwidthInLan" default:"false"`
MinHomeDiskFree Size `json:"minHomeDiskFree" xml:"minHomeDiskFree" default:"1 %"`
-1
View File
@@ -42,7 +42,6 @@
<restartOnWakeup>true</restartOnWakeup>
<autoUpgradeIntervalH>0</autoUpgradeIntervalH>
<keepTemporariesH>24</keepTemporariesH>
<cacheIgnoredFiles>true</cacheIgnoredFiles>
<progressUpdateIntervalS>5</progressUpdateIntervalS>
<symlinksEnabled>true</symlinksEnabled>
<limitBandwidthInLan>false</limitBandwidthInLan>
-1
View File
@@ -22,7 +22,6 @@
<restartOnWakeup>false</restartOnWakeup>
<autoUpgradeIntervalH>24</autoUpgradeIntervalH>
<keepTemporariesH>48</keepTemporariesH>
<cacheIgnoredFiles>true</cacheIgnoredFiles>
<progressUpdateIntervalS>10</progressUpdateIntervalS>
<symlinksEnabled>false</symlinksEnabled>
<limitBandwidthInLan>true</limitBandwidthInLan>
-66
View File
@@ -1,66 +0,0 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package ignore
import (
"time"
"github.com/syncthing/syncthing/lib/ignore/ignoreresult"
)
type nower interface {
Now() time.Time
}
var clock = nower(defaultClock{})
type cache struct {
entries map[string]cacheEntry
}
type cacheEntry struct {
result ignoreresult.R
access int64 // Unix nanosecond count. Sufficient until the year 2262.
}
func newCache() *cache {
return &cache{
entries: make(map[string]cacheEntry),
}
}
func (c *cache) clean(d time.Duration) {
for k, v := range c.entries {
if clock.Now().Sub(time.Unix(0, v.access)) > d {
delete(c.entries, k)
}
}
}
func (c *cache) get(key string) (ignoreresult.R, bool) {
entry, ok := c.entries[key]
if ok {
entry.access = clock.Now().UnixNano()
c.entries[key] = entry
}
return entry.result, ok
}
func (c *cache) set(key string, result ignoreresult.R) {
c.entries[key] = cacheEntry{result, time.Now().UnixNano()}
}
func (c *cache) len() int {
l := len(c.entries)
return l
}
type defaultClock struct{}
func (defaultClock) Now() time.Time {
return time.Now()
}
-94
View File
@@ -1,94 +0,0 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package ignore
import (
"testing"
"time"
"github.com/syncthing/syncthing/lib/ignore/ignoreresult"
)
func TestCache(t *testing.T) {
fc := new(fakeClock)
oldClock := clock
clock = fc
defer func() {
clock = oldClock
}()
c := newCache()
res, ok := c.get("nonexistent")
if res.IsIgnored() || res.IsDeletable() || ok {
t.Errorf("res %v, ok %v for nonexistent item", res, ok)
}
// Set and check some items
c.set("true", ignoreresult.IgnoredDeletable)
c.set("false", 0)
res, ok = c.get("true")
if !res.IsIgnored() || !res.IsDeletable() || !ok {
t.Errorf("res %v, ok %v for true item", res, ok)
}
res, ok = c.get("false")
if res.IsIgnored() || res.IsDeletable() || !ok {
t.Errorf("res %v, ok %v for false item", res, ok)
}
// Don't clean anything
c.clean(time.Second)
// Same values should exist
res, ok = c.get("true")
if !res.IsIgnored() || !res.IsDeletable() || !ok {
t.Errorf("res %v, ok %v for true item", res, ok)
}
res, ok = c.get("false")
if res.IsIgnored() || res.IsDeletable() || !ok {
t.Errorf("res %v, ok %v for false item", res, ok)
}
// Sleep and access, to get some data for clean
*fc += 500 // milliseconds
c.get("true")
*fc += 100 // milliseconds
// "false" was accessed ~600 ms ago, "true" was accessed ~100 ms ago.
// This should clean out "false" but not "true"
c.clean(300 * time.Millisecond)
// Same values should exist
_, ok = c.get("true")
if !ok {
t.Error("item should still exist")
}
_, ok = c.get("false")
if ok {
t.Errorf("item should have been cleaned")
}
}
type fakeClock int64 // milliseconds
func (f *fakeClock) Now() time.Time {
t := time.Unix(int64(*f)/1000, (int64(*f)%1000)*int64(time.Millisecond))
*f++
return t
}
+2 -53
View File
@@ -124,10 +124,7 @@ type Matcher struct {
fs fs.Filesystem
lines []string // exact lines read from .stignore
patterns []Pattern // patterns including those from included files
withCache bool
matches *cache
curHash string
stop chan struct{}
changeDetector ChangeDetector
mut sync.Mutex
}
@@ -135,13 +132,6 @@ type Matcher struct {
// An Option can be passed to New()
type Option func(*Matcher)
// WithCache enables or disables lookup caching. The default is disabled.
func WithCache(v bool) Option {
return func(m *Matcher) {
m.withCache = v
}
}
// WithChangeDetector sets a custom ChangeDetector. The default is to simply
// use the on disk modtime for comparison.
func WithChangeDetector(cd ChangeDetector) Option {
@@ -152,8 +142,7 @@ func WithChangeDetector(cd ChangeDetector) Option {
func New(fs fs.Filesystem, opts ...Option) *Matcher {
m := &Matcher{
fs: fs,
stop: make(chan struct{}),
fs: fs,
}
for _, opt := range opts {
opt(m)
@@ -161,9 +150,6 @@ func New(fs fs.Filesystem, opts ...Option) *Matcher {
if m.changeDetector == nil {
m.changeDetector = newModtimeChecker()
}
if m.withCache {
go m.clean(2 * time.Hour)
}
return m
}
@@ -219,9 +205,6 @@ func (m *Matcher) parseLocked(r io.Reader, file string) error {
m.curHash = newHash
m.patterns = patterns
if m.withCache {
m.matches = newCache()
}
return err
}
@@ -232,7 +215,7 @@ func (m *Matcher) parseLocked(r io.Reader, file string) error {
// NFC everywhere else). This is always the case in real usage in syncthing, as
// we ensure native unicode normalisation on all entry points (scanning and from
// protocol) - so no need to normalize when calling this, except e.g. in tests.
func (m *Matcher) Match(file string) (result ignoreresult.R) {
func (m *Matcher) Match(file string) ignoreresult.R {
switch {
case fs.IsTemporary(file):
return ignoreresult.IgnoreAndSkip
@@ -254,19 +237,6 @@ func (m *Matcher) Match(file string) (result ignoreresult.R) {
// Change backslashes to slashes (on Windows only)
file = filepath.ToSlash(file)
if m.matches != nil {
// Check the cache for a known result.
res, ok := m.matches.get(file)
if ok {
return res
}
// Update the cache with the result at return time
defer func() {
m.matches.set(file, result)
}()
}
// Check all the patterns for a match. Track whether the patterns so far
// allow skipping matched directories or not. As soon as we hit an
// exclude pattern (with some exceptions), we can't skip directories
@@ -327,27 +297,6 @@ func (m *Matcher) Hash() string {
return m.curHash
}
func (m *Matcher) Stop() {
close(m.stop)
}
func (m *Matcher) clean(d time.Duration) {
t := time.NewTimer(d / 2)
for {
select {
case <-m.stop:
return
case <-t.C:
m.mut.Lock()
if m.matches != nil {
m.matches.clean(d)
}
t.Reset(d / 2)
m.mut.Unlock()
}
}
}
func hashPatterns(patterns []Pattern) string {
h := sha256.New()
for _, pat := range patterns {
+33 -206
View File
@@ -52,7 +52,7 @@ func newTestFS() fs.Filesystem {
func TestIgnore(t *testing.T) {
testFs := newTestFS()
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Load(".stignore")
if err != nil {
t.Fatal(err)
@@ -104,7 +104,7 @@ func TestExcludes(t *testing.T) {
i*2
!ign2
`
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
t.Fatal(err)
@@ -151,7 +151,7 @@ func TestFlagOrder(t *testing.T) {
(?i)(?d)(?d)!ign9
(?d)(?d)!ign10
`
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
t.Fatal(err)
@@ -188,7 +188,7 @@ func TestDeletables(t *testing.T) {
ign7
(?i)ign8
`
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
t.Fatal(err)
@@ -229,7 +229,7 @@ func TestBadPatterns(t *testing.T) {
}
for _, pat := range badPatterns {
err := New(testFs, WithCache(true)).Parse(bytes.NewBufferString(pat), ".stignore")
err := New(testFs).Parse(bytes.NewBufferString(pat), ".stignore")
if err == nil {
t.Errorf("No error for pattern %q", pat)
}
@@ -247,7 +247,7 @@ func TestBadPatterns(t *testing.T) {
func TestCaseSensitivity(t *testing.T) {
testFs := newTestFS()
ign := New(testFs, WithCache(true))
ign := New(testFs)
err := ign.Parse(bytes.NewBufferString("test"), ".stignore")
if err != nil {
t.Error(err)
@@ -275,126 +275,6 @@ func TestCaseSensitivity(t *testing.T) {
}
}
func TestCaching(t *testing.T) {
fs := fs.NewFilesystem(fs.FilesystemTypeFake, rand.String(32)+"?content=true")
fd1, err := osutil.TempFile(fs, "", "")
if err != nil {
t.Fatal(err)
}
fd2, err := osutil.TempFile(fs, "", "")
if err != nil {
t.Fatal(err)
}
defer fd1.Close()
defer fd2.Close()
defer fs.Remove(fd1.Name())
defer fs.Remove(fd2.Name())
_, err = fd1.Write([]byte("/x/\n#include " + filepath.Base(fd2.Name()) + "\n"))
if err != nil {
t.Fatal(err)
}
fd2.Write([]byte("/y/\n"))
pats := New(fs, WithCache(true))
err = pats.Load(fd1.Name())
if err != nil {
t.Fatal(err)
}
if pats.matches.len() != 0 {
t.Fatal("Expected empty cache")
}
// Cache some outcomes
for _, letter := range []string{"a", "b", "x", "y"} {
pats.Match(letter)
}
if pats.matches.len() != 4 {
t.Fatal("Expected 4 cached results")
}
// Reload file, expect old outcomes to be preserved
err = pats.Load(fd1.Name())
if err != nil {
t.Fatal(err)
}
if pats.matches.len() != 4 {
t.Fatal("Expected 4 cached results")
}
// Modify the include file, expect empty cache. Ensure the timestamp on
// the file changes.
fd2.Write([]byte("/z/\n"))
fd2.Sync()
fakeTime := time.Now().Add(5 * time.Second)
fs.Chtimes(fd2.Name(), fakeTime, fakeTime)
err = pats.Load(fd1.Name())
if err != nil {
t.Fatal(err)
}
if pats.matches.len() != 0 {
t.Fatal("Expected 0 cached results")
}
// Cache some outcomes again
for _, letter := range []string{"b", "x", "y"} {
pats.Match(letter)
}
// Verify that outcomes preserved on next load
err = pats.Load(fd1.Name())
if err != nil {
t.Fatal(err)
}
if pats.matches.len() != 3 {
t.Fatal("Expected 3 cached results")
}
// Modify the root file, expect cache to be invalidated
fd1.Write([]byte("/a/\n"))
fd1.Sync()
fakeTime = time.Now().Add(5 * time.Second)
fs.Chtimes(fd1.Name(), fakeTime, fakeTime)
err = pats.Load(fd1.Name())
if err != nil {
t.Fatal(err)
}
if pats.matches.len() != 0 {
t.Fatal("Expected cache invalidation")
}
// Cache some outcomes again
for _, letter := range []string{"b", "x", "y"} {
pats.Match(letter)
}
// Verify that outcomes provided on next load
err = pats.Load(fd1.Name())
if err != nil {
t.Fatal(err)
}
if pats.matches.len() != 3 {
t.Fatal("Expected 3 cached results")
}
}
func TestCommentsAndBlankLines(t *testing.T) {
testFs := newTestFS()
@@ -409,7 +289,7 @@ func TestCommentsAndBlankLines(t *testing.T) {
`
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
t.Error(err)
@@ -451,59 +331,6 @@ flamingo
}
}
func BenchmarkMatchCached(b *testing.B) {
stignore := `
.frog
.frog*
.frogfox
.whale
.whale/*
.dolphin
.dolphin/*
~ferret~.*
.ferret.*
flamingo.*
flamingo
*.crow
*.crow
`
// Caches per file, hence write the patterns to a file.
fs := fs.NewFilesystem(fs.FilesystemTypeFake, rand.String(32)+"?content=true")
fd, err := osutil.TempFile(fs, "", "")
if err != nil {
b.Fatal(err)
}
_, err = fd.Write([]byte(stignore))
defer fd.Close()
defer fs.Remove(fd.Name())
if err != nil {
b.Fatal(err)
}
// Load the patterns
pats := New(fs, WithCache(true))
err = pats.Load(fd.Name())
if err != nil {
b.Fatal(err)
}
// Cache the outcome for "filename"
pats.Match("filename")
// This load should now load the cached outcomes as the set of patterns
// has not changed.
err = pats.Load(fd.Name())
if err != nil {
b.Fatal(err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
result = pats.Match("filename")
}
}
func TestCacheReload(t *testing.T) {
fs := fs.NewFilesystem(fs.FilesystemTypeFake, rand.String(32)+"?content=true")
@@ -522,7 +349,7 @@ func TestCacheReload(t *testing.T) {
t.Fatal(err)
}
pats := New(fs, WithCache(true))
pats := New(fs)
err = pats.Load(fd.Name())
if err != nil {
t.Fatal(err)
@@ -579,7 +406,7 @@ func TestCacheReload(t *testing.T) {
func TestHash(t *testing.T) {
testFs := newTestFS()
p1 := New(testFs, WithCache(true))
p1 := New(testFs)
err := p1.Load(".stignore")
if err != nil {
t.Fatal(err)
@@ -595,7 +422,7 @@ func TestHash(t *testing.T) {
/ffile
lost+found
`
p2 := New(testFs, WithCache(true))
p2 := New(testFs)
err = p2.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
t.Fatal(err)
@@ -610,7 +437,7 @@ func TestHash(t *testing.T) {
/ffile
lost+found
`
p3 := New(testFs, WithCache(true))
p3 := New(testFs)
err = p3.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
t.Fatal(err)
@@ -636,7 +463,7 @@ func TestHash(t *testing.T) {
func TestHashOfEmpty(t *testing.T) {
testFs := newTestFS()
p1 := New(testFs, WithCache(true))
p1 := New(testFs)
err := p1.Load(".stignore")
if err != nil {
@@ -678,7 +505,7 @@ func TestWindowsPatterns(t *testing.T) {
a/b
c\d
`
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
@@ -706,7 +533,7 @@ func TestAutomaticCaseInsensitivity(t *testing.T) {
A/B
c/d
`
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
@@ -728,7 +555,7 @@ func TestCommas(t *testing.T) {
foo,bar.txt
{baz,quux}.txt
`
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
@@ -762,7 +589,7 @@ func TestIssue3164(t *testing.T) {
(?d)(?i)/foo
(?d)(?i)**/bar
`
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
@@ -801,7 +628,7 @@ func TestIssue3174(t *testing.T) {
stignore := `
*ä*
`
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
@@ -822,7 +649,7 @@ func TestIssue3639(t *testing.T) {
stignore := `
foo/
`
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
@@ -858,7 +685,7 @@ func TestIssue3674(t *testing.T) {
{"as/dc", true},
}
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
@@ -893,7 +720,7 @@ func TestGobwasGlobIssue18(t *testing.T) {
{"bbaa", false},
}
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
@@ -925,7 +752,7 @@ func TestRoot(t *testing.T) {
{"b", true},
}
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
@@ -951,7 +778,7 @@ func TestLines(t *testing.T) {
!/a
`
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
@@ -992,7 +819,7 @@ func TestDuplicateLines(t *testing.T) {
/*
`
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
@@ -1025,7 +852,7 @@ func TestIssue4680(t *testing.T) {
{"#snapshot/foo", true},
}
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
@@ -1045,7 +872,7 @@ func TestIssue4689(t *testing.T) {
stignore := `// orig`
pats := New(testFs, WithCache(true))
pats := New(testFs)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
@@ -1076,7 +903,7 @@ func TestIssue4901(t *testing.T) {
puppy
`
pats := New(testFs, WithCache(true))
pats := New(testFs)
fd, err := pats.fs.Create(".stignore")
if err != nil {
@@ -1119,7 +946,7 @@ func TestIssue4901(t *testing.T) {
func TestIssue5009(t *testing.T) {
testFs := newTestFS()
pats := New(testFs, WithCache(true))
pats := New(testFs)
stignore := `
ign1
@@ -1152,7 +979,7 @@ func TestIssue5009(t *testing.T) {
func TestSpecialChars(t *testing.T) {
testFs := newTestFS()
pats := New(testFs, WithCache(true))
pats := New(testFs)
stignore := `(?i)/#recycle
(?i)/#nosync
@@ -1179,7 +1006,7 @@ func TestSpecialChars(t *testing.T) {
func TestIntlWildcards(t *testing.T) {
testFs := newTestFS()
pats := New(testFs, WithCache(true))
pats := New(testFs)
stignore := `1000春
200?春
@@ -1208,7 +1035,7 @@ func TestPartialIncludeLine(t *testing.T) {
// Loading a partial #include line (no file mentioned) should error but not crash.
pats := New(testFs, WithCache(true))
pats := New(testFs)
cases := []string{
"#include",
@@ -1267,7 +1094,7 @@ func TestSkipIgnoredDirs(t *testing.T) {
}
}
pats := New(testFs, WithCache(true))
pats := New(testFs)
stignore := `
/foo/ign*
@@ -1711,7 +1538,7 @@ func testEscape(t *testing.T, tests []escapeTest, noErrors bool) {
for name, content := range testEscapeFiles {
fs.WriteFile(testFS, name, []byte(content), 0o666)
}
pats := New(testFS, WithCache(true))
pats := New(testFS)
err := pats.Parse(bytes.NewBufferString(test.pattern), ".stignore")
if noErrors {
@@ -1753,7 +1580,7 @@ func TestIgnoreThroughSymlink(t *testing.T) {
t.Fatal(err)
}
pats := New(testFS, WithCache(true))
pats := New(testFS)
if err := pats.Load(".stignore"); err != nil {
t.Fatal(err)
}
+10 -10
View File
@@ -300,7 +300,7 @@ func (m *model) initFolders(cfg config.Configuration) error {
folderCfg.CreateRoot()
continue
}
err := m.newFolder(folderCfg, cfg.Options.CacheIgnoredFiles)
err := m.newFolder(folderCfg)
if err != nil {
return err
}
@@ -335,8 +335,8 @@ func (m *model) fatal(err error) {
}
// Need to hold lock on m.mut when calling this.
func (m *model) addAndStartFolderLocked(cfg config.FolderConfiguration, cacheIgnoredFiles bool) {
ignores := ignore.New(cfg.Filesystem(), ignore.WithCache(cacheIgnoredFiles))
func (m *model) addAndStartFolderLocked(cfg config.FolderConfiguration) {
ignores := ignore.New(cfg.Filesystem())
if cfg.Type != config.FolderTypeReceiveEncrypted {
if err := ignores.Load(".stignore"); err != nil && !fs.IsNotExist(err) {
slog.Error("Failed to load ignores", slogutil.Error(err))
@@ -509,7 +509,7 @@ func (m *model) cleanupFolderLocked(cfg config.FolderConfiguration) {
delete(m.folderEncryptionFailures, cfg.ID)
}
func (m *model) restartFolder(from, to config.FolderConfiguration, cacheIgnoredFiles bool) error {
func (m *model) restartFolder(from, to config.FolderConfiguration) error {
if to.ID == "" {
panic("bug: cannot restart empty folder ID")
}
@@ -539,7 +539,7 @@ func (m *model) restartFolder(from, to config.FolderConfiguration, cacheIgnoredF
m.cleanupFolderLocked(from)
if !to.Paused {
m.addAndStartFolderLocked(to, cacheIgnoredFiles)
m.addAndStartFolderLocked(to)
}
runner, _ := m.folderRunners.Get(to.ID)
@@ -560,11 +560,11 @@ func (m *model) restartFolder(from, to config.FolderConfiguration, cacheIgnoredF
return nil
}
func (m *model) newFolder(cfg config.FolderConfiguration, cacheIgnoredFiles bool) error {
func (m *model) newFolder(cfg config.FolderConfiguration) error {
m.mut.Lock()
defer m.mut.Unlock()
m.addAndStartFolderLocked(cfg, cacheIgnoredFiles)
m.addAndStartFolderLocked(cfg)
// Cluster configs might be received and processed before reaching this
// point, i.e. before the folder is started. If that's the case, start
@@ -2972,7 +2972,7 @@ func (m *model) CommitConfiguration(from, to config.Configuration) bool {
slog.Info("Paused folder", cfg.LogAttr())
} else {
slog.Info("Adding folder", cfg.LogAttr())
if err := m.newFolder(cfg, to.Options.CacheIgnoredFiles); err != nil {
if err := m.newFolder(cfg); err != nil {
m.fatal(err)
return true
}
@@ -2998,8 +2998,8 @@ func (m *model) CommitConfiguration(from, to config.Configuration) bool {
// This folder exists on both sides. Settings might have changed.
// Check if anything differs that requires a restart.
if !reflect.DeepEqual(fromCfg.RequiresRestartOnly(), toCfg.RequiresRestartOnly()) || from.Options.CacheIgnoredFiles != to.Options.CacheIgnoredFiles {
if err := m.restartFolder(fromCfg, toCfg, to.Options.CacheIgnoredFiles); err != nil {
if !reflect.DeepEqual(fromCfg.RequiresRestartOnly(), toCfg.RequiresRestartOnly()) {
if err := m.restartFolder(fromCfg, toCfg); err != nil {
m.fatal(err)
return true
}
+3 -3
View File
@@ -1603,7 +1603,7 @@ func TestIgnores(t *testing.T) {
ID: "fresh", Path: "XXX",
FilesystemType: config.FilesystemTypeFake,
}
ignores := ignore.New(fcfg.Filesystem(), ignore.WithCache(m.cfg.Options().CacheIgnoredFiles))
ignores := ignore.New(fcfg.Filesystem())
m.mut.Lock()
m.folderCfgs[fcfg.ID] = fcfg
m.folderIgnores[fcfg.ID] = ignores
@@ -1618,7 +1618,7 @@ func TestIgnores(t *testing.T) {
pausedDefaultFolderConfig := defaultFolderConfig
pausedDefaultFolderConfig.Paused = true
m.restartFolder(defaultFolderConfig, pausedDefaultFolderConfig, false)
m.restartFolder(defaultFolderConfig, pausedDefaultFolderConfig)
// Here folder initialization is not an issue as a paused folder isn't
// added to the model and thus there is no initial scan happening.
@@ -2216,7 +2216,7 @@ func TestIndexesForUnknownDevicesDropped(t *testing.T) {
t.Error("expected two devices")
}
m.newFolder(defaultFolderConfig, false)
m.newFolder(defaultFolderConfig)
defer cleanupModel(m)
if devs, err := m.sdb.ListDevicesForFolder("default"); err != nil || len(devs) != 1 {
+1 -1
View File
@@ -250,7 +250,7 @@ func (*alwaysChanged) Changed() bool {
func folderIgnoresAlwaysReload(t testing.TB, m *testModel, fcfg config.FolderConfiguration) {
t.Helper()
m.removeFolder(fcfg)
ignores := ignore.New(fcfg.Filesystem(), ignore.WithCache(true), ignore.WithChangeDetector(newAlwaysChanged()))
ignores := ignore.New(fcfg.Filesystem(), ignore.WithChangeDetector(newAlwaysChanged()))
m.mut.Lock()
m.addAndStartFolderLockedWithIgnores(fcfg, ignores)
m.mut.Unlock()
+3 -3
View File
@@ -749,7 +749,7 @@ func TestRecurseInclude(t *testing.T) {
*
`
testFs := newTestFs()
ignores := ignore.New(testFs, ignore.WithCache(true))
ignores := ignore.New(testFs)
if err := ignores.Parse(bytes.NewBufferString(stignore), ".stignore"); err != nil {
t.Fatal(err)
}
@@ -859,7 +859,7 @@ func TestSkipIgnoredDirs(t *testing.T) {
w := &walker{}
pats := ignore.New(fss, ignore.WithCache(true))
pats := ignore.New(fss)
stignore := `
/foo/ign*
@@ -892,7 +892,7 @@ func TestIncludedSubdir(t *testing.T) {
t.Fatal(err)
}
pats := ignore.New(fss, ignore.WithCache(true))
pats := ignore.New(fss)
stignore := `
!/foo/bar
-1
View File
@@ -91,7 +91,6 @@ type Report struct {
NATType string `json:"natType,omitempty" metric:"nat_detection,gaugeVec:type" since:"3"`
AlwaysLocalNets bool `json:"alwaysLocalNets,omitempty" metric:"feature_count{feature=AlwaysLocalNets},gauge" since:"3"`
CacheIgnoredFiles bool `json:"cacheIgnoredFiles,omitempty" metric:"feature_count{feature=CacheIgnoredFiles},gauge" since:"3"`
OverwriteRemoteDeviceNames bool `json:"overwriteRemoteDeviceNames,omitempty" metric:"feature_count{feature=OverwriteRemoteDeviceNames},gauge" since:"3"`
ProgressEmitterEnabled bool `json:"progressEmitterEnabled,omitempty" metric:"feature_count{feature=ProgressEmitterEnabled},gauge" since:"3"`
CustomDefaultFolderPath bool `json:"customDefaultFolderPath,omitempty" metric:"feature_count{feature=CustomDefaultFolderPath},gauge" since:"3"`
-1
View File
@@ -217,7 +217,6 @@ func (s *Service) reportData(ctx context.Context, urVersion int, preview bool) (
report.Uptime = s.UptimeS()
report.NATType = s.connectionsService.NATType()
report.AlwaysLocalNets = len(opts.AlwaysLocalNets) > 0
report.CacheIgnoredFiles = opts.CacheIgnoredFiles
report.OverwriteRemoteDeviceNames = opts.OverwriteRemoteDevNames
report.ProgressEmitterEnabled = opts.ProgressUpdateIntervalS > -1
report.CustomDefaultFolderPath = defaultFolder.Path != "~"
-1
View File
@@ -101,7 +101,6 @@
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
<upgradeToPreReleases>false</upgradeToPreReleases>
<keepTemporariesH>24</keepTemporariesH>
<cacheIgnoredFiles>false</cacheIgnoredFiles>
<progressUpdateIntervalS>5</progressUpdateIntervalS>
<limitBandwidthInLan>false</limitBandwidthInLan>
<minHomeDiskFree unit="%">1</minHomeDiskFree>
-1
View File
@@ -99,7 +99,6 @@
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
<upgradeToPreReleases>false</upgradeToPreReleases>
<keepTemporariesH>24</keepTemporariesH>
<cacheIgnoredFiles>false</cacheIgnoredFiles>
<progressUpdateIntervalS>5</progressUpdateIntervalS>
<limitBandwidthInLan>true</limitBandwidthInLan>
<minHomeDiskFree unit="%">1</minHomeDiskFree>
-1
View File
@@ -117,7 +117,6 @@
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
<upgradeToPreReleases>false</upgradeToPreReleases>
<keepTemporariesH>24</keepTemporariesH>
<cacheIgnoredFiles>false</cacheIgnoredFiles>
<progressUpdateIntervalS>5</progressUpdateIntervalS>
<limitBandwidthInLan>false</limitBandwidthInLan>
<minHomeDiskFree unit="%">1</minHomeDiskFree>
-1
View File
@@ -69,7 +69,6 @@
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
<upgradeToPreReleases>false</upgradeToPreReleases>
<keepTemporariesH>24</keepTemporariesH>
<cacheIgnoredFiles>false</cacheIgnoredFiles>
<progressUpdateIntervalS>5</progressUpdateIntervalS>
<limitBandwidthInLan>false</limitBandwidthInLan>
<minHomeDiskFree unit="%">1</minHomeDiskFree>