diff --git a/scanner/change_detector.go b/scanner/change_detector.go index dde337fb2..159c7a446 100644 --- a/scanner/change_detector.go +++ b/scanner/change_detector.go @@ -9,22 +9,28 @@ import ( "github.com/cloudsonic/sonic-server/log" ) +type dirInfo struct { + mdate time.Time + maybe bool +} +type dirInfoMap map[string]dirInfo + type ChangeDetector struct { rootFolder string - dirMap map[string]time.Time + dirMap dirInfoMap } func NewChangeDetector(rootFolder string) *ChangeDetector { return &ChangeDetector{ rootFolder: rootFolder, - dirMap: map[string]time.Time{}, + dirMap: dirInfoMap{}, } } func (s *ChangeDetector) Scan(lastModifiedSince time.Time) (changed []string, deleted []string, err error) { start := time.Now() - newMap := make(map[string]time.Time) - err = s.loadMap(s.rootFolder, newMap) + newMap := make(dirInfoMap) + err = s.loadMap(newMap, s.rootFolder, lastModifiedSince, false) if err != nil { return } @@ -67,20 +73,21 @@ func (s *ChangeDetector) loadDir(dirPath string) (children []string, lastUpdated return } -func (s *ChangeDetector) loadMap(rootPath string, dirMap map[string]time.Time) error { +func (s *ChangeDetector) loadMap(dirMap dirInfoMap, rootPath string, since time.Time, maybe bool) error { children, lastUpdated, err := s.loadDir(rootPath) if err != nil { return err } + maybe = maybe || lastUpdated.After(since) for _, c := range children { - err := s.loadMap(c, dirMap) + err := s.loadMap(dirMap, c, since, maybe) if err != nil { return err } } dir := s.getRelativePath(rootPath) - dirMap[dir] = lastUpdated + dirMap[dir] = dirInfo{mdate: lastUpdated, maybe: maybe} return nil } @@ -93,11 +100,16 @@ func (s *ChangeDetector) getRelativePath(subfolder string) string { return dir } -func (s *ChangeDetector) checkForUpdates(lastModifiedSince time.Time, newMap map[string]time.Time) (changed []string, deleted []string, err error) { - for dir, lastUpdated := range newMap { - oldLastUpdated, ok := s.dirMap[dir] - if !ok { - oldLastUpdated = lastModifiedSince +func (s *ChangeDetector) checkForUpdates(lastModifiedSince time.Time, newMap dirInfoMap) (changed []string, deleted []string, err error) { + for dir, newEntry := range newMap { + lastUpdated := newEntry.mdate + oldLastUpdated := lastModifiedSince + if oldEntry, ok := s.dirMap[dir]; ok { + oldLastUpdated = oldEntry.mdate + } else { + if newEntry.maybe { + oldLastUpdated = time.Time{} + } } if lastUpdated.After(oldLastUpdated) { changed = append(changed, dir) diff --git a/scanner/change_detector_test.go b/scanner/change_detector_test.go index 2ec621fba..7d8ed4ec6 100644 --- a/scanner/change_detector_test.go +++ b/scanner/change_detector_test.go @@ -33,6 +33,7 @@ var _ = Describe("ChangeDetector", func() { Expect(changed).To(ConsistOf(".")) // Add one subfolder + lastModifiedSince = time.Now() err = os.MkdirAll(path.Join(testFolder, "a"), 0700) if err != nil { panic(err) @@ -43,6 +44,7 @@ var _ = Describe("ChangeDetector", func() { Expect(changed).To(ConsistOf(".", "/a")) // Add more subfolders + lastModifiedSince = time.Now() err = os.MkdirAll(path.Join(testFolder, "a", "b", "c"), 0700) if err != nil { panic(err) @@ -53,12 +55,14 @@ var _ = Describe("ChangeDetector", func() { Expect(changed).To(ConsistOf("/a", "/a/b", "/a/b/c")) // Scan with no changes + lastModifiedSince = time.Now() changed, deleted, err = scanner.Scan(lastModifiedSince) Expect(err).To(BeNil()) Expect(deleted).To(BeEmpty()) Expect(changed).To(BeEmpty()) // New file in subfolder + lastModifiedSince = time.Now() _, err = os.Create(path.Join(testFolder, "a", "b", "empty.txt")) if err != nil { panic(err) @@ -69,6 +73,7 @@ var _ = Describe("ChangeDetector", func() { Expect(changed).To(ConsistOf("/a/b")) // Delete file in subfolder + lastModifiedSince = time.Now() err = os.Remove(path.Join(testFolder, "a", "b", "empty.txt")) if err != nil { panic(err) @@ -79,6 +84,7 @@ var _ = Describe("ChangeDetector", func() { Expect(changed).To(ConsistOf("/a/b")) // Delete subfolder + lastModifiedSince = time.Now() err = os.Remove(path.Join(testFolder, "a", "b", "c")) if err != nil { panic(err) @@ -97,7 +103,8 @@ var _ = Describe("ChangeDetector", func() { Expect(changed).To(BeEmpty()) Expect(changed).To(BeEmpty()) - _, err = os.Create(path.Join(testFolder, "a", "b", "new.txt")) + f, err := os.Create(path.Join(testFolder, "a", "b", "new.txt")) + f.Close() changed, deleted, err = newScanner.Scan(lastModifiedSince) Expect(err).To(BeNil()) Expect(deleted).To(BeEmpty())