github.com/pmorton/docker@v1.5.0/pkg/tarsum/fileinfosums.go (about) 1 package tarsum 2 3 import "sort" 4 5 // This info will be accessed through interface so the actual name and sum cannot be medled 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 15 type fileInfoSum struct { 16 name string 17 sum string 18 pos int64 19 } 20 21 func (fis fileInfoSum) Name() string { 22 return fis.name 23 } 24 func (fis fileInfoSum) Sum() string { 25 return fis.sum 26 } 27 func (fis fileInfoSum) Pos() int64 { 28 return fis.pos 29 } 30 31 type FileInfoSums []FileInfoSumInterface 32 33 // GetFile returns the first FileInfoSumInterface with a matching name 34 func (fis FileInfoSums) GetFile(name string) FileInfoSumInterface { 35 for i := range fis { 36 if fis[i].Name() == name { 37 return fis[i] 38 } 39 } 40 return nil 41 } 42 43 // GetAllFile returns a FileInfoSums with all matching names 44 func (fis FileInfoSums) GetAllFile(name string) FileInfoSums { 45 f := FileInfoSums{} 46 for i := range fis { 47 if fis[i].Name() == name { 48 f = append(f, fis[i]) 49 } 50 } 51 return f 52 } 53 54 func contains(s []string, e string) bool { 55 for _, a := range s { 56 if a == e { 57 return true 58 } 59 } 60 return false 61 } 62 63 func (fis FileInfoSums) GetDuplicatePaths() (dups FileInfoSums) { 64 seen := make(map[string]int, len(fis)) // allocate earl. no need to grow this map. 65 for i := range fis { 66 f := fis[i] 67 if _, ok := seen[f.Name()]; ok { 68 dups = append(dups, f) 69 } else { 70 seen[f.Name()] = 0 71 } 72 } 73 return dups 74 } 75 76 func (fis FileInfoSums) Len() int { return len(fis) } 77 func (fis FileInfoSums) Swap(i, j int) { fis[i], fis[j] = fis[j], fis[i] } 78 79 func (fis FileInfoSums) SortByPos() { 80 sort.Sort(byPos{fis}) 81 } 82 83 func (fis FileInfoSums) SortByNames() { 84 sort.Sort(byName{fis}) 85 } 86 87 func (fis FileInfoSums) SortBySums() { 88 dups := fis.GetDuplicatePaths() 89 if len(dups) > 0 { 90 sort.Sort(bySum{fis, dups}) 91 } else { 92 sort.Sort(bySum{fis, nil}) 93 } 94 } 95 96 // byName is a sort.Sort helper for sorting by file names. 97 // If names are the same, order them by their appearance in the tar archive 98 type byName struct{ FileInfoSums } 99 100 func (bn byName) Less(i, j int) bool { 101 if bn.FileInfoSums[i].Name() == bn.FileInfoSums[j].Name() { 102 return bn.FileInfoSums[i].Pos() < bn.FileInfoSums[j].Pos() 103 } 104 return bn.FileInfoSums[i].Name() < bn.FileInfoSums[j].Name() 105 } 106 107 // bySum is a sort.Sort helper for sorting by the sums of all the fileinfos in the tar archive 108 type bySum struct { 109 FileInfoSums 110 dups FileInfoSums 111 } 112 113 func (bs bySum) Less(i, j int) bool { 114 if bs.dups != nil && bs.FileInfoSums[i].Name() == bs.FileInfoSums[j].Name() { 115 return bs.FileInfoSums[i].Pos() < bs.FileInfoSums[j].Pos() 116 } 117 return bs.FileInfoSums[i].Sum() < bs.FileInfoSums[j].Sum() 118 } 119 120 // byPos is a sort.Sort helper for sorting by the sums of all the fileinfos by their original order 121 type byPos struct{ FileInfoSums } 122 123 func (bp byPos) Less(i, j int) bool { 124 return bp.FileInfoSums[i].Pos() < bp.FileInfoSums[j].Pos() 125 }