...

Source file src/edge-infra.dev/pkg/f8n/warehouse/oci/cmp/diff.go

Documentation: edge-infra.dev/pkg/f8n/warehouse/oci/cmp

     1  package cmp
     2  
     3  import (
     4  	v1 "github.com/google/go-containerregistry/pkg/v1"
     5  
     6  	"edge-infra.dev/pkg/f8n/warehouse/oci"
     7  	"edge-infra.dev/pkg/f8n/warehouse/oci/layer"
     8  	"edge-infra.dev/pkg/f8n/warehouse/oci/walk"
     9  )
    10  
    11  // Diff returns the list of hashes for blobs that are in a but not in any of bb.
    12  func Diff(a oci.Artifact, bb ...oci.Artifact) ([]v1.Hash, error) {
    13  	// Initial diff is entirety of a. As we encounter hashes traversing bb, we
    14  	// remove matching elements from the diff.
    15  	diff, err := toMap(a)
    16  	if err != nil {
    17  		return nil, err
    18  	}
    19  	// Calculate digest of a, if we encounter the same digest then we know a has
    20  	// no unique blobs and can exit early.
    21  	ad, err := a.Digest()
    22  	if err != nil {
    23  		return nil, err
    24  	}
    25  	hitA := false
    26  	visited := map[v1.Hash]bool{}
    27  
    28  	for _, b := range bb {
    29  		// Short circuit entire walk if we have already visited this artifact
    30  		h, err := b.Digest()
    31  		if err != nil {
    32  			return nil, err
    33  		}
    34  		if h == ad {
    35  			return nil, nil
    36  		}
    37  		if visited[h] {
    38  			continue
    39  		}
    40  
    41  		if err := walk.Walk(b, &walk.Fns{
    42  			Index: func(ii v1.ImageIndex, _ v1.ImageIndex) error {
    43  				h, err := ii.Digest()
    44  				if err != nil {
    45  					return err
    46  				}
    47  
    48  				if h == ad {
    49  					hitA = true
    50  					return walk.SkipAll
    51  				}
    52  				visited[h] = true
    53  				if diff[h] {
    54  					delete(diff, h)
    55  				}
    56  				return nil
    57  			},
    58  			Image: func(img v1.Image, _ v1.ImageIndex) error {
    59  				h, err := img.Digest()
    60  				if err != nil {
    61  					return err
    62  				}
    63  				ch, err := img.ConfigName()
    64  				if err != nil {
    65  					return err
    66  				}
    67  
    68  				if h == ad {
    69  					hitA = true
    70  					return walk.SkipAll
    71  				}
    72  				visited[h] = true
    73  				visited[ch] = true
    74  
    75  				if diff[h] {
    76  					delete(diff, h)
    77  				}
    78  				if diff[ch] {
    79  					delete(diff, ch)
    80  				}
    81  				return nil
    82  			},
    83  			Layer: func(l layer.Layer, _ v1.Image) error {
    84  				h, err := l.Digest()
    85  				if err != nil {
    86  					return err
    87  				}
    88  
    89  				visited[h] = true
    90  				if diff[h] {
    91  					delete(diff, h)
    92  				}
    93  				return nil
    94  			},
    95  		}); err != nil {
    96  			return nil, err
    97  		}
    98  
    99  		// If we have encountered every hash in a, then there are no hashes in a
   100  		// that aren't in b.
   101  		if len(diff) == 0 || hitA {
   102  			return nil, nil
   103  		}
   104  	}
   105  
   106  	// The remaining elements in diff are the unique hashes in a.
   107  	return mapToSlice(diff), nil
   108  }
   109  

View as plain text