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  }