github.com/slava-ustovytski/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  }