Merge pull request #358 from rubiojr/rubiojr/reload-on-rename2

Auto-reload config file on RENAME
This commit is contained in:
Svilen Markov 2025-02-19 01:25:08 +00:00 committed by GitHub
commit 16129c53bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -242,7 +242,7 @@ func configFilesWatcher(
// needed for lastContents and lastIncludes because they get updated in multiple goroutines // needed for lastContents and lastIncludes because they get updated in multiple goroutines
mu := sync.Mutex{} mu := sync.Mutex{}
checkForContentChangesBeforeCallback := func() { parseAndCompareBeforeCallback := func() {
currentContents, currentIncludes, err := parseYAMLIncludes(mainFilePath) currentContents, currentIncludes, err := parseYAMLIncludes(mainFilePath)
if err != nil { if err != nil {
onErr(fmt.Errorf("parsing main file contents for comparison: %w", err)) onErr(fmt.Errorf("parsing main file contents for comparison: %w", err))
@ -268,15 +268,22 @@ func configFilesWatcher(
const debounceDuration = 500 * time.Millisecond const debounceDuration = 500 * time.Millisecond
var debounceTimer *time.Timer var debounceTimer *time.Timer
debouncedCallback := func() { debouncedParseAndCompareBeforeCallback := func() {
if debounceTimer != nil { if debounceTimer != nil {
debounceTimer.Stop() debounceTimer.Stop()
debounceTimer.Reset(debounceDuration) debounceTimer.Reset(debounceDuration)
} else { } else {
debounceTimer = time.AfterFunc(debounceDuration, checkForContentChangesBeforeCallback) debounceTimer = time.AfterFunc(debounceDuration, parseAndCompareBeforeCallback)
} }
} }
deleteLastInclude := func(filePath string) {
mu.Lock()
defer mu.Unlock()
fileAbsPath, _ := filepath.Abs(filePath)
delete(lastIncludes, fileAbsPath)
}
go func() { go func() {
for { for {
select { select {
@ -285,16 +292,33 @@ func configFilesWatcher(
return return
} }
if event.Has(fsnotify.Write) { if event.Has(fsnotify.Write) {
debouncedCallback() debouncedParseAndCompareBeforeCallback()
} else if event.Has(fsnotify.Remove) { } else if event.Has(fsnotify.Rename) {
func() { // on linux the file will no longer be watched after a rename, on windows
mu.Lock() // it will continue to be watched with the new name but we have no access to
defer mu.Unlock() // the new name in this event in order to stop watching it manually and match the
fileAbsPath, _ := filepath.Abs(event.Name) // behavior in linux, may lead to weird unintended behaviors on windows as we're
delete(lastIncludes, fileAbsPath) // only handling renames from linux's perspective
}() // see https://github.com/fsnotify/fsnotify/issues/255
debouncedCallback() // remove the old file from our manually tracked includes, calling
// debouncedParseAndCompareBeforeCallback will re-add it if it's still
// required after it triggers
deleteLastInclude(event.Name)
// wait for file to maybe get created again
// see https://github.com/glanceapp/glance/pull/358
for i := 0; i < 10; i++ {
if _, err := os.Stat(event.Name); err == nil {
break
}
time.Sleep(200 * time.Millisecond)
}
debouncedParseAndCompareBeforeCallback()
} else if event.Has(fsnotify.Remove) {
deleteLastInclude(event.Name)
debouncedParseAndCompareBeforeCallback()
} }
case err, isOpen := <-watcher.Errors: case err, isOpen := <-watcher.Errors:
if !isOpen { if !isOpen {