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:
Vendored
-1
@@ -116,7 +116,6 @@
|
|||||||
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
|
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
|
||||||
<upgradeToPreReleases>false</upgradeToPreReleases>
|
<upgradeToPreReleases>false</upgradeToPreReleases>
|
||||||
<keepTemporariesH>24</keepTemporariesH>
|
<keepTemporariesH>24</keepTemporariesH>
|
||||||
<cacheIgnoredFiles>false</cacheIgnoredFiles>
|
|
||||||
<progressUpdateIntervalS>5</progressUpdateIntervalS>
|
<progressUpdateIntervalS>5</progressUpdateIntervalS>
|
||||||
<limitBandwidthInLan>false</limitBandwidthInLan>
|
<limitBandwidthInLan>false</limitBandwidthInLan>
|
||||||
<minHomeDiskFree unit="%">1</minHomeDiskFree>
|
<minHomeDiskFree unit="%">1</minHomeDiskFree>
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ func TestDefaultValues(t *testing.T) {
|
|||||||
NATTimeoutS: 10,
|
NATTimeoutS: 10,
|
||||||
AutoUpgradeIntervalH: 12,
|
AutoUpgradeIntervalH: 12,
|
||||||
KeepTemporariesH: 24,
|
KeepTemporariesH: 24,
|
||||||
CacheIgnoredFiles: false,
|
|
||||||
ProgressUpdateIntervalS: 5,
|
ProgressUpdateIntervalS: 5,
|
||||||
LimitBandwidthInLan: false,
|
LimitBandwidthInLan: false,
|
||||||
MinHomeDiskFree: Size{1, "%"},
|
MinHomeDiskFree: Size{1, "%"},
|
||||||
@@ -278,7 +277,6 @@ func TestOverriddenValues(t *testing.T) {
|
|||||||
NATTimeoutS: 15,
|
NATTimeoutS: 15,
|
||||||
AutoUpgradeIntervalH: 24,
|
AutoUpgradeIntervalH: 24,
|
||||||
KeepTemporariesH: 48,
|
KeepTemporariesH: 48,
|
||||||
CacheIgnoredFiles: true,
|
|
||||||
ProgressUpdateIntervalS: 10,
|
ProgressUpdateIntervalS: 10,
|
||||||
LimitBandwidthInLan: true,
|
LimitBandwidthInLan: true,
|
||||||
MinHomeDiskFree: Size{5.2, "%"},
|
MinHomeDiskFree: Size{5.2, "%"},
|
||||||
|
|||||||
@@ -320,10 +320,6 @@ func migrateToConfigV15(cfg *Configuration) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func migrateToConfigV14(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
|
// Migrate UPnP -> NAT options
|
||||||
cfg.Options.NATEnabled = cfg.Options.DeprecatedUPnPEnabled
|
cfg.Options.NATEnabled = cfg.Options.DeprecatedUPnPEnabled
|
||||||
cfg.Options.DeprecatedUPnPEnabled = false
|
cfg.Options.DeprecatedUPnPEnabled = false
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ type OptionsConfiguration struct {
|
|||||||
AutoUpgradeIntervalH int `json:"autoUpgradeIntervalH" xml:"autoUpgradeIntervalH" default:"12"`
|
AutoUpgradeIntervalH int `json:"autoUpgradeIntervalH" xml:"autoUpgradeIntervalH" default:"12"`
|
||||||
UpgradeToPreReleases bool `json:"upgradeToPreReleases" xml:"upgradeToPreReleases"`
|
UpgradeToPreReleases bool `json:"upgradeToPreReleases" xml:"upgradeToPreReleases"`
|
||||||
KeepTemporariesH int `json:"keepTemporariesH" xml:"keepTemporariesH" default:"24"`
|
KeepTemporariesH int `json:"keepTemporariesH" xml:"keepTemporariesH" default:"24"`
|
||||||
CacheIgnoredFiles bool `json:"cacheIgnoredFiles" xml:"cacheIgnoredFiles" default:"false"`
|
|
||||||
ProgressUpdateIntervalS int `json:"progressUpdateIntervalS" xml:"progressUpdateIntervalS" default:"5"`
|
ProgressUpdateIntervalS int `json:"progressUpdateIntervalS" xml:"progressUpdateIntervalS" default:"5"`
|
||||||
LimitBandwidthInLan bool `json:"limitBandwidthInLan" xml:"limitBandwidthInLan" default:"false"`
|
LimitBandwidthInLan bool `json:"limitBandwidthInLan" xml:"limitBandwidthInLan" default:"false"`
|
||||||
MinHomeDiskFree Size `json:"minHomeDiskFree" xml:"minHomeDiskFree" default:"1 %"`
|
MinHomeDiskFree Size `json:"minHomeDiskFree" xml:"minHomeDiskFree" default:"1 %"`
|
||||||
|
|||||||
Vendored
-1
@@ -42,7 +42,6 @@
|
|||||||
<restartOnWakeup>true</restartOnWakeup>
|
<restartOnWakeup>true</restartOnWakeup>
|
||||||
<autoUpgradeIntervalH>0</autoUpgradeIntervalH>
|
<autoUpgradeIntervalH>0</autoUpgradeIntervalH>
|
||||||
<keepTemporariesH>24</keepTemporariesH>
|
<keepTemporariesH>24</keepTemporariesH>
|
||||||
<cacheIgnoredFiles>true</cacheIgnoredFiles>
|
|
||||||
<progressUpdateIntervalS>5</progressUpdateIntervalS>
|
<progressUpdateIntervalS>5</progressUpdateIntervalS>
|
||||||
<symlinksEnabled>true</symlinksEnabled>
|
<symlinksEnabled>true</symlinksEnabled>
|
||||||
<limitBandwidthInLan>false</limitBandwidthInLan>
|
<limitBandwidthInLan>false</limitBandwidthInLan>
|
||||||
|
|||||||
-1
@@ -22,7 +22,6 @@
|
|||||||
<restartOnWakeup>false</restartOnWakeup>
|
<restartOnWakeup>false</restartOnWakeup>
|
||||||
<autoUpgradeIntervalH>24</autoUpgradeIntervalH>
|
<autoUpgradeIntervalH>24</autoUpgradeIntervalH>
|
||||||
<keepTemporariesH>48</keepTemporariesH>
|
<keepTemporariesH>48</keepTemporariesH>
|
||||||
<cacheIgnoredFiles>true</cacheIgnoredFiles>
|
|
||||||
<progressUpdateIntervalS>10</progressUpdateIntervalS>
|
<progressUpdateIntervalS>10</progressUpdateIntervalS>
|
||||||
<symlinksEnabled>false</symlinksEnabled>
|
<symlinksEnabled>false</symlinksEnabled>
|
||||||
<limitBandwidthInLan>true</limitBandwidthInLan>
|
<limitBandwidthInLan>true</limitBandwidthInLan>
|
||||||
|
|||||||
@@ -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()
|
|
||||||
}
|
|
||||||
@@ -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
@@ -124,10 +124,7 @@ type Matcher struct {
|
|||||||
fs fs.Filesystem
|
fs fs.Filesystem
|
||||||
lines []string // exact lines read from .stignore
|
lines []string // exact lines read from .stignore
|
||||||
patterns []Pattern // patterns including those from included files
|
patterns []Pattern // patterns including those from included files
|
||||||
withCache bool
|
|
||||||
matches *cache
|
|
||||||
curHash string
|
curHash string
|
||||||
stop chan struct{}
|
|
||||||
changeDetector ChangeDetector
|
changeDetector ChangeDetector
|
||||||
mut sync.Mutex
|
mut sync.Mutex
|
||||||
}
|
}
|
||||||
@@ -135,13 +132,6 @@ type Matcher struct {
|
|||||||
// An Option can be passed to New()
|
// An Option can be passed to New()
|
||||||
type Option func(*Matcher)
|
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
|
// WithChangeDetector sets a custom ChangeDetector. The default is to simply
|
||||||
// use the on disk modtime for comparison.
|
// use the on disk modtime for comparison.
|
||||||
func WithChangeDetector(cd ChangeDetector) Option {
|
func WithChangeDetector(cd ChangeDetector) Option {
|
||||||
@@ -152,8 +142,7 @@ func WithChangeDetector(cd ChangeDetector) Option {
|
|||||||
|
|
||||||
func New(fs fs.Filesystem, opts ...Option) *Matcher {
|
func New(fs fs.Filesystem, opts ...Option) *Matcher {
|
||||||
m := &Matcher{
|
m := &Matcher{
|
||||||
fs: fs,
|
fs: fs,
|
||||||
stop: make(chan struct{}),
|
|
||||||
}
|
}
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(m)
|
opt(m)
|
||||||
@@ -161,9 +150,6 @@ func New(fs fs.Filesystem, opts ...Option) *Matcher {
|
|||||||
if m.changeDetector == nil {
|
if m.changeDetector == nil {
|
||||||
m.changeDetector = newModtimeChecker()
|
m.changeDetector = newModtimeChecker()
|
||||||
}
|
}
|
||||||
if m.withCache {
|
|
||||||
go m.clean(2 * time.Hour)
|
|
||||||
}
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,9 +205,6 @@ func (m *Matcher) parseLocked(r io.Reader, file string) error {
|
|||||||
|
|
||||||
m.curHash = newHash
|
m.curHash = newHash
|
||||||
m.patterns = patterns
|
m.patterns = patterns
|
||||||
if m.withCache {
|
|
||||||
m.matches = newCache()
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
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
|
// 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
|
// 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.
|
// 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 {
|
switch {
|
||||||
case fs.IsTemporary(file):
|
case fs.IsTemporary(file):
|
||||||
return ignoreresult.IgnoreAndSkip
|
return ignoreresult.IgnoreAndSkip
|
||||||
@@ -254,19 +237,6 @@ func (m *Matcher) Match(file string) (result ignoreresult.R) {
|
|||||||
// Change backslashes to slashes (on Windows only)
|
// Change backslashes to slashes (on Windows only)
|
||||||
file = filepath.ToSlash(file)
|
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
|
// 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
|
// allow skipping matched directories or not. As soon as we hit an
|
||||||
// exclude pattern (with some exceptions), we can't skip directories
|
// exclude pattern (with some exceptions), we can't skip directories
|
||||||
@@ -327,27 +297,6 @@ func (m *Matcher) Hash() string {
|
|||||||
return m.curHash
|
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 {
|
func hashPatterns(patterns []Pattern) string {
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
for _, pat := range patterns {
|
for _, pat := range patterns {
|
||||||
|
|||||||
+33
-206
@@ -52,7 +52,7 @@ func newTestFS() fs.Filesystem {
|
|||||||
func TestIgnore(t *testing.T) {
|
func TestIgnore(t *testing.T) {
|
||||||
testFs := newTestFS()
|
testFs := newTestFS()
|
||||||
|
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
err := pats.Load(".stignore")
|
err := pats.Load(".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -104,7 +104,7 @@ func TestExcludes(t *testing.T) {
|
|||||||
i*2
|
i*2
|
||||||
!ign2
|
!ign2
|
||||||
`
|
`
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -151,7 +151,7 @@ func TestFlagOrder(t *testing.T) {
|
|||||||
(?i)(?d)(?d)!ign9
|
(?i)(?d)(?d)!ign9
|
||||||
(?d)(?d)!ign10
|
(?d)(?d)!ign10
|
||||||
`
|
`
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -188,7 +188,7 @@ func TestDeletables(t *testing.T) {
|
|||||||
ign7
|
ign7
|
||||||
(?i)ign8
|
(?i)ign8
|
||||||
`
|
`
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -229,7 +229,7 @@ func TestBadPatterns(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, pat := range badPatterns {
|
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 {
|
if err == nil {
|
||||||
t.Errorf("No error for pattern %q", pat)
|
t.Errorf("No error for pattern %q", pat)
|
||||||
}
|
}
|
||||||
@@ -247,7 +247,7 @@ func TestBadPatterns(t *testing.T) {
|
|||||||
func TestCaseSensitivity(t *testing.T) {
|
func TestCaseSensitivity(t *testing.T) {
|
||||||
testFs := newTestFS()
|
testFs := newTestFS()
|
||||||
|
|
||||||
ign := New(testFs, WithCache(true))
|
ign := New(testFs)
|
||||||
err := ign.Parse(bytes.NewBufferString("test"), ".stignore")
|
err := ign.Parse(bytes.NewBufferString("test"), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
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) {
|
func TestCommentsAndBlankLines(t *testing.T) {
|
||||||
testFs := newTestFS()
|
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")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
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) {
|
func TestCacheReload(t *testing.T) {
|
||||||
fs := fs.NewFilesystem(fs.FilesystemTypeFake, rand.String(32)+"?content=true")
|
fs := fs.NewFilesystem(fs.FilesystemTypeFake, rand.String(32)+"?content=true")
|
||||||
|
|
||||||
@@ -522,7 +349,7 @@ func TestCacheReload(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pats := New(fs, WithCache(true))
|
pats := New(fs)
|
||||||
err = pats.Load(fd.Name())
|
err = pats.Load(fd.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -579,7 +406,7 @@ func TestCacheReload(t *testing.T) {
|
|||||||
func TestHash(t *testing.T) {
|
func TestHash(t *testing.T) {
|
||||||
testFs := newTestFS()
|
testFs := newTestFS()
|
||||||
|
|
||||||
p1 := New(testFs, WithCache(true))
|
p1 := New(testFs)
|
||||||
err := p1.Load(".stignore")
|
err := p1.Load(".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -595,7 +422,7 @@ func TestHash(t *testing.T) {
|
|||||||
/ffile
|
/ffile
|
||||||
lost+found
|
lost+found
|
||||||
`
|
`
|
||||||
p2 := New(testFs, WithCache(true))
|
p2 := New(testFs)
|
||||||
err = p2.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err = p2.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -610,7 +437,7 @@ func TestHash(t *testing.T) {
|
|||||||
/ffile
|
/ffile
|
||||||
lost+found
|
lost+found
|
||||||
`
|
`
|
||||||
p3 := New(testFs, WithCache(true))
|
p3 := New(testFs)
|
||||||
err = p3.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err = p3.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -636,7 +463,7 @@ func TestHash(t *testing.T) {
|
|||||||
func TestHashOfEmpty(t *testing.T) {
|
func TestHashOfEmpty(t *testing.T) {
|
||||||
testFs := newTestFS()
|
testFs := newTestFS()
|
||||||
|
|
||||||
p1 := New(testFs, WithCache(true))
|
p1 := New(testFs)
|
||||||
|
|
||||||
err := p1.Load(".stignore")
|
err := p1.Load(".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -678,7 +505,7 @@ func TestWindowsPatterns(t *testing.T) {
|
|||||||
a/b
|
a/b
|
||||||
c\d
|
c\d
|
||||||
`
|
`
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -706,7 +533,7 @@ func TestAutomaticCaseInsensitivity(t *testing.T) {
|
|||||||
A/B
|
A/B
|
||||||
c/d
|
c/d
|
||||||
`
|
`
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -728,7 +555,7 @@ func TestCommas(t *testing.T) {
|
|||||||
foo,bar.txt
|
foo,bar.txt
|
||||||
{baz,quux}.txt
|
{baz,quux}.txt
|
||||||
`
|
`
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -762,7 +589,7 @@ func TestIssue3164(t *testing.T) {
|
|||||||
(?d)(?i)/foo
|
(?d)(?i)/foo
|
||||||
(?d)(?i)**/bar
|
(?d)(?i)**/bar
|
||||||
`
|
`
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -801,7 +628,7 @@ func TestIssue3174(t *testing.T) {
|
|||||||
stignore := `
|
stignore := `
|
||||||
*ä*
|
*ä*
|
||||||
`
|
`
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -822,7 +649,7 @@ func TestIssue3639(t *testing.T) {
|
|||||||
stignore := `
|
stignore := `
|
||||||
foo/
|
foo/
|
||||||
`
|
`
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -858,7 +685,7 @@ func TestIssue3674(t *testing.T) {
|
|||||||
{"as/dc", true},
|
{"as/dc", true},
|
||||||
}
|
}
|
||||||
|
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -893,7 +720,7 @@ func TestGobwasGlobIssue18(t *testing.T) {
|
|||||||
{"bbaa", false},
|
{"bbaa", false},
|
||||||
}
|
}
|
||||||
|
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -925,7 +752,7 @@ func TestRoot(t *testing.T) {
|
|||||||
{"b", true},
|
{"b", true},
|
||||||
}
|
}
|
||||||
|
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -951,7 +778,7 @@ func TestLines(t *testing.T) {
|
|||||||
!/a
|
!/a
|
||||||
`
|
`
|
||||||
|
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
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")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1025,7 +852,7 @@ func TestIssue4680(t *testing.T) {
|
|||||||
{"#snapshot/foo", true},
|
{"#snapshot/foo", true},
|
||||||
}
|
}
|
||||||
|
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1045,7 +872,7 @@ func TestIssue4689(t *testing.T) {
|
|||||||
|
|
||||||
stignore := `// orig`
|
stignore := `// orig`
|
||||||
|
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1076,7 +903,7 @@ func TestIssue4901(t *testing.T) {
|
|||||||
puppy
|
puppy
|
||||||
`
|
`
|
||||||
|
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
fd, err := pats.fs.Create(".stignore")
|
fd, err := pats.fs.Create(".stignore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1119,7 +946,7 @@ func TestIssue4901(t *testing.T) {
|
|||||||
func TestIssue5009(t *testing.T) {
|
func TestIssue5009(t *testing.T) {
|
||||||
testFs := newTestFS()
|
testFs := newTestFS()
|
||||||
|
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
stignore := `
|
stignore := `
|
||||||
ign1
|
ign1
|
||||||
@@ -1152,7 +979,7 @@ func TestIssue5009(t *testing.T) {
|
|||||||
func TestSpecialChars(t *testing.T) {
|
func TestSpecialChars(t *testing.T) {
|
||||||
testFs := newTestFS()
|
testFs := newTestFS()
|
||||||
|
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
stignore := `(?i)/#recycle
|
stignore := `(?i)/#recycle
|
||||||
(?i)/#nosync
|
(?i)/#nosync
|
||||||
@@ -1179,7 +1006,7 @@ func TestSpecialChars(t *testing.T) {
|
|||||||
func TestIntlWildcards(t *testing.T) {
|
func TestIntlWildcards(t *testing.T) {
|
||||||
testFs := newTestFS()
|
testFs := newTestFS()
|
||||||
|
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
stignore := `1000春
|
stignore := `1000春
|
||||||
200?春
|
200?春
|
||||||
@@ -1208,7 +1035,7 @@ func TestPartialIncludeLine(t *testing.T) {
|
|||||||
|
|
||||||
// Loading a partial #include line (no file mentioned) should error but not crash.
|
// Loading a partial #include line (no file mentioned) should error but not crash.
|
||||||
|
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
cases := []string{
|
cases := []string{
|
||||||
"#include",
|
"#include",
|
||||||
@@ -1267,7 +1094,7 @@ func TestSkipIgnoredDirs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pats := New(testFs, WithCache(true))
|
pats := New(testFs)
|
||||||
|
|
||||||
stignore := `
|
stignore := `
|
||||||
/foo/ign*
|
/foo/ign*
|
||||||
@@ -1711,7 +1538,7 @@ func testEscape(t *testing.T, tests []escapeTest, noErrors bool) {
|
|||||||
for name, content := range testEscapeFiles {
|
for name, content := range testEscapeFiles {
|
||||||
fs.WriteFile(testFS, name, []byte(content), 0o666)
|
fs.WriteFile(testFS, name, []byte(content), 0o666)
|
||||||
}
|
}
|
||||||
pats := New(testFS, WithCache(true))
|
pats := New(testFS)
|
||||||
|
|
||||||
err := pats.Parse(bytes.NewBufferString(test.pattern), ".stignore")
|
err := pats.Parse(bytes.NewBufferString(test.pattern), ".stignore")
|
||||||
if noErrors {
|
if noErrors {
|
||||||
@@ -1753,7 +1580,7 @@ func TestIgnoreThroughSymlink(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pats := New(testFS, WithCache(true))
|
pats := New(testFS)
|
||||||
if err := pats.Load(".stignore"); err != nil {
|
if err := pats.Load(".stignore"); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -300,7 +300,7 @@ func (m *model) initFolders(cfg config.Configuration) error {
|
|||||||
folderCfg.CreateRoot()
|
folderCfg.CreateRoot()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
err := m.newFolder(folderCfg, cfg.Options.CacheIgnoredFiles)
|
err := m.newFolder(folderCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -335,8 +335,8 @@ func (m *model) fatal(err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Need to hold lock on m.mut when calling this.
|
// Need to hold lock on m.mut when calling this.
|
||||||
func (m *model) addAndStartFolderLocked(cfg config.FolderConfiguration, cacheIgnoredFiles bool) {
|
func (m *model) addAndStartFolderLocked(cfg config.FolderConfiguration) {
|
||||||
ignores := ignore.New(cfg.Filesystem(), ignore.WithCache(cacheIgnoredFiles))
|
ignores := ignore.New(cfg.Filesystem())
|
||||||
if cfg.Type != config.FolderTypeReceiveEncrypted {
|
if cfg.Type != config.FolderTypeReceiveEncrypted {
|
||||||
if err := ignores.Load(".stignore"); err != nil && !fs.IsNotExist(err) {
|
if err := ignores.Load(".stignore"); err != nil && !fs.IsNotExist(err) {
|
||||||
slog.Error("Failed to load ignores", slogutil.Error(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)
|
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 == "" {
|
if to.ID == "" {
|
||||||
panic("bug: cannot restart empty folder ID")
|
panic("bug: cannot restart empty folder ID")
|
||||||
}
|
}
|
||||||
@@ -539,7 +539,7 @@ func (m *model) restartFolder(from, to config.FolderConfiguration, cacheIgnoredF
|
|||||||
|
|
||||||
m.cleanupFolderLocked(from)
|
m.cleanupFolderLocked(from)
|
||||||
if !to.Paused {
|
if !to.Paused {
|
||||||
m.addAndStartFolderLocked(to, cacheIgnoredFiles)
|
m.addAndStartFolderLocked(to)
|
||||||
}
|
}
|
||||||
|
|
||||||
runner, _ := m.folderRunners.Get(to.ID)
|
runner, _ := m.folderRunners.Get(to.ID)
|
||||||
@@ -560,11 +560,11 @@ func (m *model) restartFolder(from, to config.FolderConfiguration, cacheIgnoredF
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *model) newFolder(cfg config.FolderConfiguration, cacheIgnoredFiles bool) error {
|
func (m *model) newFolder(cfg config.FolderConfiguration) error {
|
||||||
m.mut.Lock()
|
m.mut.Lock()
|
||||||
defer m.mut.Unlock()
|
defer m.mut.Unlock()
|
||||||
|
|
||||||
m.addAndStartFolderLocked(cfg, cacheIgnoredFiles)
|
m.addAndStartFolderLocked(cfg)
|
||||||
|
|
||||||
// Cluster configs might be received and processed before reaching this
|
// Cluster configs might be received and processed before reaching this
|
||||||
// point, i.e. before the folder is started. If that's the case, start
|
// 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())
|
slog.Info("Paused folder", cfg.LogAttr())
|
||||||
} else {
|
} else {
|
||||||
slog.Info("Adding folder", cfg.LogAttr())
|
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)
|
m.fatal(err)
|
||||||
return true
|
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.
|
// This folder exists on both sides. Settings might have changed.
|
||||||
// Check if anything differs that requires a restart.
|
// Check if anything differs that requires a restart.
|
||||||
if !reflect.DeepEqual(fromCfg.RequiresRestartOnly(), toCfg.RequiresRestartOnly()) || from.Options.CacheIgnoredFiles != to.Options.CacheIgnoredFiles {
|
if !reflect.DeepEqual(fromCfg.RequiresRestartOnly(), toCfg.RequiresRestartOnly()) {
|
||||||
if err := m.restartFolder(fromCfg, toCfg, to.Options.CacheIgnoredFiles); err != nil {
|
if err := m.restartFolder(fromCfg, toCfg); err != nil {
|
||||||
m.fatal(err)
|
m.fatal(err)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1603,7 +1603,7 @@ func TestIgnores(t *testing.T) {
|
|||||||
ID: "fresh", Path: "XXX",
|
ID: "fresh", Path: "XXX",
|
||||||
FilesystemType: config.FilesystemTypeFake,
|
FilesystemType: config.FilesystemTypeFake,
|
||||||
}
|
}
|
||||||
ignores := ignore.New(fcfg.Filesystem(), ignore.WithCache(m.cfg.Options().CacheIgnoredFiles))
|
ignores := ignore.New(fcfg.Filesystem())
|
||||||
m.mut.Lock()
|
m.mut.Lock()
|
||||||
m.folderCfgs[fcfg.ID] = fcfg
|
m.folderCfgs[fcfg.ID] = fcfg
|
||||||
m.folderIgnores[fcfg.ID] = ignores
|
m.folderIgnores[fcfg.ID] = ignores
|
||||||
@@ -1618,7 +1618,7 @@ func TestIgnores(t *testing.T) {
|
|||||||
pausedDefaultFolderConfig := defaultFolderConfig
|
pausedDefaultFolderConfig := defaultFolderConfig
|
||||||
pausedDefaultFolderConfig.Paused = true
|
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
|
// 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.
|
// 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")
|
t.Error("expected two devices")
|
||||||
}
|
}
|
||||||
|
|
||||||
m.newFolder(defaultFolderConfig, false)
|
m.newFolder(defaultFolderConfig)
|
||||||
defer cleanupModel(m)
|
defer cleanupModel(m)
|
||||||
|
|
||||||
if devs, err := m.sdb.ListDevicesForFolder("default"); err != nil || len(devs) != 1 {
|
if devs, err := m.sdb.ListDevicesForFolder("default"); err != nil || len(devs) != 1 {
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ func (*alwaysChanged) Changed() bool {
|
|||||||
func folderIgnoresAlwaysReload(t testing.TB, m *testModel, fcfg config.FolderConfiguration) {
|
func folderIgnoresAlwaysReload(t testing.TB, m *testModel, fcfg config.FolderConfiguration) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
m.removeFolder(fcfg)
|
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.mut.Lock()
|
||||||
m.addAndStartFolderLockedWithIgnores(fcfg, ignores)
|
m.addAndStartFolderLockedWithIgnores(fcfg, ignores)
|
||||||
m.mut.Unlock()
|
m.mut.Unlock()
|
||||||
|
|||||||
@@ -749,7 +749,7 @@ func TestRecurseInclude(t *testing.T) {
|
|||||||
*
|
*
|
||||||
`
|
`
|
||||||
testFs := newTestFs()
|
testFs := newTestFs()
|
||||||
ignores := ignore.New(testFs, ignore.WithCache(true))
|
ignores := ignore.New(testFs)
|
||||||
if err := ignores.Parse(bytes.NewBufferString(stignore), ".stignore"); err != nil {
|
if err := ignores.Parse(bytes.NewBufferString(stignore), ".stignore"); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -859,7 +859,7 @@ func TestSkipIgnoredDirs(t *testing.T) {
|
|||||||
|
|
||||||
w := &walker{}
|
w := &walker{}
|
||||||
|
|
||||||
pats := ignore.New(fss, ignore.WithCache(true))
|
pats := ignore.New(fss)
|
||||||
|
|
||||||
stignore := `
|
stignore := `
|
||||||
/foo/ign*
|
/foo/ign*
|
||||||
@@ -892,7 +892,7 @@ func TestIncludedSubdir(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pats := ignore.New(fss, ignore.WithCache(true))
|
pats := ignore.New(fss)
|
||||||
|
|
||||||
stignore := `
|
stignore := `
|
||||||
!/foo/bar
|
!/foo/bar
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ type Report struct {
|
|||||||
NATType string `json:"natType,omitempty" metric:"nat_detection,gaugeVec:type" since:"3"`
|
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"`
|
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"`
|
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"`
|
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"`
|
CustomDefaultFolderPath bool `json:"customDefaultFolderPath,omitempty" metric:"feature_count{feature=CustomDefaultFolderPath},gauge" since:"3"`
|
||||||
|
|||||||
@@ -217,7 +217,6 @@ func (s *Service) reportData(ctx context.Context, urVersion int, preview bool) (
|
|||||||
report.Uptime = s.UptimeS()
|
report.Uptime = s.UptimeS()
|
||||||
report.NATType = s.connectionsService.NATType()
|
report.NATType = s.connectionsService.NATType()
|
||||||
report.AlwaysLocalNets = len(opts.AlwaysLocalNets) > 0
|
report.AlwaysLocalNets = len(opts.AlwaysLocalNets) > 0
|
||||||
report.CacheIgnoredFiles = opts.CacheIgnoredFiles
|
|
||||||
report.OverwriteRemoteDeviceNames = opts.OverwriteRemoteDevNames
|
report.OverwriteRemoteDeviceNames = opts.OverwriteRemoteDevNames
|
||||||
report.ProgressEmitterEnabled = opts.ProgressUpdateIntervalS > -1
|
report.ProgressEmitterEnabled = opts.ProgressUpdateIntervalS > -1
|
||||||
report.CustomDefaultFolderPath = defaultFolder.Path != "~"
|
report.CustomDefaultFolderPath = defaultFolder.Path != "~"
|
||||||
|
|||||||
@@ -101,7 +101,6 @@
|
|||||||
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
|
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
|
||||||
<upgradeToPreReleases>false</upgradeToPreReleases>
|
<upgradeToPreReleases>false</upgradeToPreReleases>
|
||||||
<keepTemporariesH>24</keepTemporariesH>
|
<keepTemporariesH>24</keepTemporariesH>
|
||||||
<cacheIgnoredFiles>false</cacheIgnoredFiles>
|
|
||||||
<progressUpdateIntervalS>5</progressUpdateIntervalS>
|
<progressUpdateIntervalS>5</progressUpdateIntervalS>
|
||||||
<limitBandwidthInLan>false</limitBandwidthInLan>
|
<limitBandwidthInLan>false</limitBandwidthInLan>
|
||||||
<minHomeDiskFree unit="%">1</minHomeDiskFree>
|
<minHomeDiskFree unit="%">1</minHomeDiskFree>
|
||||||
|
|||||||
@@ -99,7 +99,6 @@
|
|||||||
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
|
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
|
||||||
<upgradeToPreReleases>false</upgradeToPreReleases>
|
<upgradeToPreReleases>false</upgradeToPreReleases>
|
||||||
<keepTemporariesH>24</keepTemporariesH>
|
<keepTemporariesH>24</keepTemporariesH>
|
||||||
<cacheIgnoredFiles>false</cacheIgnoredFiles>
|
|
||||||
<progressUpdateIntervalS>5</progressUpdateIntervalS>
|
<progressUpdateIntervalS>5</progressUpdateIntervalS>
|
||||||
<limitBandwidthInLan>true</limitBandwidthInLan>
|
<limitBandwidthInLan>true</limitBandwidthInLan>
|
||||||
<minHomeDiskFree unit="%">1</minHomeDiskFree>
|
<minHomeDiskFree unit="%">1</minHomeDiskFree>
|
||||||
|
|||||||
@@ -117,7 +117,6 @@
|
|||||||
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
|
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
|
||||||
<upgradeToPreReleases>false</upgradeToPreReleases>
|
<upgradeToPreReleases>false</upgradeToPreReleases>
|
||||||
<keepTemporariesH>24</keepTemporariesH>
|
<keepTemporariesH>24</keepTemporariesH>
|
||||||
<cacheIgnoredFiles>false</cacheIgnoredFiles>
|
|
||||||
<progressUpdateIntervalS>5</progressUpdateIntervalS>
|
<progressUpdateIntervalS>5</progressUpdateIntervalS>
|
||||||
<limitBandwidthInLan>false</limitBandwidthInLan>
|
<limitBandwidthInLan>false</limitBandwidthInLan>
|
||||||
<minHomeDiskFree unit="%">1</minHomeDiskFree>
|
<minHomeDiskFree unit="%">1</minHomeDiskFree>
|
||||||
|
|||||||
@@ -69,7 +69,6 @@
|
|||||||
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
|
<autoUpgradeIntervalH>12</autoUpgradeIntervalH>
|
||||||
<upgradeToPreReleases>false</upgradeToPreReleases>
|
<upgradeToPreReleases>false</upgradeToPreReleases>
|
||||||
<keepTemporariesH>24</keepTemporariesH>
|
<keepTemporariesH>24</keepTemporariesH>
|
||||||
<cacheIgnoredFiles>false</cacheIgnoredFiles>
|
|
||||||
<progressUpdateIntervalS>5</progressUpdateIntervalS>
|
<progressUpdateIntervalS>5</progressUpdateIntervalS>
|
||||||
<limitBandwidthInLan>false</limitBandwidthInLan>
|
<limitBandwidthInLan>false</limitBandwidthInLan>
|
||||||
<minHomeDiskFree unit="%">1</minHomeDiskFree>
|
<minHomeDiskFree unit="%">1</minHomeDiskFree>
|
||||||
|
|||||||
Reference in New Issue
Block a user