github.com/endophage/docker@v1.4.2-0.20161027011718-242853499895/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  }