Ver Fonte

Handle symlinks, Staggered versioner (fixes #1071)

Jakob Borg há 11 anos atrás
pai
commit
94ab06e92f
1 ficheiros alterados com 54 adições e 55 exclusões
  1. 54 55
      internal/versioner/staggered.go

+ 54 - 55
internal/versioner/staggered.go

@@ -45,16 +45,6 @@ type Staggered struct {
 	mutex         *sync.Mutex
 }
 
-// Check if file or dir
-func isFile(path string) bool {
-	fileInfo, err := os.Stat(path)
-	if err != nil {
-		l.Infoln("versioner isFile:", err)
-		return false
-	}
-	return fileInfo.Mode().IsRegular()
-}
-
 // Rename versions with old version format
 func (v Staggered) renameOld() {
 	err := filepath.Walk(v.versionsPath, func(path string, f os.FileInfo, err error) error {
@@ -167,14 +157,16 @@ func (v Staggered) clean() {
 		if err != nil {
 			return err
 		}
-		switch mode := f.Mode(); {
-		case mode.IsDir():
+
+		if f.Mode().IsDir() && f.Mode()&os.ModeSymlink == 0 {
 			filesPerDir[path] = 0
 			if path != v.versionsPath {
 				dir := filepath.Dir(path)
 				filesPerDir[dir]++
 			}
-		case mode.IsRegular():
+		} else {
+			// Regular file, or possibly a symlink.
+
 			extension := filenameTag(path)
 			dir := filepath.Dir(path)
 			name := path[:len(path)-len(extension)-1]
@@ -227,56 +219,63 @@ func (v Staggered) expire(versions []string) {
 	var prevAge int64
 	firstFile := true
 	for _, file := range versions {
-		if isFile(file) {
-			versionTime, err := time.Parse(TimeFormat, filenameTag(file))
+		fi, err := os.Stat(file)
+		if err != nil {
+			l.Warnln("versioner:", err)
+			continue
+		}
+
+		if fi.IsDir() {
+			l.Infof("non-file %q is named like a file version", file)
+			continue
+		}
+
+		versionTime, err := time.Parse(TimeFormat, filenameTag(file))
+		if err != nil {
+			l.Infof("Versioner: file name %q is invalid: %v", file, err)
+			continue
+		}
+		age := int64(time.Since(versionTime).Seconds())
+
+		// If the file is older than the max age of the last interval, remove it
+		if lastIntv := v.interval[len(v.interval)-1]; lastIntv.end > 0 && age > lastIntv.end {
+			if debug {
+				l.Debugln("Versioner: File over maximum age -> delete ", file)
+			}
+			err = os.Remove(file)
 			if err != nil {
-				l.Infof("Versioner: file name %q is invalid: %v", file, err)
-				continue
+				l.Warnf("Versioner: can't remove %q: %v", file, err)
 			}
-			age := int64(time.Since(versionTime).Seconds())
+			continue
+		}
 
-			// If the file is older than the max age of the last interval, remove it
-			if lastIntv := v.interval[len(v.interval)-1]; lastIntv.end > 0 && age > lastIntv.end {
-				if debug {
-					l.Debugln("Versioner: File over maximum age -> delete ", file)
-				}
-				err = os.Remove(file)
-				if err != nil {
-					l.Warnf("Versioner: can't remove %q: %v", file, err)
-				}
-				continue
-			}
+		// If it's the first (oldest) file in the list we can skip the interval checks
+		if firstFile {
+			prevAge = age
+			firstFile = false
+			continue
+		}
 
-			// If it's the first (oldest) file in the list we can skip the interval checks
-			if firstFile {
-				prevAge = age
-				firstFile = false
-				continue
+		// Find the interval the file fits in
+		var usedInterval Interval
+		for _, usedInterval = range v.interval {
+			if age < usedInterval.end {
+				break
 			}
+		}
 
-			// Find the interval the file fits in
-			var usedInterval Interval
-			for _, usedInterval = range v.interval {
-				if age < usedInterval.end {
-					break
-				}
+		if prevAge-age < usedInterval.step {
+			if debug {
+				l.Debugln("too many files in step -> delete", file)
 			}
-
-			if prevAge-age < usedInterval.step {
-				if debug {
-					l.Debugln("too many files in step -> delete", file)
-				}
-				err = os.Remove(file)
-				if err != nil {
-					l.Warnf("Versioner: can't remove %q: %v", file, err)
-				}
-				continue
+			err = os.Remove(file)
+			if err != nil {
+				l.Warnf("Versioner: can't remove %q: %v", file, err)
 			}
-
-			prevAge = age
-		} else {
-			l.Infof("non-file %q is named like a file version", file)
+			continue
 		}
+
+		prevAge = age
 	}
 }
 
@@ -289,7 +288,7 @@ func (v Staggered) Archive(filePath string) error {
 	v.mutex.Lock()
 	defer v.mutex.Unlock()
 
-	if _, err := os.Stat(filePath); err != nil {
+	if _, err := os.Lstat(filePath); err != nil {
 		if os.IsNotExist(err) {
 			if debug {
 				l.Debugln("not archiving nonexistent file", filePath)