lib/fs: Watch attrib. changes on inotify for mod. time (#7623)

* lib/fs: Watch attrib. changes on inotify for mod. time

* fix bsds (real) and darwin (test only)
This commit is contained in:
Simon Frei 2021-05-02 16:45:44 +02:00 committed by GitHub
parent ed9cb923fb
commit 75b58eb480
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 11 deletions

View File

@ -10,8 +10,9 @@ package fs
import "github.com/syncthing/notify" import "github.com/syncthing/notify"
// notify.InAttrib is not only required for permissions, but also mod. time changes
const ( const (
subEventMask = notify.InCreate | notify.InMovedTo | notify.InDelete | notify.InDeleteSelf | notify.InModify | notify.InMovedFrom | notify.InMoveSelf subEventMask = notify.InCreate | notify.InMovedTo | notify.InDelete | notify.InDeleteSelf | notify.InModify | notify.InMovedFrom | notify.InMoveSelf | notify.InAttrib
permEventMask = notify.InAttrib permEventMask = 0
rmEventMask = notify.InDelete | notify.InDeleteSelf | notify.InMovedFrom | notify.InMoveSelf rmEventMask = notify.InDelete | notify.InDeleteSelf | notify.InMovedFrom | notify.InMoveSelf
) )

View File

@ -13,7 +13,8 @@ import "github.com/syncthing/notify"
const ( const (
// Platform independent notify.Create is required, as kqueue does not have // Platform independent notify.Create is required, as kqueue does not have
// any event signalling file creation, but notify does generate those internally. // any event signalling file creation, but notify does generate those internally.
subEventMask = notify.NoteDelete | notify.NoteWrite | notify.NoteRename | notify.Create // NoteAttrib is not only required for permissions, but also mod. time changes
permEventMask = notify.NoteAttrib | notify.NoteExtend subEventMask = notify.NoteDelete | notify.NoteWrite | notify.NoteRename | notify.Create | notify.NoteAttrib | notify.NoteExtend
permEventMask = 0
rmEventMask = notify.NoteDelete | notify.NoteRename rmEventMask = notify.NoteDelete | notify.NoteRename
) )

View File

@ -87,7 +87,7 @@ func TestWatchIgnore(t *testing.T) {
{name, NonRemove}, {name, NonRemove},
} }
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{ignore: filepath.Join(name, ignored), skipIgnoredDirs: true}) testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{ignore: filepath.Join(name, ignored), skipIgnoredDirs: true}, false)
} }
func TestWatchInclude(t *testing.T) { func TestWatchInclude(t *testing.T) {
@ -114,7 +114,7 @@ func TestWatchInclude(t *testing.T) {
{name, NonRemove}, {name, NonRemove},
} }
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{ignore: filepath.Join(name, ignored), include: filepath.Join(name, included)}) testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{ignore: filepath.Join(name, ignored), include: filepath.Join(name, included)}, false)
} }
func TestWatchRename(t *testing.T) { func TestWatchRename(t *testing.T) {
@ -146,7 +146,7 @@ func TestWatchRename(t *testing.T) {
// set the "allow others" flag because we might get the create of // set the "allow others" flag because we might get the create of
// "oldfile" initially // "oldfile" initially
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{}) testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{}, false)
} }
// TestWatchWinRoot checks that a watch at a drive letter does not panic due to // TestWatchWinRoot checks that a watch at a drive letter does not panic due to
@ -308,7 +308,7 @@ func TestWatchOverflow(t *testing.T) {
} }
} }
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{}) testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{}, false)
} }
func TestWatchErrorLinuxInterpretation(t *testing.T) { func TestWatchErrorLinuxInterpretation(t *testing.T) {
@ -413,7 +413,39 @@ func TestWatchIssue4877(t *testing.T) {
testFs = origTestFs testFs = origTestFs
}() }()
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{}) testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{}, false)
}
func TestWatchModTime(t *testing.T) {
name := "modtime"
file := createTestFile(name, "foo")
path := filepath.Join(name, file)
now := time.Now()
before := now.Add(-10 * time.Second)
if err := testFs.Chtimes(path, before, before); err != nil {
t.Fatal(err)
}
testCase := func() {
if err := testFs.Chtimes(path, now, now); err != nil {
t.Error(err)
}
}
expectedEvents := []Event{
{file, NonRemove},
}
var allowedEvents []Event
// Apparently an event for the parent is also sent on mac
if runtime.GOOS == "darwin" {
allowedEvents = []Event{
{name, NonRemove},
}
}
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{}, true)
} }
// path relative to folder root, also creates parent dirs if necessary // path relative to folder root, also creates parent dirs if necessary
@ -442,7 +474,7 @@ func sleepMs(ms int) {
time.Sleep(time.Duration(ms) * time.Millisecond) time.Sleep(time.Duration(ms) * time.Millisecond)
} }
func testScenario(t *testing.T, name string, testCase func(), expectedEvents, allowedEvents []Event, fm fakeMatcher) { func testScenario(t *testing.T, name string, testCase func(), expectedEvents, allowedEvents []Event, fm fakeMatcher, ignorePerms bool) {
if err := testFs.MkdirAll(name, 0755); err != nil { if err := testFs.MkdirAll(name, 0755); err != nil {
panic(fmt.Sprintf("Failed to create directory %s: %s", name, err)) panic(fmt.Sprintf("Failed to create directory %s: %s", name, err))
} }
@ -451,7 +483,7 @@ func testScenario(t *testing.T, name string, testCase func(), expectedEvents, al
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
eventChan, errChan, err := testFs.Watch(name, fm, ctx, false) eventChan, errChan, err := testFs.Watch(name, fm, ctx, ignorePerms)
if err != nil { if err != nil {
panic(err) panic(err)
} }