mirror of
https://github.com/vbatts/go-mtree.git
synced 2025-09-13 22:03:19 +00:00
compare: properly compare tar_time and time
In certain circumstances, if a manifest with "time" keywords was compared to another manifest with "tar_time" keywords, differences were not actually reported despite there being logic for it. Unfortunately, even though commit26ff922da6
("compare: implement mtree.DirectoryHierarchy comparisons") explicitly included logic to handle the necessary "time" -> "tar_time" conversions, the same commit also made it so that Compare() could be instructed to only consider a subset of keywords and failed to take into account said "time" -> "tar_time" remapping. Most users have likely not noticed this because gomtree will re-use the keywords from a manifest when doing a straightforward "gomtree validate" invocation, but if you explicitly requested "time" when validating a "tar_time" manifest (and *not* the other way around) then any time changes would be undetected. Fixes:26ff922da6
("compare: implement mtree.DirectoryHierarchy comparisons") Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
This commit is contained in:
parent
b3097c1af5
commit
0beb885cbf
2 changed files with 74 additions and 8 deletions
18
compare.go
18
compare.go
|
@ -3,6 +3,7 @@ package mtree
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
|
@ -405,15 +406,16 @@ func compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword, same bool) ([]Ino
|
|||
return nil, fmt.Errorf("comparison failed %s: %s", path, err)
|
||||
}
|
||||
|
||||
// Now remove "changed" entries that don't match the keys.
|
||||
// Ignore changes to keys not in the requested set.
|
||||
if keys != nil {
|
||||
var filterChanged []KeyDelta
|
||||
for _, keyDiff := range changed {
|
||||
if InKeywordSlice(keyDiff.name.Prefix(), keys) {
|
||||
filterChanged = append(filterChanged, keyDiff)
|
||||
}
|
||||
}
|
||||
changed = filterChanged
|
||||
changed = slices.DeleteFunc(changed, func(delta KeyDelta) bool {
|
||||
name := delta.name.Prefix()
|
||||
return !InKeywordSlice(name, keys) &&
|
||||
// We remap time to tar_time in compareEntry, so we
|
||||
// need to treat them equivalently here.
|
||||
!(name == "time" && InKeywordSlice("tar_time", keys)) &&
|
||||
!(name == "tar_time" && InKeywordSlice("time", keys))
|
||||
})
|
||||
}
|
||||
|
||||
// Check if there were any actual changes.
|
||||
|
|
64
test/cli/0012.sh
Normal file
64
test/cli/0012.sh
Normal file
|
@ -0,0 +1,64 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
name=$(basename $0)
|
||||
root="$(dirname $(dirname $(dirname $0)))"
|
||||
gomtree=$(go run ${root}/test/realpath/main.go ${root}/gomtree)
|
||||
t=$(mktemp -d /tmp/go-mtree.XXXXXX)
|
||||
|
||||
echo "[${name}] Running in ${t}"
|
||||
|
||||
## Make sure that comparing manifests with tar_time and time correctly detect
|
||||
## errors (while also *truncating* timestamps for tar_time comparisons).
|
||||
|
||||
pushd ${root}
|
||||
mkdir -p ${t}/root
|
||||
|
||||
date="2025-09-05T13:05:10.12345" # POSIX format for "touch -d".
|
||||
|
||||
touch -d "$date" ${t}/root/foo
|
||||
|
||||
keywords=type,uid,gid,nlink,link,mode,flags,xattr,size,sha256
|
||||
|
||||
# Generate regular manifests with time and tar_time.
|
||||
${gomtree} -c -k ${keywords},time -p ${t}/root -f ${t}/time.mtree
|
||||
${gomtree} -c -k ${keywords},tar_time -p ${t}/root -f ${t}/tartime.mtree
|
||||
|
||||
# Validation with both manifests should still succeed.
|
||||
${gomtree} validate -p ${t}/root -f ${t}/time.mtree
|
||||
${gomtree} validate -p ${t}/root -f ${t}/tartime.mtree
|
||||
# Manifest comparison should also succeed.
|
||||
${gomtree} validate -f ${t}/tartime.mtree -f ${t}/time.mtree
|
||||
${gomtree} validate -f ${t}/time.mtree -f ${t}/tartime.mtree
|
||||
# Forcefully requesting a different time type should also succeed.
|
||||
${gomtree} validate -k ${keywords},tar_time -p ${t}/root -f ${t}/time.mtree
|
||||
${gomtree} validate -k ${keywords},time -p ${t}/root -f ${t}/tartime.mtree
|
||||
|
||||
# Change the timestamp.
|
||||
touch -d "1997-03-25T13:40:00.67890" ${t}/root/foo
|
||||
|
||||
# Standard validations should fail.
|
||||
(! ${gomtree} validate -p ${t}/root -f ${t}/time.mtree)
|
||||
(! ${gomtree} validate -p ${t}/root -f ${t}/tartime.mtree)
|
||||
|
||||
# Forcefully requesting a different time type should also fail.
|
||||
(! ${gomtree} validate -k ${keywords},tar_time -p ${t}/root -f ${t}/time.mtree)
|
||||
(! ${gomtree} validate -k ${keywords},time -p ${t}/root -f ${t}/tartime.mtree)
|
||||
|
||||
# Ditto if we generate the manifests and compare them.
|
||||
${gomtree} -c -k ${keywords},time -p ${t}/root -f ${t}/time-change.mtree
|
||||
${gomtree} -c -k ${keywords},tar_time -p ${t}/root -f ${t}/tartime-change.mtree
|
||||
|
||||
# Same time types.
|
||||
(! ${gomtree} validate -f ${t}/time.mtree -f ${t}/time-change.mtree)
|
||||
(! ${gomtree} validate -f ${t}/time-change.mtree -f ${t}/time.mtree)
|
||||
(! ${gomtree} validate -f ${t}/tartime.mtree -f ${t}/tartime-change.mtree)
|
||||
(! ${gomtree} validate -f ${t}/tartime-change.mtree -f ${t}/tartime.mtree)
|
||||
|
||||
# Different time types:
|
||||
# (old) time <=> (new) tar_time
|
||||
(! ${gomtree} validate -f ${t}/time.mtree -f ${t}/tartime-change.mtree)
|
||||
(! ${gomtree} validate -f ${t}/tartime-change.mtree -f ${t}/time.mtree)
|
||||
# (old) tar_time <=> (new) time
|
||||
(! ${gomtree} validate -f ${t}/tartime.mtree -f ${t}/time-change.mtree)
|
||||
(! ${gomtree} validate -f ${t}/time-change.mtree -f ${t}/tartime.mtree)
|
Loading…
Add table
Add a link
Reference in a new issue