(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount, opts ...diff.ApplyOpt)
| 98 | } |
| 99 | |
| 100 | func (s erofsDiff) Apply(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount, opts ...diff.ApplyOpt) (d ocispec.Descriptor, err error) { |
| 101 | t1 := time.Now() |
| 102 | defer func() { |
| 103 | if err == nil { |
| 104 | log.G(ctx).WithFields(log.Fields{ |
| 105 | "d": time.Since(t1), |
| 106 | "digest": desc.Digest, |
| 107 | "size": desc.Size, |
| 108 | "media": desc.MediaType, |
| 109 | }).Debugf("diff applied") |
| 110 | } |
| 111 | }() |
| 112 | |
| 113 | var ( |
| 114 | erofsLayerType string |
| 115 | fastcopy bool |
| 116 | ) |
| 117 | diffLayerType := desc.MediaType |
| 118 | native := erofsutils.IsErofsMediaType(diffLayerType) |
| 119 | if native { |
| 120 | base, ext, hasExt := strings.Cut(diffLayerType, "+") |
| 121 | // Mimic the OCI layer for EROFS blobs for diff.NewProcessorChain(), so |
| 122 | // there is no need to bother with too much unrelated logic for now. |
| 123 | diffLayerType = ocispec.MediaTypeImageLayer |
| 124 | if hasExt { |
| 125 | // `+zstd` indicates that the original EROFS blob is additionally |
| 126 | // compressed with standard zstd streams. |
| 127 | // Only `+zstd` is considered since it is more performant than gzip |
| 128 | // and has useful features like skippable frames. |
| 129 | if ext != "zstd" { |
| 130 | return emptyDesc, fmt.Errorf("unsupported erofs layer suffix: %s", ext) |
| 131 | } |
| 132 | diffLayerType = diffLayerType + "+zstd" |
| 133 | } else { |
| 134 | fastcopy = true |
| 135 | } |
| 136 | erofsLayerType = base |
| 137 | } else if _, err := images.DiffCompression(ctx, diffLayerType); err != nil { |
| 138 | return emptyDesc, fmt.Errorf("unsupported media type: %s", desc.MediaType) |
| 139 | } |
| 140 | |
| 141 | var config diff.ApplyConfig |
| 142 | for _, o := range opts { |
| 143 | if err := o(ctx, desc, &config); err != nil { |
| 144 | return emptyDesc, fmt.Errorf("failed to apply config opt: %w", err) |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | layer, err := erofsutils.MountsToLayer(mounts) |
| 149 | if err != nil { |
| 150 | return emptyDesc, err |
| 151 | } |
| 152 | |
| 153 | ra, err := s.store.ReaderAt(ctx, desc) |
| 154 | if err != nil { |
| 155 | return emptyDesc, fmt.Errorf("failed to get reader from content store: %w", err) |
| 156 | } |
| 157 | defer ra.Close() |
nothing calls this directly
no test coverage detected