diff --git a/cmd/gomtree/main.go b/cmd/gomtree/main.go index cd81344..92c6f6a 100644 --- a/cmd/gomtree/main.go +++ b/cmd/gomtree/main.go @@ -396,7 +396,11 @@ func isTarSpec(spec *mtree.DirectoryHierarchy) bool { } func splitKeywordsArg(str string) []string { - return strings.Fields(strings.Replace(str, ",", " ", -1)) + keywords := []string{} + for _, kw := range strings.Fields(strings.Replace(str, ",", " ", -1)) { + keywords = append(keywords, mtree.KeywordSynonym(kw)) + } + return keywords } func inSlice(a string, list []string) bool { diff --git a/hierarchy.go b/hierarchy.go index 88a007d..3c8da39 100644 --- a/hierarchy.go +++ b/hierarchy.go @@ -38,7 +38,7 @@ func (dh DirectoryHierarchy) UsedKeywords() []string { for _, kv := range kvs { kw := KeyVal(kv).Keyword() if !inSlice(kw, usedkeywords) { - usedkeywords = append(usedkeywords, kw) + usedkeywords = append(usedkeywords, KeywordSynonym(kw)) } } } diff --git a/hierarchy_test.go b/hierarchy_test.go new file mode 100644 index 0000000..0a58e56 --- /dev/null +++ b/hierarchy_test.go @@ -0,0 +1,38 @@ +package mtree + +import ( + "strings" + "testing" +) + +var checklist = []struct { + blob string + set []string +}{ + {blob: ` +# machine: bananaboat +# tree: .git +# date: Wed Nov 16 14:54:17 2016 + +# . +/set type=file nlink=1 mode=0664 uid=1000 gid=100 +. size=4096 type=dir mode=0755 nlink=8 time=1479326055.423853146 + .COMMIT_EDITMSG.un~ size=1006 mode=0644 time=1479325423.450468662 sha1digest=dead0face + .TAG_EDITMSG.un~ size=1069 mode=0600 time=1471362316.801317529 sha256digest=dead0face +`, set: []string{"size", "mode", "time", "sha256digest"}}, +} + +func TestUsedKeywords(t *testing.T) { + for i, item := range checklist { + dh, err := ParseSpec(strings.NewReader(item.blob)) + if err != nil { + t.Error(err) + } + used := dh.UsedKeywords() + for _, k := range item.set { + if !inSlice(k, used) { + t.Errorf("%d: expected to find %q in %q", i, k, used) + } + } + } +} diff --git a/keywords.go b/keywords.go index fd996d3..93916f4 100644 --- a/keywords.go +++ b/keywords.go @@ -251,6 +251,31 @@ var ( } ) +// KeywordSynonym returns the canonical name for keywords that have synonyms, +// and just returns the name provided if there is no synonym. In this way it +// ought to be safe to wrap any keyword name. +func KeywordSynonym(name string) string { + switch name { + case "md5": + return "md5digest" + case "rmd160": + return "ripemd160digest" + case "rmd160digest": + return "ripemd160digest" + case "sha1": + return "sha1digest" + case "sha256": + return "sha256digest" + case "sha384": + return "sha384digest" + case "sha512": + return "sha512digest" + case "xattrs": + return "xattr" + } + return name +} + var ( modeKeywordFunc = func(path string, info os.FileInfo, r io.Reader) (string, error) { permissions := info.Mode().Perm() @@ -292,7 +317,7 @@ var ( if _, err := io.Copy(h, r); err != nil { return "", err } - return fmt.Sprintf("%s=%x", name, h.Sum(nil)), nil + return fmt.Sprintf("%s=%x", KeywordSynonym(name), h.Sum(nil)), nil } } tartimeKeywordFunc = func(path string, info os.FileInfo, r io.Reader) (string, error) { diff --git a/keywords_test.go b/keywords_test.go index 5860fc0..4411453 100644 --- a/keywords_test.go +++ b/keywords_test.go @@ -93,3 +93,33 @@ func TestKeywordsTimeTar(t *testing.T) { } } } + +func TestKeywordSynonym(t *testing.T) { + checklist := []struct { + give, expect string + }{ + {give: "time", expect: "time"}, + {give: "md5", expect: "md5digest"}, + {give: "md5digest", expect: "md5digest"}, + {give: "rmd160", expect: "ripemd160digest"}, + {give: "rmd160digest", expect: "ripemd160digest"}, + {give: "ripemd160digest", expect: "ripemd160digest"}, + {give: "sha1", expect: "sha1digest"}, + {give: "sha1digest", expect: "sha1digest"}, + {give: "sha256", expect: "sha256digest"}, + {give: "sha256digest", expect: "sha256digest"}, + {give: "sha384", expect: "sha384digest"}, + {give: "sha384digest", expect: "sha384digest"}, + {give: "sha512", expect: "sha512digest"}, + {give: "sha512digest", expect: "sha512digest"}, + {give: "xattr", expect: "xattr"}, + {give: "xattrs", expect: "xattr"}, + } + + for i, check := range checklist { + got := KeywordSynonym(check.give) + if got != check.expect { + t.Errorf("%d: expected %q; got %q", i, check.expect, got) + } + } +} diff --git a/test/cli/0004.sh b/test/cli/0004.sh new file mode 100644 index 0000000..b538285 --- /dev/null +++ b/test/cli/0004.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -e +#set -x + +name=$(basename $0) +root=$1 +gomtree=$(readlink -f ${root}/gomtree) +t=$(mktemp -d /tmp/go-mtree.XXXXXX) + +echo "[${name}] Running in ${t}" + +pushd ${root} +git archive --format=tar HEAD^{tree} . > ${t}/${name}.tar +mkdir -p ${t}/extract +tar -C ${t}/extract/ -xf ${t}/${name}.tar + +## This is a checking that keyword synonyms are respected +${gomtree} -k sha1digest -c -p ${t}/extract/ > ${t}/${name}.mtree +${gomtree} -k sha1 -f ${t}/${name}.mtree -p ${t}/extract/ +${gomtree} -k sha1 -c -p ${t}/extract/ > ${t}/${name}.mtree +${gomtree} -k sha1digest -f ${t}/${name}.mtree -p ${t}/extract/ + +popd +rm -rf ${t}