1
0
mirror of https://github.com/containers/image.git synced 2025-04-18 19:44:05 +03:00

Replace Set.Values with a non-allocating Set.All

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This commit is contained in:
Miloslav Trmač 2024-08-23 00:59:30 +02:00
parent 4c5a86a9eb
commit bc6b35d0c9
6 changed files with 36 additions and 16 deletions

View File

@ -6,6 +6,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"iter"
"maps" "maps"
"reflect" "reflect"
"slices" "slices"
@ -417,7 +418,7 @@ func (ic *imageCopier) compareImageDestinationManifestEqual(ctx context.Context,
} }
} }
algos, err := algorithmsByNames(compressionAlgos.Values()) algos, err := algorithmsByNames(compressionAlgos.All())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -552,7 +553,7 @@ func (ic *imageCopier) copyLayers(ctx context.Context) ([]compressiontypes.Algor
if srcInfosUpdated || layerDigestsDiffer(srcInfos, destInfos) { if srcInfosUpdated || layerDigestsDiffer(srcInfos, destInfos) {
ic.manifestUpdates.LayerInfos = destInfos ic.manifestUpdates.LayerInfos = destInfos
} }
algos, err := algorithmsByNames(compressionAlgos.Values()) algos, err := algorithmsByNames(compressionAlgos.All())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -988,10 +989,10 @@ func computeDiffID(stream io.Reader, decompressor compressiontypes.DecompressorF
return digest.Canonical.FromReader(stream) return digest.Canonical.FromReader(stream)
} }
// algorithmsByNames returns slice of Algorithms from slice of Algorithm Names // algorithmsByNames returns slice of Algorithms from a sequence of Algorithm Names
func algorithmsByNames(names []string) ([]compressiontypes.Algorithm, error) { func algorithmsByNames(names iter.Seq[string]) ([]compressiontypes.Algorithm, error) {
result := []compressiontypes.Algorithm{} result := []compressiontypes.Algorithm{}
for _, name := range names { for name := range names {
algo, err := compression.AlgorithmByName(name) algo, err := compression.AlgorithmByName(name)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -1,6 +1,10 @@
package set package set
import "golang.org/x/exp/maps" import (
"iter"
"golang.org/x/exp/maps"
)
// FIXME: // FIXME:
// - Docstrings // - Docstrings
@ -47,6 +51,12 @@ func (s *Set[E]) Empty() bool {
return len(s.m) == 0 return len(s.m) == 0
} }
func (s *Set[E]) Values() []E { func (s *Set[E]) All() iter.Seq[E] {
return maps.Keys(s.m) return func(yield func(E) bool) {
for _, v := range maps.Keys(s.m) {
if !yield(v) {
return
}
}
}
} }

View File

@ -1,6 +1,7 @@
package set package set
import ( import (
"slices"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -26,7 +27,7 @@ func TestAdd(t *testing.T) {
s.Add(2) // Adding an already-present element s.Add(2) // Adding an already-present element
assert.True(t, s.Contains(2)) assert.True(t, s.Contains(2))
// should not contain duplicate value of `2` // should not contain duplicate value of `2`
assert.ElementsMatch(t, []int{1, 2}, s.Values()) assert.ElementsMatch(t, []int{1, 2}, slices.Collect(s.All()))
// Unrelated elements are unaffected // Unrelated elements are unaffected
assert.True(t, s.Contains(1)) assert.True(t, s.Contains(1))
assert.False(t, s.Contains(3)) assert.False(t, s.Contains(3))
@ -36,7 +37,7 @@ func TestAddSlice(t *testing.T) {
s := NewWithValues(1) s := NewWithValues(1)
s.Add(2) s.Add(2)
s.AddSlice([]int{3, 4}) s.AddSlice([]int{3, 4})
assert.ElementsMatch(t, []int{1, 2, 3, 4}, s.Values()) assert.ElementsMatch(t, []int{1, 2, 3, 4}, slices.Collect(s.All()))
} }
func TestDelete(t *testing.T) { func TestDelete(t *testing.T) {
@ -66,12 +67,20 @@ func TestEmpty(t *testing.T) {
assert.True(t, s.Empty()) assert.True(t, s.Empty())
} }
func TestValues(t *testing.T) { func TestAll(t *testing.T) {
s := New[int]() s := New[int]()
assert.Empty(t, s.Values()) assert.Empty(t, slices.Collect(s.All()))
s.Add(1) s.Add(1)
s.Add(2) s.Add(2)
// ignore duplicate // ignore duplicate
s.Add(2) s.Add(2)
assert.ElementsMatch(t, []int{1, 2}, s.Values()) assert.ElementsMatch(t, []int{1, 2}, slices.Collect(s.All()))
// Break / return inside the range body (yield function returning false) works
var partial []int
for v := range s.All() {
partial = append(partial, v)
break
}
assert.Len(t, partial, 1)
assert.True(t, partial[0] == 1 || partial[0] == 2)
} }

View File

@ -123,7 +123,7 @@ func (ref ociReference) getBlobsToDelete(blobsUsedByDescriptorToDelete map[diges
// //
// So, NOTE: the blobPath() call below hard-codes "" even in calls where OCISharedBlobDirPath is set // So, NOTE: the blobPath() call below hard-codes "" even in calls where OCISharedBlobDirPath is set
func (ref ociReference) deleteBlobs(blobsToDelete *set.Set[digest.Digest]) error { func (ref ociReference) deleteBlobs(blobsToDelete *set.Set[digest.Digest]) error {
for _, digest := range blobsToDelete.Values() { for digest := range blobsToDelete.All() {
blobPath, err := ref.blobPath(digest, "") //Only delete in the local directory, see comment above blobPath, err := ref.blobPath(digest, "") //Only delete in the local directory, see comment above
if err != nil { if err != nil {
return err return err

View File

@ -240,7 +240,7 @@ func (mem *cache) candidateLocations(transport types.ImageTransport, scope types
if uncompressedDigest = mem.uncompressedDigestLocked(primaryDigest); uncompressedDigest != "" { if uncompressedDigest = mem.uncompressedDigestLocked(primaryDigest); uncompressedDigest != "" {
otherDigests := mem.digestsByUncompressed[uncompressedDigest] // nil if not present in the map otherDigests := mem.digestsByUncompressed[uncompressedDigest] // nil if not present in the map
if otherDigests != nil { if otherDigests != nil {
for _, d := range otherDigests.Values() { for d := range otherDigests.All() {
if d != primaryDigest && d != uncompressedDigest { if d != primaryDigest && d != uncompressedDigest {
res = mem.appendReplacementCandidates(res, transport, scope, d, v2Options) res = mem.appendReplacementCandidates(res, transport, scope, d, v2Options)
} }

View File

@ -124,7 +124,7 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
// Now use `GetCredentials` to the specific auth configs for each // Now use `GetCredentials` to the specific auth configs for each
// previously listed registry. // previously listed registry.
allCreds := make(map[string]types.DockerAuthConfig) allCreds := make(map[string]types.DockerAuthConfig)
for _, key := range allKeys.Values() { for key := range allKeys.All() {
creds, err := GetCredentials(sys, key) creds, err := GetCredentials(sys, key)
if err != nil { if err != nil {
// Note: we rely on the logging in `GetCredentials`. // Note: we rely on the logging in `GetCredentials`.