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