@@ -131,10 +131,10 @@ type CopyGraphOptions struct {
131131// Returns the descriptor of the root node on successful copy.
132132func Copy (ctx context.Context , src ReadOnlyTarget , srcRef string , dst Target , dstRef string , opts CopyOptions ) (ocispec.Descriptor , error ) {
133133 if src == nil {
134- return ocispec.Descriptor {}, errors .New ("nil source target" )
134+ return ocispec.Descriptor {}, newCopyError ( "Copy" , CopyErrorOriginSource , errors .New ("nil source target" ) )
135135 }
136136 if dst == nil {
137- return ocispec.Descriptor {}, errors .New ("nil destination target" )
137+ return ocispec.Descriptor {}, newCopyError ( "Copy" , CopyErrorOriginDestination , errors .New ("nil destination target" ) )
138138 }
139139 if dstRef == "" {
140140 dstRef = srcRef
@@ -147,14 +147,14 @@ func Copy(ctx context.Context, src ReadOnlyTarget, srcRef string, dst Target, ds
147147 proxy := cas .NewProxyWithLimit (src , cas .NewMemory (), opts .MaxMetadataBytes )
148148 root , err := resolveRoot (ctx , src , srcRef , proxy )
149149 if err != nil {
150- return ocispec.Descriptor {}, fmt . Errorf ( "failed to resolve %s: %w" , srcRef , err )
150+ return ocispec.Descriptor {}, err
151151 }
152152
153153 if opts .MapRoot != nil {
154154 proxy .StopCaching = true
155155 root , err = opts .MapRoot (ctx , proxy , root )
156156 if err != nil {
157- return ocispec.Descriptor {}, err
157+ return ocispec.Descriptor {}, newCopyError ( "MapRoot" , CopyErrorOriginSource , err )
158158 }
159159 proxy .StopCaching = false
160160 }
@@ -174,6 +174,12 @@ func Copy(ctx context.Context, src ReadOnlyTarget, srcRef string, dst Target, ds
174174// from the source CAS to the destination CAS.
175175// The root node (e.g. a manifest of the artifact) is identified by a descriptor.
176176func CopyGraph (ctx context.Context , src content.ReadOnlyStorage , dst content.Storage , root ocispec.Descriptor , opts CopyGraphOptions ) error {
177+ if src == nil {
178+ return newCopyError ("CopyGraph" , CopyErrorOriginSource , errors .New ("nil source target" ))
179+ }
180+ if dst == nil {
181+ return newCopyError ("CopyGraph" , CopyErrorOriginDestination , errors .New ("nil destination target" ))
182+ }
177183 return copyGraph (ctx , src , dst , root , nil , nil , nil , opts )
178184}
179185
@@ -222,7 +228,7 @@ func copyGraph(ctx context.Context, src content.ReadOnlyStorage, dst content.Sto
222228 // skip if a rooted sub-DAG exists
223229 exists , err := dst .Exists (ctx , desc )
224230 if err != nil {
225- return err
231+ return newCopyError ( "Exists" , CopyErrorOriginDestination , err )
226232 }
227233 if exists {
228234 if opts .OnCopySkipped != nil {
@@ -236,7 +242,7 @@ func copyGraph(ctx context.Context, src content.ReadOnlyStorage, dst content.Sto
236242 // find successors while non-leaf nodes will be fetched and cached
237243 successors , err := opts .FindSuccessors (ctx , proxy , desc )
238244 if err != nil {
239- return err
245+ return newCopyError ( "FindSuccessors" , CopyErrorOriginSource , err )
240246 }
241247 successors = removeForeignLayers (successors )
242248
@@ -264,7 +270,7 @@ func copyGraph(ctx context.Context, src content.ReadOnlyStorage, dst content.Sto
264270
265271 exists , err = proxy .Cache .Exists (ctx , desc )
266272 if err != nil {
267- return err
273+ return fmt . Errorf ( "failed to check cache existence: %s: %w" , desc . Digest , err )
268274 }
269275 if exists {
270276 return copyNode (ctx , proxy .Cache , dst , desc , opts )
@@ -324,7 +330,7 @@ func mountOrCopyNode(ctx context.Context, src content.ReadOnlyStorage, dst conte
324330
325331 // Mount or copy
326332 if err := mounter .Mount (ctx , desc , sourceRepository , getContent ); err != nil && ! errors .Is (err , skipSource ) {
327- return err
333+ return newCopyError ( "Mount" , CopyErrorOriginDestination , err )
328334 }
329335
330336 if ! mountFailed {
@@ -352,12 +358,12 @@ func mountOrCopyNode(ctx context.Context, src content.ReadOnlyStorage, dst conte
352358func doCopyNode (ctx context.Context , src content.ReadOnlyStorage , dst content.Storage , desc ocispec.Descriptor ) error {
353359 rc , err := src .Fetch (ctx , desc )
354360 if err != nil {
355- return err
361+ return newCopyError ( "Fetch" , CopyErrorOriginSource , err )
356362 }
357363 defer rc .Close ()
358364 err = dst .Push (ctx , desc , rc )
359365 if err != nil && ! errors .Is (err , errdef .ErrAlreadyExists ) {
360- return err
366+ return newCopyError ( "Push" , CopyErrorOriginDestination , err )
361367 }
362368 return nil
363369}
@@ -389,13 +395,13 @@ func copyNode(ctx context.Context, src content.ReadOnlyStorage, dst content.Stor
389395func copyCachedNodeWithReference (ctx context.Context , src * cas.Proxy , dst registry.ReferencePusher , desc ocispec.Descriptor , dstRef string ) error {
390396 rc , err := src .FetchCached (ctx , desc )
391397 if err != nil {
392- return err
398+ return newCopyError ( "Fetch" , CopyErrorOriginSource , err )
393399 }
394400 defer rc .Close ()
395401
396402 err = dst .PushReference (ctx , desc , rc , dstRef )
397403 if err != nil && ! errors .Is (err , errdef .ErrAlreadyExists ) {
398- return err
404+ return newCopyError ( "PushReference" , CopyErrorOriginDestination , err )
399405 }
400406 return nil
401407}
@@ -404,7 +410,11 @@ func copyCachedNodeWithReference(ctx context.Context, src *cas.Proxy, dst regist
404410func resolveRoot (ctx context.Context , src ReadOnlyTarget , srcRef string , proxy * cas.Proxy ) (ocispec.Descriptor , error ) {
405411 refFetcher , ok := src .(registry.ReferenceFetcher )
406412 if ! ok {
407- return src .Resolve (ctx , srcRef )
413+ desc , err := src .Resolve (ctx , srcRef )
414+ if err != nil {
415+ return ocispec.Descriptor {}, newCopyError ("Resolve" , CopyErrorOriginSource , err )
416+ }
417+ return desc , nil
408418 }
409419
410420 // optimize performance for ReferenceFetcher targets
@@ -414,7 +424,7 @@ func resolveRoot(ctx context.Context, src ReadOnlyTarget, srcRef string, proxy *
414424 }
415425 root , rc , err := refProxy .FetchReference (ctx , srcRef )
416426 if err != nil {
417- return ocispec.Descriptor {}, err
427+ return ocispec.Descriptor {}, newCopyError ( "FetchReference" , CopyErrorOriginSource , err )
418428 }
419429 defer rc .Close ()
420430 // cache root if it is a non-leaf node
@@ -425,7 +435,7 @@ func resolveRoot(ctx context.Context, src ReadOnlyTarget, srcRef string, proxy *
425435 return nil , errors .New ("fetching only root node expected" )
426436 })
427437 if _ , err = content .Successors (ctx , fetcher , root ); err != nil {
428- return ocispec.Descriptor {}, err
438+ return ocispec.Descriptor {}, newCopyError ( "Successors" , CopyErrorOriginSource , err )
429439 }
430440
431441 // TODO: optimize special case where root is a leaf node (i.e. a blob)
@@ -434,7 +444,7 @@ func resolveRoot(ctx context.Context, src ReadOnlyTarget, srcRef string, proxy *
434444}
435445
436446// prepareCopy prepares the hooks for copy.
437- func prepareCopy (ctx context.Context , dst Target , dstRef string , proxy * cas.Proxy , root ocispec.Descriptor , opts * CopyOptions ) error {
447+ func prepareCopy (_ context.Context , dst Target , dstRef string , proxy * cas.Proxy , root ocispec.Descriptor , opts * CopyOptions ) error {
438448 if refPusher , ok := dst .(registry.ReferencePusher ); ok {
439449 // optimize performance for ReferencePusher targets
440450 preCopy := opts .PreCopy
@@ -467,7 +477,7 @@ func prepareCopy(ctx context.Context, dst Target, dstRef string, proxy *cas.Prox
467477 if content .Equal (desc , root ) {
468478 // for root node, tag it after copying it
469479 if err := dst .Tag (ctx , root , dstRef ); err != nil {
470- return err
480+ return newCopyError ( "Tag" , CopyErrorOriginDestination , err )
471481 }
472482 }
473483 if postCopy != nil {
@@ -499,7 +509,10 @@ func prepareCopy(ctx context.Context, dst Target, dstRef string, proxy *cas.Prox
499509 return err
500510 }
501511 }
502- return dst .Tag (ctx , root , dstRef )
512+ if err := dst .Tag (ctx , root , dstRef ); err != nil {
513+ return newCopyError ("Tag" , CopyErrorOriginDestination , err )
514+ }
515+ return nil
503516 }
504517
505518 return nil
0 commit comments