MCPcopy
hub / github.com/google/go-containerregistry / MultiWrite

Function MultiWrite

pkg/legacy/tarball/write.go:195–317  ·  view source on GitHub ↗

MultiWrite writes the contents of each image to the provided reader, in the V1 image tarball format. The contents are written in the following format: One manifest.json file at the top level containing information about several images. One repositories file mapping from the image /<repo na

(refToImage map[name.Reference]v1.Image, w io.Writer)

Source from the content-addressed store, hash-verified

193//
194// One file for the config blob, named after its SHA.
195func MultiWrite(refToImage map[name.Reference]v1.Image, w io.Writer) error {
196 tf := tar.NewWriter(w)
197 defer tf.Close()
198
199 sortedImages, imageToTags := dedupRefToImage(refToImage)
200 var m tarball.Manifest
201 repos := make(repositoriesTarDescriptor)
202
203 seenLayerIDs := make(map[string]struct{})
204 for _, img := range sortedImages {
205 tags := imageToTags[img]
206
207 // Write the config.
208 cfgName, err := img.ConfigName()
209 if err != nil {
210 return err
211 }
212 cfgFileName := fmt.Sprintf("%s.json", cfgName.Hex)
213 cfgBlob, err := img.RawConfigFile()
214 if err != nil {
215 return err
216 }
217 if err := writeTarEntry(tf, cfgFileName, bytes.NewReader(cfgBlob), int64(len(cfgBlob))); err != nil {
218 return err
219 }
220 cfg, err := img.ConfigFile()
221 if err != nil {
222 return err
223 }
224
225 // Store foreign layer info.
226 layerSources := make(map[v1.Hash]v1.Descriptor)
227
228 // Write the layers.
229 layers, err := img.Layers()
230 if err != nil {
231 return err
232 }
233 history := filterEmpty(cfg.History)
234 // Create a blank config history if the config didn't have a history.
235 if len(history) == 0 && len(layers) != 0 {
236 history = make([]v1.History, len(layers))
237 } else if len(layers) != len(history) {
238 return fmt.Errorf("image config had layer history which did not match the number of layers, got len(history)=%d, len(layers)=%d, want len(history)=len(layers)", len(history), len(layers))
239 }
240 layerFiles := make([]string, len(layers))
241 var prev *v1Layer
242 for i, l := range layers {
243 if err := updateLayerSources(layerSources, l, img); err != nil {
244 return fmt.Errorf("unable to update image metadata to include undistributable layer source information: %w", err)
245 }
246 var cur *v1Layer
247 if i < (len(layers) - 1) {
248 cur, err = newV1Layer(l, prev, history[i])
249 } else {
250 cur, err = newTopV1Layer(l, prev, history[i], cfg, cfgBlob)
251 }
252 if err != nil {

Callers 4

TestMultiWriteSameImageFunction · 0.70
TestWriteSharedLayersFunction · 0.70
WriteFunction · 0.70

Calls 15

jsonMethod · 0.95
versionMethod · 0.95
UncompressedSizeFunction · 0.92
filterEmptyFunction · 0.85
updateLayerSourcesFunction · 0.85
newV1LayerFunction · 0.85
newTopV1LayerFunction · 0.85
addTagsFunction · 0.85
dedupRefToImageFunction · 0.70
writeTarEntryFunction · 0.70
CloseMethod · 0.65
ConfigNameMethod · 0.65

Tested by 3

TestMultiWriteSameImageFunction · 0.56
TestWriteSharedLayersFunction · 0.56

Used in the wild real call sites across dependent graphs

searching dependent graphs…