From ad402763e160ded1924c9b154983d81614e90deb Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Fri, 13 Sep 2013 15:49:57 +0200 Subject: [PATCH] Changes: Better metadata comparison Change the comparison to better handle files that are copied during container creation but not actually changed: * Inode - this will change during a copy * ctime - this will change during a copy (as we can't set it back) * blocksize - this will change for sparse files during copy * size for directories - this can change anytime but doesn't necessarily reflect an actual contents change * Compare mtimes at microsecond precision (as this is what utimes has) --- changes.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/changes.go b/changes.go index d1b0a25b0d..53fa2d49b4 100644 --- a/changes.go +++ b/changes.go @@ -185,15 +185,22 @@ func (info *FileInfo)addChanges(oldInfo *FileInfo, changes *[]Change) { // change? oldStat := &oldChild.stat newStat := &newChild.stat - if oldStat.Ino != newStat.Ino || - oldStat.Mode != newStat.Mode || + // Note: We can't compare inode or ctime or blocksize here, because these change + // when copying a file into a container. However, that is not generally a problem + // because any content change will change mtime, and any status change should + // be visible when actually comparing the stat fields. The only time this + // breaks down is if some code intentionally hides a change by setting + // back mtime + oldMtime := syscall.NsecToTimeval(oldStat.Mtim.Nano()) + newMtime := syscall.NsecToTimeval(oldStat.Mtim.Nano()) + if 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 { + // Don't look at size for dirs, its not a good measure of change + (oldStat.Size != newStat.Size && oldStat.Mode &syscall.S_IFDIR != syscall.S_IFDIR) || + oldMtime.Sec != newMtime.Sec || + oldMtime.Usec != newMtime.Usec { change := Change{ Path: newChild.path(), Kind: ChangeModify,