github.com/rentongzhang/docker@v1.8.2-rc1/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 (fis FileInfoSums) GetDuplicatePaths() (dups FileInfoSums) { 55 seen := make(map[string]int, len(fis)) // allocate earl. no need to grow this map. 56 for i := range fis { 57 f := fis[i] 58 if _, ok := seen[f.Name()]; ok { 59 dups = append(dups, f) 60 } else { 61 seen[f.Name()] = 0 62 } 63 } 64 return dups 65 } 66 67 func (fis FileInfoSums) Len() int { return len(fis) } 68 func (fis FileInfoSums) Swap(i, j int) { fis[i], fis[j] = fis[j], fis[i] } 69 70 func (fis FileInfoSums) SortByPos() { 71 sort.Sort(byPos{fis}) 72 } 73 74 func (fis FileInfoSums) SortByNames() { 75 sort.Sort(byName{fis}) 76 } 77 78 func (fis FileInfoSums) SortBySums() { 79 dups := fis.GetDuplicatePaths() 80 if len(dups) > 0 { 81 sort.Sort(bySum{fis, dups}) 82 } else { 83 sort.Sort(bySum{fis, nil}) 84 } 85 } 86 87 // byName is a sort.Sort helper for sorting by file names. 88 // If names are the same, order them by their appearance in the tar archive 89 type byName struct{ FileInfoSums } 90 91 func (bn byName) Less(i, j int) bool { 92 if bn.FileInfoSums[i].Name() == bn.FileInfoSums[j].Name() { 93 return bn.FileInfoSums[i].Pos() < bn.FileInfoSums[j].Pos() 94 } 95 return bn.FileInfoSums[i].Name() < bn.FileInfoSums[j].Name() 96 } 97 98 // bySum is a sort.Sort helper for sorting by the sums of all the fileinfos in the tar archive 99 type bySum struct { 100 FileInfoSums 101 dups FileInfoSums 102 } 103 104 func (bs bySum) Less(i, j int) bool { 105 if bs.dups != nil && bs.FileInfoSums[i].Name() == bs.FileInfoSums[j].Name() { 106 return bs.FileInfoSums[i].Pos() < bs.FileInfoSums[j].Pos() 107 } 108 return bs.FileInfoSums[i].Sum() < bs.FileInfoSums[j].Sum() 109 } 110 111 // byPos is a sort.Sort helper for sorting by the sums of all the fileinfos by their original order 112 type byPos struct{ FileInfoSums } 113 114 func (bp byPos) Less(i, j int) bool { 115 return bp.FileInfoSums[i].Pos() < bp.FileInfoSums[j].Pos() 116 }