瀏覽代碼

Re-incorporate ChangesDirs() for the use of the devmapper backend,
without changing existing prototypes.

This is a neutral change. The primary aufs backend is still in place
and not affected.

Solomon Hykes 11 年之前
父節點
當前提交
a5031d47d9
共有 1 個文件被更改,包括 102 次插入0 次删除
  1. 102 0
      changes.go

+ 102 - 0
changes.go

@@ -5,6 +5,7 @@ import (
 	"os"
 	"path/filepath"
 	"strings"
+	"syscall"
 )
 
 type ChangeType int
@@ -104,3 +105,104 @@ func Changes(layers []string, rw string) ([]Change, error) {
 	}
 	return changes, nil
 }
+
+func ChangesDirs(newDir, oldDir string) ([]Change, error) {
+	var changes []Change
+	err := filepath.Walk(newDir, func(newPath string, f os.FileInfo, err error) error {
+		if err != nil {
+			return err
+		}
+
+		var newStat syscall.Stat_t
+		err = syscall.Lstat(newPath, &newStat)
+		if err != nil {
+			return err
+		}
+
+		// Rebase path
+		relPath, err := filepath.Rel(newDir, newPath)
+		if err != nil {
+			return err
+		}
+		relPath = filepath.Join("/", relPath)
+
+		// Skip root
+		if relPath == "/" || relPath == "/.docker-id" {
+			return nil
+		}
+
+		change := Change{
+			Path: relPath,
+		}
+
+		oldPath := filepath.Join(oldDir, relPath)
+
+		var oldStat = &syscall.Stat_t{}
+		err = syscall.Lstat(oldPath, oldStat)
+		if err != nil {
+			if !os.IsNotExist(err) {
+				return err
+			}
+			oldStat = nil
+		}
+
+		if oldStat == nil {
+			change.Kind = ChangeAdd
+			changes = append(changes, change)
+		} else {
+			if oldStat.Ino != newStat.Ino ||
+				oldStat.Mode != newStat.Mode ||
+				oldStat.Uid != newStat.Uid ||
+				oldStat.Gid != newStat.Gid ||
+				oldStat.Rdev != newStat.Rdev ||
+				oldStat.Size != newStat.Size ||
+				oldStat.Blocks != newStat.Blocks ||
+				oldStat.Mtim != newStat.Mtim ||
+				oldStat.Ctim != newStat.Ctim {
+				change.Kind = ChangeModify
+				changes = append(changes, change)
+			}
+		}
+
+		return nil
+	})
+	if err != nil {
+		return nil, err
+	}
+	err = filepath.Walk(oldDir, func(oldPath string, f os.FileInfo, err error) error {
+		if err != nil {
+			return err
+		}
+
+		// Rebase path
+		relPath, err := filepath.Rel(oldDir, oldPath)
+		if err != nil {
+			return err
+		}
+		relPath = filepath.Join("/", relPath)
+
+		// Skip root
+		if relPath == "/" {
+			return nil
+		}
+
+		change := Change{
+			Path: relPath,
+		}
+
+		newPath := filepath.Join(newDir, relPath)
+
+		var newStat = &syscall.Stat_t{}
+		err = syscall.Lstat(newPath, newStat)
+		if err != nil && os.IsNotExist(err) {
+			change.Kind = ChangeDelete
+			changes = append(changes, change)
+		}
+
+		return nil
+	})
+	if err != nil {
+		return nil, err
+	}
+	return changes, nil
+}