Skip to content

Commit dfd62f2

Browse files
authored
Revert "Implement parallelism in deploy"
1 parent e25ff36 commit dfd62f2

File tree

6 files changed

+49
-232
lines changed

6 files changed

+49
-232
lines changed

.test/test.sh

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -168,43 +168,6 @@ if [ -n "$doDeploy" ]; then
168168
data: ("json string" | @json + "\n" | @base64),
169169
},
170170
171-
# test pushing a full, actual image (tianon/true:oci@sha256:9ef42f1d602fb423fad935aac1caa0cfdbce1ad7edce64d080a4eb7b13f7cd9d), all parts
172-
{
173-
# config blob
174-
type: "blob",
175-
refs: [$reg+"/true"],
176-
data: "ewoJImFyY2hpdGVjdHVyZSI6ICJhbWQ2NCIsCgkiY29uZmlnIjogewoJCSJDbWQiOiBbCgkJCSIvdHJ1ZSIKCQldCgl9LAoJImNyZWF0ZWQiOiAiMjAyMy0wMi0wMVQwNjo1MToxMVoiLAoJImhpc3RvcnkiOiBbCgkJewoJCQkiY3JlYXRlZCI6ICIyMDIzLTAyLTAxVDA2OjUxOjExWiIsCgkJCSJjcmVhdGVkX2J5IjogImh0dHBzOi8vZ2l0aHViLmNvbS90aWFub24vZG9ja2VyZmlsZXMvdHJlZS9tYXN0ZXIvdHJ1ZSIKCQl9CgldLAoJIm9zIjogImxpbnV4IiwKCSJyb290ZnMiOiB7CgkJImRpZmZfaWRzIjogWwoJCQkic2hhMjU2OjY1YjVhNDU5M2NjNjFkM2VhNmQzNTVmYjk3YzA0MzBkODIwZWUyMWFhODUzNWY1ZGU0NWU3NWMzMTk1NGI3NDMiCgkJXSwKCQkidHlwZSI6ICJsYXllcnMiCgl9Cn0K",
177-
},
178-
{
179-
# layer blob
180-
type: "blob",
181-
refs: [$reg+"/true"],
182-
data: "H4sIAAAAAAACAyspKk1loDEwAAJTU1MwDQTotIGhuQmcDRE3MzM0YlAwYKADKC0uSSxSUGAYoaDe1ceNiZERzmdisGMA8SoYHMB8Byx6HBgsGGA6QDQrmiwyXQPl1cDlIUG9wYaflWEUDDgAAIAGdJIABAAA",
183-
},
184-
{
185-
type: "manifest",
186-
refs: [ "oci", "latest", (range(0; 10)) | $reg+"/true:\(.)", $reg+"/foo/true:\(.)" ], # test pushing a whole bunch of tags in multiple repos
187-
lookup: {
188-
# a few explicit lookup entries for better code coverage (dep calculation during parallelization)
189-
"sha256:1c51fc286aa95d9413226599576bafa38490b1e292375c90de095855b64caea6": ($reg+"/true"),
190-
"": ($reg+"/true"),
191-
},
192-
data: {
193-
schemaVersion: 2,
194-
mediaType: "application/vnd.oci.image.manifest.v1+json",
195-
config: {
196-
mediaType: "application/vnd.oci.image.config.v1+json",
197-
digest: "sha256:25be82253336f0b8c4347bc4ecbbcdc85d0e0f118ccf8dc2e119c0a47a0a486e",
198-
size: 396,
199-
},
200-
layers: [ {
201-
mediaType: "application/vnd.oci.image.layer.v1.tar+gzip",
202-
digest: "sha256:1c51fc286aa95d9413226599576bafa38490b1e292375c90de095855b64caea6",
203-
size: 117,
204-
} ],
205-
},
206-
},
207-
208171
# test blob mounting between repositories
209172
{
210173
type: "blob",
@@ -250,7 +213,7 @@ if [ -n "$doDeploy" ]; then
250213
empty
251214
')" # stored in a variable for easier debugging ("bash -x")
252215

253-
time "$coverage/bin/deploy" <<<"$json"
216+
"$coverage/bin/deploy" <<<"$json"
254217

255218
docker rm -vf meta-scripts-test-registry
256219
trap - EXIT

cmd/deploy/input.go

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"context"
66
"encoding/json"
77
"fmt"
8-
"maps"
98

109
"github.com/docker-library/meta-scripts/registry"
1110

@@ -47,14 +46,7 @@ type inputNormalized struct {
4746
Data []byte `json:"data"`
4847
CopyFrom *registry.Reference `json:"copyFrom"`
4948

50-
// if CopyFrom is nil and Type is manifest, this will be set (used by "do")
51-
MediaType string `json:"mediaType,omitempty"`
52-
}
53-
54-
func (normal inputNormalized) clone() inputNormalized {
55-
// normal.Lookup is the only thing we have concurrency issues with, so it's the only thing we'll explicitly clone 😇
56-
normal.Lookup = maps.Clone(normal.Lookup)
57-
return normal
49+
Do func(ctx context.Context, dstRef registry.Reference) (ociregistry.Descriptor, error) `json:"-"`
5850
}
5951

6052
func normalizeInputRefs(deployType deployType, rawRefs []string) ([]registry.Reference, ociregistry.Digest, error) {
@@ -230,7 +222,6 @@ func NormalizeInput(raw inputRaw) (inputNormalized, error) {
230222
normal.Lookup[d] = ref
231223
}
232224

233-
// front-load some validation / data extraction for "normal.do" to work
234225
switch normal.Type {
235226
case typeManifest:
236227
if normal.CopyFrom == nil {
@@ -249,42 +240,33 @@ func NormalizeInput(raw inputRaw) (inputNormalized, error) {
249240
// and our logic for pushing children needs to know the mediaType (see the GHSAs referenced above)
250241
return normal, fmt.Errorf("%s: pushing manifest but missing 'mediaType'", debugId)
251242
}
252-
normal.MediaType = mediaTypeHaver.MediaType
253-
}
254-
255-
case typeBlob:
256-
if normal.CopyFrom != nil && normal.CopyFrom.Digest == "" {
257-
return normal, fmt.Errorf("%s: blobs are always by-digest, and thus need a digest: %s", debugId, normal.CopyFrom)
258-
}
259-
260-
default:
261-
panic("unknown type: " + string(normal.Type))
262-
// panic instead of error because this should've already been handled/normalized above (so this is a coding error, not a runtime error)
263-
}
264-
265-
return normal, nil
266-
}
267-
268-
// WARNING: many of these codepaths will end up writing to "normal.Lookup", which because it's a map is passed by reference, so this method is *not* safe for concurrent invocation on a single "normal" object! see "normal.clone" (above)
269-
func (normal inputNormalized) do(ctx context.Context, dstRef registry.Reference) (ociregistry.Descriptor, error) {
270-
switch normal.Type {
271-
case typeManifest:
272-
if normal.CopyFrom == nil {
273-
// TODO panic on bad data, like MediaType being empty?
274-
return registry.EnsureManifest(ctx, dstRef, normal.Data, normal.MediaType, normal.Lookup)
243+
normal.Do = func(ctx context.Context, dstRef registry.Reference) (ociregistry.Descriptor, error) {
244+
return registry.EnsureManifest(ctx, dstRef, normal.Data, mediaTypeHaver.MediaType, normal.Lookup)
245+
}
275246
} else {
276-
return registry.CopyManifest(ctx, *normal.CopyFrom, dstRef, normal.Lookup)
247+
normal.Do = func(ctx context.Context, dstRef registry.Reference) (ociregistry.Descriptor, error) {
248+
return registry.CopyManifest(ctx, *normal.CopyFrom, dstRef, normal.Lookup)
249+
}
277250
}
278251

279252
case typeBlob:
280253
if normal.CopyFrom == nil {
281-
return registry.EnsureBlob(ctx, dstRef, int64(len(normal.Data)), bytes.NewReader(normal.Data))
254+
normal.Do = func(ctx context.Context, dstRef registry.Reference) (ociregistry.Descriptor, error) {
255+
return registry.EnsureBlob(ctx, dstRef, int64(len(normal.Data)), bytes.NewReader(normal.Data))
256+
}
282257
} else {
283-
return registry.CopyBlob(ctx, *normal.CopyFrom, dstRef)
258+
if normal.CopyFrom.Digest == "" {
259+
return normal, fmt.Errorf("%s: blobs are always by-digest, and thus need a digest: %s", debugId, normal.CopyFrom)
260+
}
261+
normal.Do = func(ctx context.Context, dstRef registry.Reference) (ociregistry.Descriptor, error) {
262+
return registry.CopyBlob(ctx, *normal.CopyFrom, dstRef)
263+
}
284264
}
285265

286266
default:
287267
panic("unknown type: " + string(normal.Type))
288268
// panic instead of error because this should've already been handled/normalized above (so this is a coding error, not a runtime error)
289269
}
270+
271+
return normal, nil
290272
}

cmd/deploy/input_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ func TestNormalizeInput(t *testing.T) {
281281
"refs": [ "localhost:5000/example:test" ],
282282
"data": {"mediaType": "application/vnd.oci.image.index.v1+json"}
283283
}`,
284-
`{"type":"manifest","refs":["localhost:5000/example:test@sha256:0ae6b7b9d0bc73ee36c1adef005deb431e94cf009c6a947718b31da3d668032d"],"data":"eyJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLm9jaS5pbWFnZS5pbmRleC52MStqc29uIn0=","copyFrom":null,"mediaType":"application/vnd.oci.image.index.v1+json"}`,
284+
`{"type":"manifest","refs":["localhost:5000/example:test@sha256:0ae6b7b9d0bc73ee36c1adef005deb431e94cf009c6a947718b31da3d668032d"],"data":"eyJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLm9jaS5pbWFnZS5pbmRleC52MStqc29uIn0=","copyFrom":null}`,
285285
},
286286
{
287287
"manifest raw",
@@ -290,7 +290,7 @@ func TestNormalizeInput(t *testing.T) {
290290
"refs": [ "localhost:5000/example" ],
291291
"data": "eyJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLm9jaS5pbWFnZS5pbmRleC52MStqc29uIn0="
292292
}`,
293-
`{"type":"manifest","refs":["localhost:5000/example@sha256:0ae6b7b9d0bc73ee36c1adef005deb431e94cf009c6a947718b31da3d668032d"],"data":"eyJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLm9jaS5pbWFnZS5pbmRleC52MStqc29uIn0=","copyFrom":null,"mediaType":"application/vnd.oci.image.index.v1+json"}`,
293+
`{"type":"manifest","refs":["localhost:5000/example@sha256:0ae6b7b9d0bc73ee36c1adef005deb431e94cf009c6a947718b31da3d668032d"],"data":"eyJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLm9jaS5pbWFnZS5pbmRleC52MStqc29uIn0=","copyFrom":null}`,
294294
},
295295

296296
{
@@ -301,7 +301,7 @@ func TestNormalizeInput(t *testing.T) {
301301
"lookup": { "sha256:9ef42f1d602fb423fad935aac1caa0cfdbce1ad7edce64d080a4eb7b13f7cd9d": "tianon/true" },
302302
"data": {"mediaType": "application/vnd.oci.image.index.v1+json","manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:9ef42f1d602fb423fad935aac1caa0cfdbce1ad7edce64d080a4eb7b13f7cd9d","size":1165}],"schemaVersion":2}
303303
}`,
304-
`{"type":"manifest","refs":["localhost:5000/example:test@sha256:0cb474919526d040392883b84e5babb65a149cc605b89b117781ab94e88a5e86"],"lookup":{"sha256:9ef42f1d602fb423fad935aac1caa0cfdbce1ad7edce64d080a4eb7b13f7cd9d":"tianon/true"},"data":"eyJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLm9jaS5pbWFnZS5pbmRleC52MStqc29uIiwibWFuaWZlc3RzIjpbeyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQub2NpLmltYWdlLm1hbmlmZXN0LnYxK2pzb24iLCJkaWdlc3QiOiJzaGEyNTY6OWVmNDJmMWQ2MDJmYjQyM2ZhZDkzNWFhYzFjYWEwY2ZkYmNlMWFkN2VkY2U2NGQwODBhNGViN2IxM2Y3Y2Q5ZCIsInNpemUiOjExNjV9XSwic2NoZW1hVmVyc2lvbiI6Mn0=","copyFrom":null,"mediaType":"application/vnd.oci.image.index.v1+json"}`,
304+
`{"type":"manifest","refs":["localhost:5000/example:test@sha256:0cb474919526d040392883b84e5babb65a149cc605b89b117781ab94e88a5e86"],"lookup":{"sha256:9ef42f1d602fb423fad935aac1caa0cfdbce1ad7edce64d080a4eb7b13f7cd9d":"tianon/true"},"data":"eyJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLm9jaS5pbWFnZS5pbmRleC52MStqc29uIiwibWFuaWZlc3RzIjpbeyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQub2NpLmltYWdlLm1hbmlmZXN0LnYxK2pzb24iLCJkaWdlc3QiOiJzaGEyNTY6OWVmNDJmMWQ2MDJmYjQyM2ZhZDkzNWFhYzFjYWEwY2ZkYmNlMWFkN2VkY2U2NGQwODBhNGViN2IxM2Y3Y2Q5ZCIsInNpemUiOjExNjV9XSwic2NoZW1hVmVyc2lvbiI6Mn0=","copyFrom":null}`,
305305
},
306306
{
307307
"image",
@@ -311,7 +311,7 @@ func TestNormalizeInput(t *testing.T) {
311311
"lookup": { "": "tianon/true" },
312312
"data": {"schemaVersion":2,"mediaType":"application/vnd.docker.distribution.manifest.v2+json","config":{"mediaType":"application/vnd.docker.container.image.v1+json","size":1471,"digest":"sha256:690912094c0165c489f874c72cee4ba208c28992c0699fa6e10d8cc59f93fec9"},"layers":[{"mediaType":"application/vnd.docker.image.rootfs.diff.tar.gzip","size":129,"digest":"sha256:4c74d744397d4bcbd3079d9c82a87b80d43da376313772978134d1288f20518c"}]}
313313
}`,
314-
`{"type":"manifest","refs":["localhost:5000/example@sha256:1c70f9d471b83100c45d5a218d45bbf7e073e11ea5043758a020379a7c78f878"],"lookup":{"":"tianon/true"},"data":"eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjoxNDcxLCJkaWdlc3QiOiJzaGEyNTY6NjkwOTEyMDk0YzAxNjVjNDg5Zjg3NGM3MmNlZTRiYTIwOGMyODk5MmMwNjk5ZmE2ZTEwZDhjYzU5ZjkzZmVjOSJ9LCJsYXllcnMiOlt7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLCJzaXplIjoxMjksImRpZ2VzdCI6InNoYTI1Njo0Yzc0ZDc0NDM5N2Q0YmNiZDMwNzlkOWM4MmE4N2I4MGQ0M2RhMzc2MzEzNzcyOTc4MTM0ZDEyODhmMjA1MThjIn1dfQ==","copyFrom":null,"mediaType":"application/vnd.docker.distribution.manifest.v2+json"}`,
314+
`{"type":"manifest","refs":["localhost:5000/example@sha256:1c70f9d471b83100c45d5a218d45bbf7e073e11ea5043758a020379a7c78f878"],"lookup":{"":"tianon/true"},"data":"eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjoxNDcxLCJkaWdlc3QiOiJzaGEyNTY6NjkwOTEyMDk0YzAxNjVjNDg5Zjg3NGM3MmNlZTRiYTIwOGMyODk5MmMwNjk5ZmE2ZTEwZDhjYzU5ZjkzZmVjOSJ9LCJsYXllcnMiOlt7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLCJzaXplIjoxMjksImRpZ2VzdCI6InNoYTI1Njo0Yzc0ZDc0NDM5N2Q0YmNiZDMwNzlkOWM4MmE4N2I4MGQ0M2RhMzc2MzEzNzcyOTc4MTM0ZDEyODhmMjA1MThjIn1dfQ==","copyFrom":null}`,
315315
},
316316

317317
{

cmd/deploy/main.go

Lines changed: 15 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@ import (
77
"os"
88
"os/exec"
99
"os/signal"
10-
"sync"
11-
12-
"github.com/docker-library/meta-scripts/registry"
13-
14-
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
1510
)
1611

1712
func main() {
@@ -37,11 +32,6 @@ func main() {
3732
panic(err)
3833
}
3934

40-
// a set of RWMutex objects for synchronizing the pushing of "child" objects before their parents later in the list of documents
41-
// for every RWMutex, it will be *write*-locked during push, and *read*-locked during reading (which means we won't limit the parallelization of multiple parents after a given child is pushed, but we will stop parents from being pushed before their children)
42-
childMutexes := sync.Map{}
43-
wg := sync.WaitGroup{}
44-
4535
dec := json.NewDecoder(stdout)
4636
for dec.More() {
4737
var raw inputRaw
@@ -58,128 +48,26 @@ func main() {
5848
}
5949
refsDigest := normal.Refs[0].Digest
6050

61-
var logSuffix string = " (" + string(raw.Type) + ") "
62-
if normal.CopyFrom != nil {
63-
// normal copy (one repo/registry to another)
64-
logSuffix = " 🤝" + logSuffix + normal.CopyFrom.String()
65-
// "localhost:32774/test 🤝 (manifest) tianon/test@sha256:4077658bc7e39f02f81d1682fe49f66b3db2c420813e43f5db0c53046167c12f"
51+
if normal.CopyFrom == nil {
52+
fmt.Printf("Pushing %s %s:\n", raw.Type, refsDigest)
6653
} else {
67-
// push (raw/embedded blob or manifest data)
68-
logSuffix = " 🦾" + logSuffix + string(refsDigest)
69-
// "localhost:32774/test 🦾 (blob) sha256:1a51828d59323e0e02522c45652b6a7a44a032b464b06d574f067d2358b0e9f1"
54+
fmt.Printf("Copying %s %s:\n", raw.Type, *normal.CopyFrom)
7055
}
71-
startedPrefix := "❔ "
72-
successPrefix := "✅ "
73-
failurePrefix := "❌ "
74-
75-
// locks are per-digest, but refs might be 20 tags on the same digest, so we need to get one write lock per repo@digest and release it when the first tag completes, and every other tag needs a read lock
76-
seenRefs := map[string]bool{}
7756

7857
for _, ref := range normal.Refs {
79-
ref := ref // https://github.com/golang/go/issues/60078
80-
81-
necessaryReadLockRefs := []registry.Reference{}
82-
83-
// before parallelization, collect the pushing "child" mutex we need to lock for writing right away (but only for the first entry)
84-
var mutex *sync.RWMutex
85-
if ref.Digest != "" {
86-
lockRef := ref
87-
lockRef.Tag = ""
88-
lockRefStr := lockRef.String()
89-
if seenRefs[lockRefStr] {
90-
// if we've already seen this specific ref for this input, we need a read lock, not a write lock (since they're per-repo@digest)
91-
necessaryReadLockRefs = append(necessaryReadLockRefs, lockRef)
92-
} else {
93-
seenRefs[lockRefStr] = true
94-
lock, _ := childMutexes.LoadOrStore(lockRefStr, &sync.RWMutex{})
95-
mutex = lock.(*sync.RWMutex)
96-
// if we have a "child" mutex, lock it immediately so we don't create a race between inputs
97-
mutex.Lock() // (this gets unlocked in the goroutine below)
98-
// this is sane to lock here because interdependent inputs are required to be in-order (children first), so if this hangs it's 100% a bug in the input order
99-
}
58+
fmt.Printf(" - %s", ref.StringWithKnownDigest(refsDigest))
59+
desc, err := normal.Do(ctx, ref)
60+
if err != nil {
61+
fmt.Fprintf(os.Stderr, " -- ERROR: %v\n", err)
62+
os.Exit(1)
63+
return
10064
}
101-
102-
// make a (deep) copy of "normal" so that we can use it in a goroutine ("normal.do" is not safe for concurrent invocation)
103-
normal := normal.clone()
104-
105-
wg.Add(1)
106-
go func() {
107-
defer wg.Done()
108-
109-
if mutex != nil {
110-
defer mutex.Unlock()
111-
}
112-
113-
// before we start this job (parallelized), if it's a raw data job we need to parse the raw data and see if any of the "children" are objects we're still in the process of pushing (from a previously parallel job)
114-
if len(normal.Data) > 2 { // needs to at least be bigger than "{}" for us to care (anything else either doesn't have data or can't have children)
115-
// explicitly ignoring errors because this might not actually be JSON (or even a manifest at all!); this is best-effort
116-
// TODO optimize this by checking whether normal.Data matches "^\s*{.+}\s*$" first so we have some assurance it might work before we go further?
117-
manifestChildren, _ := registry.ParseManifestChildren(normal.Data)
118-
childDescs := []ocispec.Descriptor{}
119-
childDescs = append(childDescs, manifestChildren.Manifests...)
120-
if manifestChildren.Config != nil {
121-
childDescs = append(childDescs, *manifestChildren.Config)
122-
}
123-
childDescs = append(childDescs, manifestChildren.Layers...)
124-
for _, childDesc := range childDescs {
125-
childRef := ref
126-
childRef.Digest = childDesc.Digest
127-
necessaryReadLockRefs = append(necessaryReadLockRefs, childRef)
128-
129-
// these read locks are cheap, so let's be aggressive with our "lookup" refs too
130-
if lookupRef, ok := normal.Lookup[childDesc.Digest]; ok {
131-
lookupRef.Digest = childDesc.Digest
132-
necessaryReadLockRefs = append(necessaryReadLockRefs, lookupRef)
133-
}
134-
if fallbackRef, ok := normal.Lookup[""]; ok {
135-
fallbackRef.Digest = childDesc.Digest
136-
necessaryReadLockRefs = append(necessaryReadLockRefs, fallbackRef)
137-
}
138-
}
139-
}
140-
// we don't *know* that all the lookup references are children, but if any of them have an explicit digest, let's treat them as potential children too (which is fair, because they *are* explicit potential references that it's sane to make sure exist)
141-
for digest, lookupRef := range normal.Lookup {
142-
necessaryReadLockRefs = append(necessaryReadLockRefs, lookupRef)
143-
if digest != lookupRef.Digest {
144-
lookupRef.Digest = digest
145-
necessaryReadLockRefs = append(necessaryReadLockRefs, lookupRef)
146-
}
147-
}
148-
// if we're going to do a copy, we need to *also* include the artifact we're copying in our list
149-
if normal.CopyFrom != nil {
150-
necessaryReadLockRefs = append(necessaryReadLockRefs, *normal.CopyFrom)
151-
}
152-
// ok, we've built up a list, let's start grabbing (ro) mutexes
153-
seenChildren := map[string]bool{}
154-
for _, lockRef := range necessaryReadLockRefs {
155-
lockRef.Tag = ""
156-
if lockRef.Digest == "" {
157-
continue
158-
}
159-
lockRefStr := lockRef.String()
160-
if seenChildren[lockRefStr] {
161-
continue
162-
}
163-
seenChildren[lockRefStr] = true
164-
lock, _ := childMutexes.LoadOrStore(lockRefStr, &sync.RWMutex{})
165-
lock.(*sync.RWMutex).RLock()
166-
defer lock.(*sync.RWMutex).RUnlock()
167-
}
168-
169-
logText := ref.StringWithKnownDigest(refsDigest) + logSuffix
170-
fmt.Println(startedPrefix + logText)
171-
desc, err := normal.do(ctx, ref)
172-
if err != nil {
173-
fmt.Fprintf(os.Stderr, "%s%s -- ERROR: %v\n", failurePrefix, logText, err)
174-
panic(err) // TODO exit in a more clean way (we can't use "os.Exit" because that causes *more* errors 😭)
175-
}
176-
if ref.Digest == "" && refsDigest == "" {
177-
logText += "@" + string(desc.Digest)
178-
}
179-
fmt.Println(successPrefix + logText)
180-
}()
65+
if ref.Digest == "" && refsDigest == "" {
66+
fmt.Printf("@%s", desc.Digest)
67+
}
68+
fmt.Println()
18169
}
182-
}
18370

184-
wg.Wait()
71+
fmt.Println()
72+
}
18573
}

registry/manifest-children.go

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)