mirror of
https://github.com/vbatts/go-mtree.git
synced 2024-11-22 00:15:39 +00:00
gomtree: add special cases for tar generation checking
Due to several unsolveable problems in tar generation, such as the size=... keyword, we have to special case quite a few things in the checking code. We might want to move this to mtree properly (but I'm hesitant about ignoring errors that only happen for tar DHes). Signed-off-by: Aleksa Sarai <asarai@suse.de>
This commit is contained in:
parent
d214ab47e8
commit
3bfdecf467
1 changed files with 87 additions and 0 deletions
|
@ -62,6 +62,90 @@ var formats = map[string]func([]mtree.InodeDelta) string{
|
|||
},
|
||||
}
|
||||
|
||||
// isDirEntry returns wheter an mtree.Entry describes a directory.
|
||||
func isDirEntry(e mtree.Entry) bool {
|
||||
for _, kw := range e.Keywords {
|
||||
kv := mtree.KeyVal(kw)
|
||||
if kv.Keyword() == "type" {
|
||||
return kv.Value() == "dir"
|
||||
}
|
||||
}
|
||||
// Shouldn't be reached.
|
||||
return false
|
||||
}
|
||||
|
||||
// filterMissingKeywords is a fairly annoying hack to get around the fact that
|
||||
// tar archive manifest generation has certain unsolveable problems regarding
|
||||
// certain keywords. For example, the size=... keyword cannot be implemented
|
||||
// for directories in a tar archive (which causes Missing errors for that
|
||||
// keyword).
|
||||
//
|
||||
// This function just removes all instances of Missing errors for keywords.
|
||||
// This makes certain assumptions about the type of issues tar archives have.
|
||||
// Only call this on tar archive manifest comparisons.
|
||||
func filterMissingKeywords(diffs []mtree.InodeDelta) []mtree.InodeDelta {
|
||||
newDiffs := []mtree.InodeDelta{}
|
||||
loop:
|
||||
for _, diff := range diffs {
|
||||
if diff.Type() == mtree.Modified {
|
||||
// We only apply this filtering to directories.
|
||||
// NOTE: This will probably break if someone drops the size keyword.
|
||||
if isDirEntry(*diff.Old()) || isDirEntry(*diff.New()) {
|
||||
// If this applies to '.' then we just filter everything
|
||||
// (meaning we remove this entry). This is because note all tar
|
||||
// archives include a '.' entry. Which makes checking this not
|
||||
// practical.
|
||||
if diff.Path() == "." {
|
||||
continue
|
||||
}
|
||||
|
||||
// Only filter out the size keyword.
|
||||
// NOTE: This currently takes advantage of the fact the
|
||||
// diff.Diff() returns the actual slice to diff.keys.
|
||||
keys := diff.Diff()
|
||||
for idx, k := range keys {
|
||||
// Delete the key if it's "size". Unfortunately in Go you
|
||||
// can't delete from a slice without reassigning it. So we
|
||||
// just overwrite it with the last value.
|
||||
if k.Name() == "size" {
|
||||
if len(keys) < 2 {
|
||||
continue loop
|
||||
}
|
||||
keys[idx] = keys[len(keys)-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we got here, append to the new set.
|
||||
newDiffs = append(newDiffs, diff)
|
||||
}
|
||||
return newDiffs
|
||||
}
|
||||
|
||||
// isTarSpec returns whether the spec provided came from the tar generator.
|
||||
// This takes advantage of an unsolveable problem in tar generation.
|
||||
func isTarSpec(spec *mtree.DirectoryHierarchy) bool {
|
||||
// Find a directory and check whether it's missing size=...
|
||||
// NOTE: This will definitely break if someone drops the size=... keyword.
|
||||
for _, e := range spec.Entries {
|
||||
if !isDirEntry(e) {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, kw := range e.Keywords {
|
||||
kv := mtree.KeyVal(kw)
|
||||
if kv.Keyword() == "size" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Should never be reached.
|
||||
return false
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
|
@ -327,6 +411,9 @@ func main() {
|
|||
return
|
||||
}
|
||||
if res != nil {
|
||||
if isTarSpec(specDh) || *flTar != "" {
|
||||
res = filterMissingKeywords(res)
|
||||
}
|
||||
if len(res) > 0 {
|
||||
defer os.Exit(1)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue