Image copies image from srcRef to destRef, using policyContext to validate source image admissibility. It returns the manifest which was written to the new copy of the image.
(ctx context.Context, policyContext *signature.PolicyContext, destRef, srcRef types.ImageReference, options *Options)
| 197 | // source image admissibility. It returns the manifest which was written to |
| 198 | // the new copy of the image. |
| 199 | func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef, srcRef types.ImageReference, options *Options) (copiedManifest []byte, retErr error) { |
| 200 | if options == nil { |
| 201 | options = &Options{} |
| 202 | } |
| 203 | |
| 204 | if err := validateImageListSelection(options.ImageListSelection); err != nil { |
| 205 | return nil, err |
| 206 | } |
| 207 | |
| 208 | reportWriter := io.Discard |
| 209 | |
| 210 | if options.ReportWriter != nil { |
| 211 | reportWriter = options.ReportWriter |
| 212 | } |
| 213 | |
| 214 | // safeClose amends retErr with an error from c.Close(), if any. |
| 215 | safeClose := func(name string, c io.Closer) { |
| 216 | err := c.Close() |
| 217 | if err == nil { |
| 218 | return |
| 219 | } |
| 220 | // Do not use %w for err as we don't want it to be unwrapped by callers. |
| 221 | if retErr != nil { |
| 222 | retErr = fmt.Errorf(" (%s: %s): %w", name, err.Error(), retErr) |
| 223 | } else { |
| 224 | retErr = fmt.Errorf(" (%s: %s)", name, err.Error()) |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | publicDest, err := destRef.NewImageDestination(ctx, options.DestinationCtx) |
| 229 | if err != nil { |
| 230 | return nil, fmt.Errorf("initializing destination %s: %w", transports.ImageName(destRef), err) |
| 231 | } |
| 232 | dest := imagedestination.FromPublic(publicDest) |
| 233 | defer safeClose("dest", dest) |
| 234 | |
| 235 | publicRawSource, err := srcRef.NewImageSource(ctx, options.SourceCtx) |
| 236 | if err != nil { |
| 237 | return nil, fmt.Errorf("initializing source %s: %w", transports.ImageName(srcRef), err) |
| 238 | } |
| 239 | rawSource := imagesource.FromPublic(publicRawSource) |
| 240 | defer safeClose("src", rawSource) |
| 241 | |
| 242 | // If reportWriter is not a TTY (e.g., when piping to a file), do not |
| 243 | // print the progress bars to avoid long and hard to parse output. |
| 244 | // Instead use printCopyInfo() to print single line "Copying ..." messages. |
| 245 | progressOutput := reportWriter |
| 246 | if !isTTY(reportWriter) { |
| 247 | progressOutput = io.Discard |
| 248 | } |
| 249 | |
| 250 | c := &copier{ |
| 251 | policyContext: policyContext, |
| 252 | dest: dest, |
| 253 | rawSource: rawSource, |
| 254 | options: options, |
| 255 | |
| 256 | reportWriter: reportWriter, |
nothing calls this directly
no test coverage detected
searching dependent graphs…