Import upstream version 0.5.0+git20210625.1.e8d42c3
Debian Janitor
2 years ago
0 | name: Go | |
1 | ||
2 | on: | |
3 | push: | |
4 | branches: [ master ] | |
5 | pull_request: | |
6 | branches: [ master ] | |
7 | ||
8 | jobs: | |
9 | ||
10 | build: | |
11 | runs-on: ubuntu-latest | |
12 | steps: | |
13 | - uses: actions/checkout@v2 | |
14 | ||
15 | - name: Set up Go | |
16 | uses: actions/setup-go@v2 | |
17 | with: | |
18 | go-version: 1.16 | |
19 | ||
20 | - name: Build | |
21 | run: make | |
22 | ||
23 | - name: Test | |
24 | run: make validation | |
25 | ||
26 | - name: Build.Arches | |
27 | run: make build.arches |
0 | 0 | language: go |
1 | arch: | |
2 | - amd64 | |
3 | - ppc64le | |
1 | 4 | go: |
2 | 5 | - "1.x" |
6 | - "1.14.x" | |
7 | - "1.13.x" | |
8 | - "1.12.x" | |
3 | 9 | - "1.11.x" |
4 | 10 | - "1.10.x" |
5 | 11 | - "1.9.x" |
6 | - "1.8.x" | |
7 | 12 | |
8 | 13 | sudo: false |
9 | 14 |
5 | 5 | CLEAN_FILES := *~ |
6 | 6 | TAGS := |
7 | 7 | ARCHES := linux,386 linux,amd64 linux,arm linux,arm64 openbsd,amd64 windows,amd64 darwin,amd64 |
8 | GO_VER := go1.14 | |
8 | 9 | |
9 | 10 | default: build validation |
10 | 11 | |
18 | 19 | test: .test |
19 | 20 | |
20 | 21 | CLEAN_FILES += .test .test.tags |
22 | NO_VENDOR_DIR := $(shell find . -type f -name '*.go' ! -path './vendor*' ! -path './.git*' ! -path './.vscode*' -exec dirname "{}" \; | sort -u) | |
21 | 23 | |
22 | 24 | .test: $(SOURCE_FILES) |
23 | go test -v $$(glide novendor) && touch $@ | |
25 | go test -v $(NO_VENDOR_DIR) && touch $@ | |
24 | 26 | |
25 | 27 | .test.tags: $(SOURCE_FILES) |
26 | set -e ; for tag in $(TAGS) ; do go test -tags $$tag -v $$(glide novendor) ; done && touch $@ | |
28 | set -e ; for tag in $(TAGS) ; do go test -tags $$tag -v $(NO_VENDOR_DIR) ; done && touch $@ | |
27 | 29 | |
28 | 30 | .PHONY: lint |
29 | 31 | lint: .lint |
31 | 33 | CLEAN_FILES += .lint |
32 | 34 | |
33 | 35 | .lint: $(SOURCE_FILES) |
34 | if [[ "$(go version |awk '{ print $3 }')" =~ ^go1\.11\. ]] ; then \ | |
35 | set -e ; for dir in $$(glide novendor) ; do golint -set_exit_status $$dir ; done && touch $@ \ | |
36 | @if [ "$(findstring $(GO_VER),$(shell go version))" != "" ] ; then \ | |
37 | set -e ; for dir in $(NO_VENDOR_DIR) ; do golint -set_exit_status $$dir ; done && touch $@ \ | |
36 | 38 | else \ |
37 | touch $@ ; \ | |
39 | touch $@ ; \ | |
38 | 40 | fi |
39 | 41 | |
40 | 42 | .PHONY: vet |
43 | 45 | CLEAN_FILES += .vet .vet.tags |
44 | 46 | |
45 | 47 | .vet: $(SOURCE_FILES) |
46 | go vet $$(glide novendor) && touch $@ | |
48 | go vet $(NO_VENDOR_DIR) && touch $@ | |
47 | 49 | |
48 | 50 | .vet.tags: $(SOURCE_FILES) |
49 | set -e ; for tag in $(TAGS) ; do go vet -tags $$tag -v $$(glide novendor) ; done && touch $@ | |
51 | set -e ; for tag in $(TAGS) ; do go vet -tags $$tag -v $(NO_VENDOR_DIR) ; done && touch $@ | |
50 | 52 | |
51 | 53 | .PHONY: cli.test |
52 | 54 | cli.test: .cli.test |
66 | 68 | go build -o $(BUILD) $(BUILDPATH) |
67 | 69 | |
68 | 70 | install.tools: |
69 | go get -u -v github.com/Masterminds/glide | |
70 | if [[ "$(go version |awk '{ print $3 }')" =~ ^go1\.11\. ]] ; then go get -u golang.org/x/lint/golint ; fi | |
71 | @go get -u github.com/fatih/color ; \ | |
72 | if [ "$(findstring $(GO_VER),$(shell go version))" != "" ] ; then \ | |
73 | go get -u golang.org/x/lint/golint ;\ | |
74 | fi | |
71 | 75 | |
72 | 76 | ./bin: |
73 | 77 | mkdir -p $@ |
17 | 17 | |
18 | 18 | return Compare(dh, newDh, keywords) |
19 | 19 | } |
20 | ||
21 | // TarCheck is the tar equivalent of checking a file hierarchy spec against a | |
22 | // tar stream to determine if files have been changed. This is precisely | |
23 | // equivalent to Compare(dh, tarDH, keywords). | |
24 | func TarCheck(tarDH, dh *DirectoryHierarchy, keywords []Keyword) ([]InodeDelta, error) { | |
25 | if keywords == nil { | |
26 | return Compare(dh, tarDH, dh.UsedKeywords()) | |
27 | } | |
28 | return Compare(dh, tarDH, keywords) | |
29 | } |
28 | 28 | // have different values (or have not been set in one of the |
29 | 29 | // manifests). |
30 | 30 | Modified DifferenceType = "modified" |
31 | ||
32 | // Same represents the case where two files are the same. These are | |
33 | // only generated from CompareSame(). | |
34 | Same DifferenceType = "same" | |
31 | 35 | |
32 | 36 | // ErrorDifference represents an attempted update to the values of |
33 | 37 | // a keyword that failed |
156 | 160 | |
157 | 161 | // New returns the value of the KeyDeltaVal entry in the "new" DirectoryHierarchy |
158 | 162 | // (as determined by the ordering of parameters to Compare). Returns nil if |
159 | // there was no entry in the "old" DirectoryHierarchy. | |
163 | // there was no entry in the "new" DirectoryHierarchy. | |
160 | 164 | func (k KeyDelta) New() *string { |
161 | 165 | if k.diff == Modified || k.diff == Extra { |
162 | return sPtr(k.old) | |
166 | return sPtr(k.new) | |
163 | 167 | } |
164 | 168 | return nil |
165 | 169 | } |
304 | 308 | name: name, |
305 | 309 | old: diff.Old.Value(), |
306 | 310 | new: diff.New.Value(), |
311 | }) | |
312 | } | |
313 | } | |
314 | } | |
315 | ||
316 | return results, nil | |
317 | } | |
318 | ||
319 | // compare is the actual workhorse for Compare() and CompareSame() | |
320 | func compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword, same bool) ([]InodeDelta, error) { | |
321 | // Represents the new and old states for an entry. | |
322 | type stateT struct { | |
323 | Old *Entry | |
324 | New *Entry | |
325 | } | |
326 | ||
327 | // To deal with different orderings of the entries, use a path-keyed | |
328 | // map to make sure we don't start comparing unrelated entries. | |
329 | diffs := map[string]*stateT{} | |
330 | ||
331 | // First, iterate over the old hierarchy. If nil, pretend it's empty. | |
332 | if oldDh != nil { | |
333 | for _, e := range oldDh.Entries { | |
334 | if e.Type == RelativeType || e.Type == FullType { | |
335 | path, err := e.Path() | |
336 | if err != nil { | |
337 | return nil, err | |
338 | } | |
339 | ||
340 | // Cannot take &kv because it's the iterator. | |
341 | cEntry := new(Entry) | |
342 | *cEntry = e | |
343 | ||
344 | _, ok := diffs[path] | |
345 | if !ok { | |
346 | diffs[path] = &stateT{} | |
347 | } | |
348 | diffs[path].Old = cEntry | |
349 | } | |
350 | } | |
351 | } | |
352 | ||
353 | // Then, iterate over the new hierarchy. If nil, pretend it's empty. | |
354 | if newDh != nil { | |
355 | for _, e := range newDh.Entries { | |
356 | if e.Type == RelativeType || e.Type == FullType { | |
357 | path, err := e.Path() | |
358 | if err != nil { | |
359 | return nil, err | |
360 | } | |
361 | ||
362 | // Cannot take &kv because it's the iterator. | |
363 | cEntry := new(Entry) | |
364 | *cEntry = e | |
365 | ||
366 | _, ok := diffs[path] | |
367 | if !ok { | |
368 | diffs[path] = &stateT{} | |
369 | } | |
370 | diffs[path].New = cEntry | |
371 | } | |
372 | } | |
373 | } | |
374 | ||
375 | // Now we compute the diff. | |
376 | var results []InodeDelta | |
377 | for path, diff := range diffs { | |
378 | // Invalid | |
379 | if diff.Old == nil && diff.New == nil { | |
380 | return nil, fmt.Errorf("invalid state: both old and new are nil: path=%s", path) | |
381 | } | |
382 | ||
383 | switch { | |
384 | // Missing | |
385 | case diff.New == nil: | |
386 | results = append(results, InodeDelta{ | |
387 | diff: Missing, | |
388 | path: path, | |
389 | old: *diff.Old, | |
390 | }) | |
391 | ||
392 | // Extra | |
393 | case diff.Old == nil: | |
394 | results = append(results, InodeDelta{ | |
395 | diff: Extra, | |
396 | path: path, | |
397 | new: *diff.New, | |
398 | }) | |
399 | ||
400 | // Modified | |
401 | default: | |
402 | changed, err := compareEntry(*diff.Old, *diff.New) | |
403 | if err != nil { | |
404 | return nil, fmt.Errorf("comparison failed %s: %s", path, err) | |
405 | } | |
406 | ||
407 | // Now remove "changed" entries that don't match the keys. | |
408 | if keys != nil { | |
409 | var filterChanged []KeyDelta | |
410 | for _, keyDiff := range changed { | |
411 | if InKeywordSlice(keyDiff.name.Prefix(), keys) { | |
412 | filterChanged = append(filterChanged, keyDiff) | |
413 | } | |
414 | } | |
415 | changed = filterChanged | |
416 | } | |
417 | ||
418 | // Check if there were any actual changes. | |
419 | if len(changed) > 0 { | |
420 | results = append(results, InodeDelta{ | |
421 | diff: Modified, | |
422 | path: path, | |
423 | old: *diff.Old, | |
424 | new: *diff.New, | |
425 | keys: changed, | |
426 | }) | |
427 | } else if same { | |
428 | // this means that nothing changed, i.e. that | |
429 | // the files are the same. | |
430 | results = append(results, InodeDelta{ | |
431 | diff: Same, | |
432 | path: path, | |
433 | old: *diff.Old, | |
434 | new: *diff.New, | |
435 | keys: changed, | |
307 | 436 | }) |
308 | 437 | } |
309 | 438 | } |
331 | 460 | // NB: The order of the parameters matters (old, new) because Extra and |
332 | 461 | // Missing are considered as different discrepancy types. |
333 | 462 | func Compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, error) { |
334 | // Represents the new and old states for an entry. | |
335 | type stateT struct { | |
336 | Old *Entry | |
337 | New *Entry | |
338 | } | |
339 | ||
340 | // To deal with different orderings of the entries, use a path-keyed | |
341 | // map to make sure we don't start comparing unrelated entries. | |
342 | diffs := map[string]*stateT{} | |
343 | ||
344 | // First, iterate over the old hierarchy. If nil, pretend it's empty. | |
345 | if oldDh != nil { | |
346 | for _, e := range oldDh.Entries { | |
347 | if e.Type == RelativeType || e.Type == FullType { | |
348 | path, err := e.Path() | |
349 | if err != nil { | |
350 | return nil, err | |
351 | } | |
352 | ||
353 | // Cannot take &kv because it's the iterator. | |
354 | cEntry := new(Entry) | |
355 | *cEntry = e | |
356 | ||
357 | _, ok := diffs[path] | |
358 | if !ok { | |
359 | diffs[path] = &stateT{} | |
360 | } | |
361 | diffs[path].Old = cEntry | |
362 | } | |
363 | } | |
364 | } | |
365 | ||
366 | // Then, iterate over the new hierarchy. If nil, pretend it's empty. | |
367 | if newDh != nil { | |
368 | for _, e := range newDh.Entries { | |
369 | if e.Type == RelativeType || e.Type == FullType { | |
370 | path, err := e.Path() | |
371 | if err != nil { | |
372 | return nil, err | |
373 | } | |
374 | ||
375 | // Cannot take &kv because it's the iterator. | |
376 | cEntry := new(Entry) | |
377 | *cEntry = e | |
378 | ||
379 | _, ok := diffs[path] | |
380 | if !ok { | |
381 | diffs[path] = &stateT{} | |
382 | } | |
383 | diffs[path].New = cEntry | |
384 | } | |
385 | } | |
386 | } | |
387 | ||
388 | // Now we compute the diff. | |
389 | var results []InodeDelta | |
390 | for path, diff := range diffs { | |
391 | // Invalid | |
392 | if diff.Old == nil && diff.New == nil { | |
393 | return nil, fmt.Errorf("invalid state: both old and new are nil: path=%s", path) | |
394 | } | |
395 | ||
396 | switch { | |
397 | // Missing | |
398 | case diff.New == nil: | |
399 | results = append(results, InodeDelta{ | |
400 | diff: Missing, | |
401 | path: path, | |
402 | old: *diff.Old, | |
403 | }) | |
404 | ||
405 | // Extra | |
406 | case diff.Old == nil: | |
407 | results = append(results, InodeDelta{ | |
408 | diff: Extra, | |
409 | path: path, | |
410 | new: *diff.New, | |
411 | }) | |
412 | ||
413 | // Modified | |
414 | default: | |
415 | changed, err := compareEntry(*diff.Old, *diff.New) | |
416 | if err != nil { | |
417 | return nil, fmt.Errorf("comparison failed %s: %s", path, err) | |
418 | } | |
419 | ||
420 | // Now remove "changed" entries that don't match the keys. | |
421 | if keys != nil { | |
422 | var filterChanged []KeyDelta | |
423 | for _, keyDiff := range changed { | |
424 | if InKeywordSlice(keyDiff.name.Prefix(), keys) { | |
425 | filterChanged = append(filterChanged, keyDiff) | |
426 | } | |
427 | } | |
428 | changed = filterChanged | |
429 | } | |
430 | ||
431 | // Check if there were any actual changes. | |
432 | if len(changed) > 0 { | |
433 | results = append(results, InodeDelta{ | |
434 | diff: Modified, | |
435 | path: path, | |
436 | old: *diff.Old, | |
437 | new: *diff.New, | |
438 | keys: changed, | |
439 | }) | |
440 | } | |
441 | } | |
442 | } | |
443 | ||
444 | return results, nil | |
445 | } | |
463 | return compare(oldDh, newDh, keys, false) | |
464 | } | |
465 | ||
466 | // CompareSame is the same as Compare, except it also includes the entries | |
467 | // that are the same with a Same DifferenceType. | |
468 | func CompareSame(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, error) { | |
469 | return compare(oldDh, newDh, keys, true) | |
470 | } |
0 | hash: 8b0df7f603e6b580aa2640d99d3fa7430198f7db89321ff2abf76efa969d14c2 | |
1 | updated: 2018-08-20T07:56:40.333174254-04:00 | |
2 | imports: | |
3 | - name: github.com/fatih/color | |
4 | version: 5b77d2a35fb0ede96d138fc9a99f5c9b6aef11b4 | |
5 | - name: github.com/sirupsen/logrus | |
6 | version: 3e01752db0189b9157070a0e1668a620f9a85da2 | |
7 | - name: golang.org/x/crypto | |
8 | version: 1351f936d976c60a0a48d728281922cf63eafb8d | |
9 | subpackages: | |
10 | - ripemd160 | |
11 | - ssh/terminal | |
12 | - name: golang.org/x/sys | |
13 | version: 8dbc5d05d6edcc104950cc299a1ce6641235bc86 | |
14 | subpackages: | |
15 | - unix | |
16 | testImports: | |
17 | - name: github.com/davecgh/go-spew | |
18 | version: 8991bc29aa16c548c550c7ff78260e27b9ab7c73 | |
19 | subpackages: | |
20 | - spew |
0 | package: github.com/vbatts/go-mtree | |
1 | description: File systems verification utility and library, in likeness of mtree(8) | |
2 | homepage: https://github.com/vbatts/go-mtree | |
3 | license: BSD-3-Clause | |
4 | import: | |
5 | - package: golang.org/x/crypto | |
6 | subpackages: | |
7 | - ripemd160 | |
8 | - package: github.com/sirupsen/logrus | |
9 | version: ^1.0.0 | |
10 | - package: golang.org/x/sys | |
11 | version: 8dbc5d05d6edcc104950cc299a1ce6641235bc86 | |
12 | subpackages: | |
13 | - unix | |
14 | - package: github.com/fatih/color | |
15 | version: ^1.6.0 |
0 | module github.com/vbatts/go-mtree | |
1 | ||
2 | go 1.13 | |
3 | ||
4 | require ( | |
5 | github.com/davecgh/go-spew v1.1.1 | |
6 | github.com/fatih/color v1.12.0 // indirect | |
7 | github.com/sirupsen/logrus v1.7.0 | |
8 | golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad | |
9 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c | |
10 | ) |
0 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | |
1 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |
2 | github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= | |
3 | github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= | |
4 | github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= | |
5 | github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= | |
6 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= | |
7 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= | |
8 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | |
9 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | |
10 | github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= | |
11 | github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= | |
12 | github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= | |
13 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | |
14 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |
15 | golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= | |
16 | golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= | |
17 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |
18 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |
19 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |
20 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |
21 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |
22 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= | |
23 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |
24 | golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= | |
25 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= |
108 | 108 | t.Fatal(err) |
109 | 109 | } |
110 | 110 | |
111 | res, err := TarCheck(tdh, dh, append(DefaultKeywords, "sha1")) | |
111 | res, err := Compare(tdh, dh, append(DefaultKeywords, "sha1")) | |
112 | 112 | if err != nil { |
113 | 113 | t.Fatal(err) |
114 | 114 | } |
163 | 163 | } |
164 | 164 | |
165 | 165 | // Test the tar manifest against itself |
166 | res, err = TarCheck(tdh, tdh, []Keyword{"sha1"}) | |
166 | res, err = Compare(tdh, tdh, []Keyword{"sha1"}) | |
167 | 167 | if err != nil { |
168 | 168 | t.Fatal(err) |
169 | 169 | } |
179 | 179 | if err != nil { |
180 | 180 | t.Fatal(err) |
181 | 181 | } |
182 | res, err = TarCheck(tdh, dh, []Keyword{"sha1"}) | |
182 | res, err = Compare(tdh, dh, []Keyword{"sha1"}) | |
183 | 183 | if err != nil { |
184 | 184 | t.Fatal(err) |
185 | 185 | } |
217 | 217 | t.Fatal(err) |
218 | 218 | } |
219 | 219 | |
220 | res, err := TarCheck(tdh, tdh, []Keyword{"sha1"}) | |
220 | res, err := Compare(tdh, tdh, []Keyword{"sha1"}) | |
221 | 221 | if err != nil { |
222 | 222 | t.Fatal(err) |
223 | 223 | } |
12 | 12 | // VersionMinor is for functionality in a backwards-compatible manner |
13 | 13 | VersionMinor = 5 |
14 | 14 | // VersionPatch is for backwards-compatible bug fixes |
15 | VersionPatch = 0 | |
15 | VersionPatch = 1 | |
16 | 16 | |
17 | 17 | // VersionDev indicates development branch. Releases will be empty string. |
18 | 18 | VersionDev = "-dev" |