diff --git a/.travis.yml b/.travis.yml index 2f76686..73b5adb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,15 @@ language: go +arch: + - amd64 + - ppc64le go: - "1.x" + - "1.14.x" + - "1.13.x" + - "1.12.x" - "1.11.x" - "1.10.x" - "1.9.x" - - "1.8.x" sudo: false diff --git a/Makefile b/Makefile index bd98334..ef52ea7 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ CLEAN_FILES := *~ TAGS := ARCHES := linux,386 linux,amd64 linux,arm linux,arm64 openbsd,amd64 windows,amd64 darwin,amd64 +GO_VER := go1.14 default: build validation @@ -19,12 +20,13 @@ test: .test CLEAN_FILES += .test .test.tags +NO_VENDOR_DIR := $(shell find . -type f -name '*.go' ! -path './vendor*' ! -path './.git*' ! -path './.vscode*' -exec dirname "{}" \; | sort -u) .test: $(SOURCE_FILES) - go test -v $$(glide novendor) && touch $@ + go test -v $(NO_VENDOR_DIR) && touch $@ .test.tags: $(SOURCE_FILES) - set -e ; for tag in $(TAGS) ; do go test -tags $$tag -v $$(glide novendor) ; done && touch $@ + set -e ; for tag in $(TAGS) ; do go test -tags $$tag -v $(NO_VENDOR_DIR) ; done && touch $@ .PHONY: lint lint: .lint @@ -32,10 +34,10 @@ CLEAN_FILES += .lint .lint: $(SOURCE_FILES) - if [[ "$(go version |awk '{ print $3 }')" =~ ^go1\.11\. ]] ; then \ - set -e ; for dir in $$(glide novendor) ; do golint -set_exit_status $$dir ; done && touch $@ \ + @if [ "$(findstring $(GO_VER),$(shell go version))" != "" ] ; then \ + set -e ; for dir in $(NO_VENDOR_DIR) ; do golint -set_exit_status $$dir ; done && touch $@ \ else \ - touch $@ ; \ + touch $@ ; \ fi .PHONY: vet @@ -44,10 +46,10 @@ CLEAN_FILES += .vet .vet.tags .vet: $(SOURCE_FILES) - go vet $$(glide novendor) && touch $@ + go vet $(NO_VENDOR_DIR) && touch $@ .vet.tags: $(SOURCE_FILES) - set -e ; for tag in $(TAGS) ; do go vet -tags $$tag -v $$(glide novendor) ; done && touch $@ + set -e ; for tag in $(TAGS) ; do go vet -tags $$tag -v $(NO_VENDOR_DIR) ; done && touch $@ .PHONY: cli.test cli.test: .cli.test @@ -67,8 +69,10 @@ go build -o $(BUILD) $(BUILDPATH) install.tools: - go get -u -v github.com/Masterminds/glide - if [[ "$(go version |awk '{ print $3 }')" =~ ^go1\.11\. ]] ; then go get -u golang.org/x/lint/golint ; fi + @go get -u github.com/fatih/color ; \ + if [ "$(findstring $(GO_VER),$(shell go version))" != "" ] ; then \ + go get -u golang.org/x/lint/golint ;\ + fi ./bin: mkdir -p $@ diff --git a/check.go b/check.go index 29e05e3..5d60fff 100644 --- a/check.go +++ b/check.go @@ -18,13 +18,3 @@ return Compare(dh, newDh, keywords) } - -// TarCheck is the tar equivalent of checking a file hierarchy spec against a -// tar stream to determine if files have been changed. This is precisely -// equivalent to Compare(dh, tarDH, keywords). -func TarCheck(tarDH, dh *DirectoryHierarchy, keywords []Keyword) ([]InodeDelta, error) { - if keywords == nil { - return Compare(dh, tarDH, dh.UsedKeywords()) - } - return Compare(dh, tarDH, keywords) -} diff --git a/compare.go b/compare.go index 625a792..e17757d 100644 --- a/compare.go +++ b/compare.go @@ -29,6 +29,10 @@ // have different values (or have not been set in one of the // manifests). Modified DifferenceType = "modified" + + // Same represents the case where two files are the same. These are + // only generated from CompareSame(). + Same DifferenceType = "same" // ErrorDifference represents an attempted update to the values of // a keyword that failed @@ -157,10 +161,10 @@ // New returns the value of the KeyDeltaVal entry in the "new" DirectoryHierarchy // (as determined by the ordering of parameters to Compare). Returns nil if -// there was no entry in the "old" DirectoryHierarchy. +// there was no entry in the "new" DirectoryHierarchy. func (k KeyDelta) New() *string { if k.diff == Modified || k.diff == Extra { - return sPtr(k.old) + return sPtr(k.new) } return nil } @@ -305,6 +309,131 @@ name: name, old: diff.Old.Value(), new: diff.New.Value(), + }) + } + } + } + + return results, nil +} + +// compare is the actual workhorse for Compare() and CompareSame() +func compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword, same bool) ([]InodeDelta, error) { + // Represents the new and old states for an entry. + type stateT struct { + Old *Entry + New *Entry + } + + // To deal with different orderings of the entries, use a path-keyed + // map to make sure we don't start comparing unrelated entries. + diffs := map[string]*stateT{} + + // First, iterate over the old hierarchy. If nil, pretend it's empty. + if oldDh != nil { + for _, e := range oldDh.Entries { + if e.Type == RelativeType || e.Type == FullType { + path, err := e.Path() + if err != nil { + return nil, err + } + + // Cannot take &kv because it's the iterator. + cEntry := new(Entry) + *cEntry = e + + _, ok := diffs[path] + if !ok { + diffs[path] = &stateT{} + } + diffs[path].Old = cEntry + } + } + } + + // Then, iterate over the new hierarchy. If nil, pretend it's empty. + if newDh != nil { + for _, e := range newDh.Entries { + if e.Type == RelativeType || e.Type == FullType { + path, err := e.Path() + if err != nil { + return nil, err + } + + // Cannot take &kv because it's the iterator. + cEntry := new(Entry) + *cEntry = e + + _, ok := diffs[path] + if !ok { + diffs[path] = &stateT{} + } + diffs[path].New = cEntry + } + } + } + + // Now we compute the diff. + var results []InodeDelta + for path, diff := range diffs { + // Invalid + if diff.Old == nil && diff.New == nil { + return nil, fmt.Errorf("invalid state: both old and new are nil: path=%s", path) + } + + switch { + // Missing + case diff.New == nil: + results = append(results, InodeDelta{ + diff: Missing, + path: path, + old: *diff.Old, + }) + + // Extra + case diff.Old == nil: + results = append(results, InodeDelta{ + diff: Extra, + path: path, + new: *diff.New, + }) + + // Modified + default: + changed, err := compareEntry(*diff.Old, *diff.New) + if err != nil { + return nil, fmt.Errorf("comparison failed %s: %s", path, err) + } + + // Now remove "changed" entries that don't match the keys. + if keys != nil { + var filterChanged []KeyDelta + for _, keyDiff := range changed { + if InKeywordSlice(keyDiff.name.Prefix(), keys) { + filterChanged = append(filterChanged, keyDiff) + } + } + changed = filterChanged + } + + // Check if there were any actual changes. + if len(changed) > 0 { + results = append(results, InodeDelta{ + diff: Modified, + path: path, + old: *diff.Old, + new: *diff.New, + keys: changed, + }) + } else if same { + // this means that nothing changed, i.e. that + // the files are the same. + results = append(results, InodeDelta{ + diff: Same, + path: path, + old: *diff.Old, + new: *diff.New, + keys: changed, }) } } @@ -332,115 +461,11 @@ // NB: The order of the parameters matters (old, new) because Extra and // Missing are considered as different discrepancy types. func Compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, error) { - // Represents the new and old states for an entry. - type stateT struct { - Old *Entry - New *Entry - } - - // To deal with different orderings of the entries, use a path-keyed - // map to make sure we don't start comparing unrelated entries. - diffs := map[string]*stateT{} - - // First, iterate over the old hierarchy. If nil, pretend it's empty. - if oldDh != nil { - for _, e := range oldDh.Entries { - if e.Type == RelativeType || e.Type == FullType { - path, err := e.Path() - if err != nil { - return nil, err - } - - // Cannot take &kv because it's the iterator. - cEntry := new(Entry) - *cEntry = e - - _, ok := diffs[path] - if !ok { - diffs[path] = &stateT{} - } - diffs[path].Old = cEntry - } - } - } - - // Then, iterate over the new hierarchy. If nil, pretend it's empty. - if newDh != nil { - for _, e := range newDh.Entries { - if e.Type == RelativeType || e.Type == FullType { - path, err := e.Path() - if err != nil { - return nil, err - } - - // Cannot take &kv because it's the iterator. - cEntry := new(Entry) - *cEntry = e - - _, ok := diffs[path] - if !ok { - diffs[path] = &stateT{} - } - diffs[path].New = cEntry - } - } - } - - // Now we compute the diff. - var results []InodeDelta - for path, diff := range diffs { - // Invalid - if diff.Old == nil && diff.New == nil { - return nil, fmt.Errorf("invalid state: both old and new are nil: path=%s", path) - } - - switch { - // Missing - case diff.New == nil: - results = append(results, InodeDelta{ - diff: Missing, - path: path, - old: *diff.Old, - }) - - // Extra - case diff.Old == nil: - results = append(results, InodeDelta{ - diff: Extra, - path: path, - new: *diff.New, - }) - - // Modified - default: - changed, err := compareEntry(*diff.Old, *diff.New) - if err != nil { - return nil, fmt.Errorf("comparison failed %s: %s", path, err) - } - - // Now remove "changed" entries that don't match the keys. - if keys != nil { - var filterChanged []KeyDelta - for _, keyDiff := range changed { - if InKeywordSlice(keyDiff.name.Prefix(), keys) { - filterChanged = append(filterChanged, keyDiff) - } - } - changed = filterChanged - } - - // Check if there were any actual changes. - if len(changed) > 0 { - results = append(results, InodeDelta{ - diff: Modified, - path: path, - old: *diff.Old, - new: *diff.New, - keys: changed, - }) - } - } - } - - return results, nil -} + return compare(oldDh, newDh, keys, false) +} + +// CompareSame is the same as Compare, except it also includes the entries +// that are the same with a Same DifferenceType. +func CompareSame(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, error) { + return compare(oldDh, newDh, keys, true) +} diff --git a/debian/changelog b/debian/changelog index a3b5d86..f478fcd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +golang-github-vbatts-go-mtree (0.5.0+git20210125.1.4d95ad8-1) UNRELEASED; urgency=low + + * New upstream snapshot. + + -- Debian Janitor Fri, 16 Apr 2021 03:13:54 -0000 + golang-github-vbatts-go-mtree (0.4.4-2) unstable; urgency=medium * (Build-)Depends += "golang-github-davecgh-go-spew-dev" (Closes: #955682). diff --git a/glide.lock b/glide.lock deleted file mode 100644 index 4d197f7..0000000 --- a/glide.lock +++ /dev/null @@ -1,21 +0,0 @@ -hash: 8b0df7f603e6b580aa2640d99d3fa7430198f7db89321ff2abf76efa969d14c2 -updated: 2018-08-20T07:56:40.333174254-04:00 -imports: -- name: github.com/fatih/color - version: 5b77d2a35fb0ede96d138fc9a99f5c9b6aef11b4 -- name: github.com/sirupsen/logrus - version: 3e01752db0189b9157070a0e1668a620f9a85da2 -- name: golang.org/x/crypto - version: 1351f936d976c60a0a48d728281922cf63eafb8d - subpackages: - - ripemd160 - - ssh/terminal -- name: golang.org/x/sys - version: 8dbc5d05d6edcc104950cc299a1ce6641235bc86 - subpackages: - - unix -testImports: -- name: github.com/davecgh/go-spew - version: 8991bc29aa16c548c550c7ff78260e27b9ab7c73 - subpackages: - - spew diff --git a/glide.yaml b/glide.yaml deleted file mode 100644 index 3e78783..0000000 --- a/glide.yaml +++ /dev/null @@ -1,16 +0,0 @@ -package: github.com/vbatts/go-mtree -description: File systems verification utility and library, in likeness of mtree(8) -homepage: https://github.com/vbatts/go-mtree -license: BSD-3-Clause -import: -- package: golang.org/x/crypto - subpackages: - - ripemd160 -- package: github.com/sirupsen/logrus - version: ^1.0.0 -- package: golang.org/x/sys - version: 8dbc5d05d6edcc104950cc299a1ce6641235bc86 - subpackages: - - unix -- package: github.com/fatih/color - version: ^1.6.0 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..60db947 --- /dev/null +++ b/go.mod @@ -0,0 +1,13 @@ +module github.com/vbatts/go-mtree + +go 1.13 + +require ( + github.com/davecgh/go-spew v1.1.1 + github.com/fatih/color v1.10.0 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect + github.com/sirupsen/logrus v1.7.0 + github.com/stretchr/objx v0.1.1 // indirect + golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad + golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..4ebb3ae --- /dev/null +++ b/go.sum @@ -0,0 +1,48 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME= +github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/tar_test.go b/tar_test.go index 4b88e51..82d8abe 100644 --- a/tar_test.go +++ b/tar_test.go @@ -109,7 +109,7 @@ t.Fatal(err) } - res, err := TarCheck(tdh, dh, append(DefaultKeywords, "sha1")) + res, err := Compare(tdh, dh, append(DefaultKeywords, "sha1")) if err != nil { t.Fatal(err) } @@ -164,7 +164,7 @@ } // Test the tar manifest against itself - res, err = TarCheck(tdh, tdh, []Keyword{"sha1"}) + res, err = Compare(tdh, tdh, []Keyword{"sha1"}) if err != nil { t.Fatal(err) } @@ -180,7 +180,7 @@ if err != nil { t.Fatal(err) } - res, err = TarCheck(tdh, dh, []Keyword{"sha1"}) + res, err = Compare(tdh, dh, []Keyword{"sha1"}) if err != nil { t.Fatal(err) } @@ -218,7 +218,7 @@ t.Fatal(err) } - res, err := TarCheck(tdh, tdh, []Keyword{"sha1"}) + res, err := Compare(tdh, tdh, []Keyword{"sha1"}) if err != nil { t.Fatal(err) } diff --git a/version.go b/version.go index ba089cb..8ba2684 100644 --- a/version.go +++ b/version.go @@ -13,7 +13,7 @@ // VersionMinor is for functionality in a backwards-compatible manner VersionMinor = 5 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 0 + VersionPatch = 1 // VersionDev indicates development branch. Releases will be empty string. VersionDev = "-dev"