소스 검색

Tweak impl for handling config renames

Svilen Markov 4 달 전
부모
커밋
27af0400c0
1개의 변경된 파일32개의 추가작업 그리고 25개의 파일을 삭제
  1. 32 25
      internal/glance/config.go

+ 32 - 25
internal/glance/config.go

@@ -242,7 +242,7 @@ func configFilesWatcher(
 	// needed for lastContents and lastIncludes because they get updated in multiple goroutines
 	mu := sync.Mutex{}
 
-	checkForContentChangesBeforeCallback := func() {
+	parseAndCompareBeforeCallback := func() {
 		currentContents, currentIncludes, err := parseYAMLIncludes(mainFilePath)
 		if err != nil {
 			onErr(fmt.Errorf("parsing main file contents for comparison: %w", err))
@@ -268,15 +268,22 @@ func configFilesWatcher(
 
 	const debounceDuration = 500 * time.Millisecond
 	var debounceTimer *time.Timer
-	debouncedCallback := func() {
+	debouncedParseAndCompareBeforeCallback := func() {
 		if debounceTimer != nil {
 			debounceTimer.Stop()
 			debounceTimer.Reset(debounceDuration)
 		} 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() {
 		for {
 			select {
@@ -285,33 +292,33 @@ func configFilesWatcher(
 					return
 				}
 				if event.Has(fsnotify.Write) {
-					debouncedCallback()
+					debouncedParseAndCompareBeforeCallback()
 				} else if event.Has(fsnotify.Rename) {
-					// wait for file to be available
-					for i := 0; i < 20; i++ {
-						_, err := os.Stat(mainFileAbsPath)
-						if err == nil {
+					// on linux the file will no longer be watched after a rename, on windows
+					// it will continue to be watched with the new name but we have no access to
+					// the new name in this event in order to stop watching it manually and match the
+					// behavior in linux, may lead to weird unintended behaviors on windows as we're
+					// only handling renames from linux's perspective
+					// see https://github.com/fsnotify/fsnotify/issues/255
+
+					// 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(100 * time.Millisecond)
-					}
-					// fsnotify removes the file from the watch list on rename events,
-					// add it back.
-					// See https://github.com/fsnotify/fsnotify/issues/214
-					err := watcher.Add(mainFileAbsPath)
-					if err != nil {
-						onErr(fmt.Errorf("watching file:", err))
+						time.Sleep(200 * time.Millisecond)
 					}
-					debouncedCallback()
+
+					debouncedParseAndCompareBeforeCallback()
 				} else if event.Has(fsnotify.Remove) {
-					func() {
-						mu.Lock()
-						defer mu.Unlock()
-						fileAbsPath, _ := filepath.Abs(event.Name)
-						delete(lastIncludes, fileAbsPath)
-					}()
-
-					debouncedCallback()
+					deleteLastInclude(event.Name)
+					debouncedParseAndCompareBeforeCallback()
 				}
 			case err, isOpen := <-watcher.Errors:
 				if !isOpen {