fileinfosums.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package tarsum
  2. import "sort"
  3. // FileInfoSumInterface provides an interface for accessing file checksum
  4. // information within a tar file. This info is accessed through interface
  5. // so the actual name and sum cannot be melded with.
  6. type FileInfoSumInterface interface {
  7. // File name
  8. Name() string
  9. // Checksum of this particular file and its headers
  10. Sum() string
  11. // Position of file in the tar
  12. Pos() int64
  13. }
  14. type fileInfoSum struct {
  15. name string
  16. sum string
  17. pos int64
  18. }
  19. func (fis fileInfoSum) Name() string {
  20. return fis.name
  21. }
  22. func (fis fileInfoSum) Sum() string {
  23. return fis.sum
  24. }
  25. func (fis fileInfoSum) Pos() int64 {
  26. return fis.pos
  27. }
  28. // FileInfoSums provides a list of FileInfoSumInterfaces.
  29. type FileInfoSums []FileInfoSumInterface
  30. // GetFile returns the first FileInfoSumInterface with a matching name.
  31. func (fis FileInfoSums) GetFile(name string) FileInfoSumInterface {
  32. for i := range fis {
  33. if fis[i].Name() == name {
  34. return fis[i]
  35. }
  36. }
  37. return nil
  38. }
  39. // GetAllFile returns a FileInfoSums with all matching names.
  40. func (fis FileInfoSums) GetAllFile(name string) FileInfoSums {
  41. f := FileInfoSums{}
  42. for i := range fis {
  43. if fis[i].Name() == name {
  44. f = append(f, fis[i])
  45. }
  46. }
  47. return f
  48. }
  49. // GetDuplicatePaths returns a FileInfoSums with all duplicated paths.
  50. func (fis FileInfoSums) GetDuplicatePaths() (dups FileInfoSums) {
  51. seen := make(map[string]int, len(fis)) // allocate earl. no need to grow this map.
  52. for i := range fis {
  53. f := fis[i]
  54. if _, ok := seen[f.Name()]; ok {
  55. dups = append(dups, f)
  56. } else {
  57. seen[f.Name()] = 0
  58. }
  59. }
  60. return dups
  61. }
  62. // Len returns the size of the FileInfoSums.
  63. func (fis FileInfoSums) Len() int { return len(fis) }
  64. // Swap swaps two FileInfoSum values if a FileInfoSums list.
  65. func (fis FileInfoSums) Swap(i, j int) { fis[i], fis[j] = fis[j], fis[i] }
  66. // SortByPos sorts FileInfoSums content by position.
  67. func (fis FileInfoSums) SortByPos() {
  68. sort.Sort(byPos{fis})
  69. }
  70. // SortByNames sorts FileInfoSums content by name.
  71. func (fis FileInfoSums) SortByNames() {
  72. sort.Sort(byName{fis})
  73. }
  74. // SortBySums sorts FileInfoSums content by sums.
  75. func (fis FileInfoSums) SortBySums() {
  76. dups := fis.GetDuplicatePaths()
  77. if len(dups) > 0 {
  78. sort.Sort(bySum{fis, dups})
  79. } else {
  80. sort.Sort(bySum{fis, nil})
  81. }
  82. }
  83. // byName is a sort.Sort helper for sorting by file names.
  84. // If names are the same, order them by their appearance in the tar archive
  85. type byName struct{ FileInfoSums }
  86. func (bn byName) Less(i, j int) bool {
  87. if bn.FileInfoSums[i].Name() == bn.FileInfoSums[j].Name() {
  88. return bn.FileInfoSums[i].Pos() < bn.FileInfoSums[j].Pos()
  89. }
  90. return bn.FileInfoSums[i].Name() < bn.FileInfoSums[j].Name()
  91. }
  92. // bySum is a sort.Sort helper for sorting by the sums of all the fileinfos in the tar archive
  93. type bySum struct {
  94. FileInfoSums
  95. dups FileInfoSums
  96. }
  97. func (bs bySum) Less(i, j int) bool {
  98. if bs.dups != nil && bs.FileInfoSums[i].Name() == bs.FileInfoSums[j].Name() {
  99. return bs.FileInfoSums[i].Pos() < bs.FileInfoSums[j].Pos()
  100. }
  101. return bs.FileInfoSums[i].Sum() < bs.FileInfoSums[j].Sum()
  102. }
  103. // byPos is a sort.Sort helper for sorting by the sums of all the fileinfos by their original order
  104. type byPos struct{ FileInfoSums }
  105. func (bp byPos) Less(i, j int) bool {
  106. return bp.FileInfoSums[i].Pos() < bp.FileInfoSums[j].Pos()
  107. }