fs/diff: support symlink to abspath with second-precision mtime

Previously, `Changes()` for a symlink to absolute path, with second-precision
mtime of the link itself always resulted in ENOENT.

This is because `compareFileContent()` was called for the link target path, without changing the root path.

Fix moby/buildkit#172

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
This commit is contained in:
Akihiro Suda
2017-11-20 09:14:48 +00:00
parent 1bd39d36ed
commit a3aeb398fe
5 changed files with 88 additions and 19 deletions

View File

@@ -74,11 +74,14 @@ func sameFile(f1, f2 *currentPath) (bool, error) {
// If the timestamp may have been truncated in one of the
// files, check content of file to determine difference
if t1.Nanosecond() == 0 || t2.Nanosecond() == 0 {
if f1.f.Size() > 0 {
eq, err := compareFileContent(f1.fullPath, f2.fullPath)
if err != nil || !eq {
return eq, err
}
var eq bool
if (f1.f.Mode() & os.ModeSymlink) == os.ModeSymlink {
eq, err = compareSymlinkTarget(f1.fullPath, f2.fullPath)
} else if f1.f.Size() > 0 {
eq, err = compareFileContent(f1.fullPath, f2.fullPath)
}
if err != nil || !eq {
return eq, err
}
} else if t1.Nanosecond() != t2.Nanosecond() {
return false, nil
@@ -88,6 +91,18 @@ func sameFile(f1, f2 *currentPath) (bool, error) {
return true, nil
}
func compareSymlinkTarget(p1, p2 string) (bool, error) {
t1, err := os.Readlink(p1)
if err != nil {
return false, err
}
t2, err := os.Readlink(p2)
if err != nil {
return false, err
}
return t1 == t2, nil
}
const compareChuckSize = 32 * 1024
// compareFileContent compares the content of 2 same sized files