1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Add Changes.ChangesLayers()

This calculates the difference between a set of layers and a
directory tree.
This commit is contained in:
Alexander Larsson 2013-09-13 15:56:06 +02:00 committed by Victor Vieux
parent 36603e68e3
commit ad0a6a03e3

View file

@ -235,11 +235,88 @@ func (info *FileInfo)Changes(oldInfo *FileInfo) []Change {
} }
func collectFileInfo(sourceDir string) (*FileInfo, error) { func newRootFileInfo() *FileInfo {
root := &FileInfo { root := &FileInfo {
name: "/", name: "/",
children: make(map[string]*FileInfo), children: make(map[string]*FileInfo),
} }
return root
}
func applyLayer(root *FileInfo, layer string) error {
err := filepath.Walk(layer, func(layerPath string, f os.FileInfo, err error) error {
if err != nil {
return err
}
// Skip root
if layerPath == layer {
return nil
}
// rebase path
relPath, err := filepath.Rel(layer, layerPath)
if err != nil {
return err
}
relPath = filepath.Join("/", relPath)
// Skip AUFS metadata
if matched, err := filepath.Match("/.wh..wh.*", relPath); err != nil || matched {
if err != nil || !f.IsDir() {
return err
}
return filepath.SkipDir
}
var layerStat syscall.Stat_t
err = syscall.Lstat(layerPath, &layerStat)
if err != nil {
return err
}
file := filepath.Base(relPath)
// If there is a whiteout, then the file was removed
if strings.HasPrefix(file, ".wh.") {
originalFile := file[len(".wh."):]
deletePath := filepath.Join(filepath.Dir(relPath), originalFile)
root.Remove(deletePath)
} else {
// Added or changed file
existing := root.LookUp(relPath)
if existing != nil {
// Changed file
existing.stat = layerStat
if !existing.isDir() {
// Changed from dir to non-dir, delete all previous files
existing.children = make(map[string]*FileInfo)
}
} else {
// Added file
parent := root.LookUp(filepath.Dir(relPath))
if parent == nil {
return fmt.Errorf("collectFileInfo: Unexpectedly no parent for %s", relPath)
}
info := &FileInfo {
name: filepath.Base(relPath),
children: make(map[string]*FileInfo),
parent: parent,
stat: layerStat,
}
parent.children[info.name] = info
}
}
return nil
})
return err
}
func collectFileInfo(sourceDir string) (*FileInfo, error) {
root := newRootFileInfo()
err := filepath.Walk(sourceDir, func(path string, f os.FileInfo, err error) error { err := filepath.Walk(sourceDir, func(path string, f os.FileInfo, err error) error {
if err != nil { if err != nil {
@ -282,6 +359,22 @@ func collectFileInfo(sourceDir string) (*FileInfo, error) {
return root, nil return root, nil
} }
func ChangesLayers(newDir string, layers []string) ([]Change, error) {
newRoot, err := collectFileInfo(newDir)
if err != nil {
return nil, err
}
oldRoot := newRootFileInfo()
for i := len(layers)-1; i >= 0; i-- {
layer := layers[i]
if err = applyLayer(oldRoot, layer); err != nil {
return nil, err
}
}
return newRoot.Changes(oldRoot), nil
}
func ChangesDirs(newDir, oldDir string) ([]Change, error) { func ChangesDirs(newDir, oldDir string) ([]Change, error) {
oldRoot, err := collectFileInfo(oldDir) oldRoot, err := collectFileInfo(oldDir)
if err != nil { if err != nil {