Compare creates a diff between the given mounts and uploads the result to the content store.
(ctx context.Context, lower, upper []mount.Mount, opts ...diff.Opt)
| 60 | // Compare creates a diff between the given mounts and uploads the result |
| 61 | // to the content store. |
| 62 | func (s *walkingDiff) Compare(ctx context.Context, lower, upper []mount.Mount, opts ...diff.Opt) (d ocispec.Descriptor, err error) { |
| 63 | var config diff.Config |
| 64 | for _, opt := range opts { |
| 65 | if err := opt(&config); err != nil { |
| 66 | return emptyDesc, err |
| 67 | } |
| 68 | } |
| 69 | if tm := epoch.FromContext(ctx); tm != nil && config.SourceDateEpoch == nil { |
| 70 | config.SourceDateEpoch = tm |
| 71 | } |
| 72 | |
| 73 | var writeDiffOpts []archive.WriteDiffOpt |
| 74 | if config.SourceDateEpoch != nil { |
| 75 | writeDiffOpts = append(writeDiffOpts, archive.WithSourceDateEpoch(config.SourceDateEpoch)) |
| 76 | } |
| 77 | |
| 78 | compressionType := compression.Uncompressed |
| 79 | if config.Compressor != nil { |
| 80 | if config.MediaType == "" { |
| 81 | return emptyDesc, errors.New("media type must be explicitly specified when using custom compressor") |
| 82 | } |
| 83 | compressionType = compression.Unknown |
| 84 | } else { |
| 85 | if config.MediaType == "" { |
| 86 | config.MediaType = ocispec.MediaTypeImageLayerGzip |
| 87 | } |
| 88 | |
| 89 | switch config.MediaType { |
| 90 | case ocispec.MediaTypeImageLayer: |
| 91 | case ocispec.MediaTypeImageLayerGzip: |
| 92 | compressionType = compression.Gzip |
| 93 | case ocispec.MediaTypeImageLayerZstd: |
| 94 | compressionType = compression.Zstd |
| 95 | default: |
| 96 | return emptyDesc, fmt.Errorf("unsupported diff media type: %v: %w", config.MediaType, errdefs.ErrNotImplemented) |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | var ocidesc ocispec.Descriptor |
| 101 | if err := mount.WithTempMount(ctx, lower, func(lowerRoot string) error { |
| 102 | return mount.WithReadonlyTempMount(ctx, upper, func(upperRoot string) error { |
| 103 | var newReference bool |
| 104 | if config.Reference == "" { |
| 105 | newReference = true |
| 106 | config.Reference = uniqueRef() |
| 107 | } |
| 108 | |
| 109 | cw, err := s.store.Writer(ctx, |
| 110 | content.WithRef(config.Reference), |
| 111 | content.WithDescriptor(ocispec.Descriptor{ |
| 112 | MediaType: config.MediaType, // most contentstore implementations just ignore this |
| 113 | })) |
| 114 | if err != nil { |
| 115 | return fmt.Errorf("failed to open writer: %w", err) |
| 116 | } |
| 117 | |
| 118 | // errOpen is set when an error occurs while the content writer has not been |
| 119 | // committed or closed yet to force a cleanup |
nothing calls this directly
no test coverage detected