...

Source file src/cuelabs.dev/go/oci/ociregistry/ociunify/lister.go

Documentation: cuelabs.dev/go/oci/ociregistry/ociunify

     1  // Copyright 2023 CUE Labs AG
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package ociunify
    16  
    17  import (
    18  	"context"
    19  	"errors"
    20  	"sort"
    21  	"strings"
    22  
    23  	"cuelabs.dev/go/oci/ociregistry"
    24  )
    25  
    26  func (u unifier) Repositories(ctx context.Context, startAfter string) ociregistry.Seq[string] {
    27  	r0, r1 := both(u, func(r ociregistry.Interface, _ int) ociregistry.Seq[string] {
    28  		return r.Repositories(ctx, startAfter)
    29  	})
    30  	return mergeIter(r0, r1, strings.Compare)
    31  }
    32  
    33  func (u unifier) Tags(ctx context.Context, repo, startAfter string) ociregistry.Seq[string] {
    34  	r0, r1 := both(u, func(r ociregistry.Interface, _ int) ociregistry.Seq[string] {
    35  		return r.Tags(ctx, repo, startAfter)
    36  	})
    37  	return mergeIter(r0, r1, strings.Compare)
    38  }
    39  
    40  func (u unifier) Referrers(ctx context.Context, repo string, digest ociregistry.Digest, artifactType string) ociregistry.Seq[ociregistry.Descriptor] {
    41  	r0, r1 := both(u, func(r ociregistry.Interface, _ int) ociregistry.Seq[ociregistry.Descriptor] {
    42  		return r.Referrers(ctx, repo, digest, artifactType)
    43  	})
    44  	return mergeIter(r0, r1, compareDescriptor)
    45  }
    46  
    47  func compareDescriptor(d0, d1 ociregistry.Descriptor) int {
    48  	return strings.Compare(string(d0.Digest), string(d1.Digest))
    49  }
    50  
    51  func mergeIter[T any](it0, it1 ociregistry.Seq[T], cmp func(T, T) int) ociregistry.Seq[T] {
    52  	// TODO streaming merge sort
    53  	xs0, err0 := ociregistry.All(it0)
    54  	xs1, err1 := ociregistry.All(it1)
    55  	if err0 != nil || err1 != nil {
    56  		notFound0 := errors.Is(err0, ociregistry.ErrNameUnknown)
    57  		notFound1 := errors.Is(err1, ociregistry.ErrNameUnknown)
    58  		if notFound0 && notFound1 {
    59  			return ociregistry.ErrorIter[T](err0)
    60  		}
    61  		if notFound0 {
    62  			err0 = nil
    63  		}
    64  		if notFound1 {
    65  			err1 = nil
    66  		}
    67  	}
    68  	var xs []T
    69  	if len(xs0)+len(xs1) > 0 {
    70  		xs = make([]T, len(xs0)+len(xs1))
    71  		copy(xs, xs0)
    72  		copy(xs[len(xs0):], xs1)
    73  		sort.Slice(xs, func(i, j int) bool {
    74  			return cmp(xs[i], xs[j]) < 0
    75  		})
    76  		j := 0
    77  		for i := 1; i < len(xs); i++ {
    78  			if cmp(xs[i], xs[j]) != 0 {
    79  				j++
    80  				xs[j] = xs[i]
    81  			}
    82  		}
    83  		xs = xs[:j+1]
    84  	}
    85  	err := err0
    86  	if err == nil {
    87  		err = err1
    88  	}
    89  	if err == nil {
    90  		return ociregistry.SliceIter(xs)
    91  	}
    92  	return func(yield func(T, error) bool) {
    93  		for _, x := range xs {
    94  			if !yield(x, nil) {
    95  				return
    96  			}
    97  		}
    98  		yield(*new(T), err)
    99  	}
   100  }
   101  

View as plain text