Merge pull request #48 from crosbymichael/reset-mtime

Ensure same atime, mtime after applying whiteouts
This commit is contained in:
Guillaume J. Charmes 2013-11-19 15:40:12 -08:00
commit 91330243b5
1 changed files with 39 additions and 7 deletions

View File

@ -1,10 +1,11 @@
package archive package archive
import ( import (
"log"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"syscall"
"time"
) )
// ApplyLayer parses a diff in the standard layer format from `layer`, and // ApplyLayer parses a diff in the standard layer format from `layer`, and
@ -17,6 +18,20 @@ func ApplyLayer(dest string, layer Archive) error {
return err return err
} }
modifiedDirs := make(map[string]*syscall.Stat_t)
addDir := func(file string) {
d := filepath.Dir(file)
if _, exists := modifiedDirs[d]; !exists {
if s, err := os.Lstat(d); err == nil {
if sys := s.Sys(); sys != nil {
if stat, ok := sys.(*syscall.Stat_t); ok {
modifiedDirs[d] = stat
}
}
}
}
}
// Step 2: walk for whiteouts and apply them, removing them in the process // Step 2: walk for whiteouts and apply them, removing them in the process
err := filepath.Walk(dest, func(fullPath string, f os.FileInfo, err error) error { err := filepath.Walk(dest, func(fullPath string, f os.FileInfo, err error) error {
if err != nil { if err != nil {
@ -39,25 +54,42 @@ func ApplyLayer(dest string, layer Archive) error {
if matched, err := filepath.Match("/.wh..wh.*", path); err != nil { if matched, err := filepath.Match("/.wh..wh.*", path); err != nil {
return err return err
} else if matched { } else if matched {
log.Printf("Removing aufs metadata %s", fullPath) addDir(fullPath)
_ = os.RemoveAll(fullPath) if err := os.RemoveAll(fullPath); err != nil {
return err
}
} }
filename := filepath.Base(path) filename := filepath.Base(path)
if strings.HasPrefix(filename, ".wh.") { if strings.HasPrefix(filename, ".wh.") {
rmTargetName := filename[len(".wh."):] rmTargetName := filename[len(".wh."):]
rmTargetPath := filepath.Join(filepath.Dir(fullPath), rmTargetName) rmTargetPath := filepath.Join(filepath.Dir(fullPath), rmTargetName)
// Remove the file targeted by the whiteout // Remove the file targeted by the whiteout
log.Printf("Removing whiteout target %s", rmTargetPath) addDir(rmTargetPath)
_ = os.RemoveAll(rmTargetPath) if err := os.RemoveAll(rmTargetPath); err != nil {
return err
}
// Remove the whiteout itself // Remove the whiteout itself
log.Printf("Removing whiteout %s", fullPath) addDir(fullPath)
_ = os.RemoveAll(fullPath) if err := os.RemoveAll(fullPath); err != nil {
return err
}
} }
return nil return nil
}) })
if err != nil { if err != nil {
return err return err
} }
for k, v := range modifiedDirs {
aTime := time.Unix(v.Atim.Unix())
mTime := time.Unix(v.Mtim.Unix())
if err := os.Chtimes(k, aTime, mTime); err != nil {
return err
}
}
return nil return nil
} }