9
9
dockerArchiveTransport "github.com/containers/image/v5/docker/archive"
10
10
"github.com/containers/image/v5/docker/reference"
11
11
"github.com/containers/image/v5/manifest"
12
- ociArchiveTransport "github.com/containers/image/v5/oci/archive"
12
+ "github.com/containers/image/v5/oci/archive"
13
13
ociTransport "github.com/containers/image/v5/oci/layout"
14
14
"github.com/containers/image/v5/types"
15
15
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
@@ -46,8 +46,8 @@ func (r *Runtime) Save(ctx context.Context, names []string, format, path string,
46
46
case 1 :
47
47
// All formats support saving 1.
48
48
default :
49
- if format != "docker-archive" {
50
- return errors .Errorf ("unsupported format %q for saving multiple images (only docker-archive)" , format )
49
+ if format != "docker-archive" && format != "oci-archive" {
50
+ return errors .Errorf ("unsupported format %q for saving multiple images (only docker-archive and oci-archive )" , format )
51
51
}
52
52
if len (options .AdditionalTags ) > 0 {
53
53
return errors .Errorf ("cannot save multiple images with multiple tags" )
@@ -56,15 +56,17 @@ func (r *Runtime) Save(ctx context.Context, names []string, format, path string,
56
56
57
57
// Dispatch the save operations.
58
58
switch format {
59
- case "oci-archive" , "oci- dir" , "docker-dir" :
59
+ case "oci-dir" , "docker-dir" :
60
60
if len (names ) > 1 {
61
61
return errors .Errorf ("%q does not support saving multiple images (%v)" , format , names )
62
62
}
63
63
return r .saveSingleImage (ctx , names [0 ], format , path , options )
64
-
65
64
case "docker-archive" :
66
65
options .ManifestMIMEType = manifest .DockerV2Schema2MediaType
67
- return r .saveDockerArchive (ctx , names , path , options )
66
+ return r .saveArchive (ctx , names , format , path , options )
67
+ case "oci-archive" :
68
+ options .ManifestMIMEType = ociv1 .MediaTypeImageManifest
69
+ return r .saveArchive (ctx , names , format , path , options )
68
70
}
69
71
70
72
return errors .Errorf ("unsupported format %q for saving images" , format )
@@ -98,9 +100,6 @@ func (r *Runtime) saveSingleImage(ctx context.Context, name, format, path string
98
100
// Prepare the destination reference.
99
101
var destRef types.ImageReference
100
102
switch format {
101
- case "oci-archive" :
102
- destRef , err = ociArchiveTransport .NewReference (path , tag )
103
-
104
103
case "oci-dir" :
105
104
destRef , err = ociTransport .NewReference (path , tag )
106
105
options .ManifestMIMEType = ociv1 .MediaTypeImageManifest
@@ -132,10 +131,11 @@ func (r *Runtime) saveSingleImage(ctx context.Context, name, format, path string
132
131
// data needed to properly save images. Since multiple names could refer to
133
132
// the *same* image, we need to dance a bit and store additional "names".
134
133
// Those can then be used as additional tags when copying.
135
- func (r * Runtime ) saveDockerArchive (ctx context.Context , names []string , path string , options * SaveOptions ) error {
134
+ func (r * Runtime ) saveArchive (ctx context.Context , names []string , format , path string , options * SaveOptions ) ( finalErr error ) {
136
135
type localImage struct {
137
- image * Image
138
- tags []reference.NamedTagged
136
+ image * Image
137
+ tags []reference.NamedTagged
138
+ destNames []string
139
139
}
140
140
141
141
additionalTags := []reference.NamedTagged {}
@@ -180,47 +180,112 @@ func (r *Runtime) saveDockerArchive(ctx context.Context, names []string, path st
180
180
if withTag {
181
181
local .tags = append (local .tags , tagged )
182
182
}
183
+ local .destNames = append (local .destNames , tagged .String ())
183
184
}
184
185
localImages [image .ID ()] = local
185
186
if r .eventChannel != nil {
186
187
defer r .writeEvent (& Event {ID : image .ID (), Name : path , Time : time .Now (), Type : EventTypeImageSave })
187
188
}
188
189
}
189
190
190
- writer , err := dockerArchiveTransport .NewWriter (r .systemContextCopy (), path )
191
- if err != nil {
192
- return err
193
- }
194
- defer writer .Close ()
195
-
196
- for _ , id := range orderedIDs {
197
- local , exists := localImages [id ]
198
- if ! exists {
199
- return errors .Errorf ("internal error: saveDockerArchive: ID %s not found in local map" , id )
200
- }
201
-
202
- copyOpts := options .CopyOptions
203
- copyOpts .dockerArchiveAdditionalTags = local .tags
204
-
205
- c , err := r .newCopier (& copyOpts )
191
+ switch format {
192
+ case "docker-archive" :
193
+ writer , err := dockerArchiveTransport .NewWriter (r .systemContextCopy (), path )
206
194
if err != nil {
207
195
return err
208
196
}
209
- defer c .close ()
197
+ defer func () {
198
+ err := writer .Close ()
199
+ if err == nil {
200
+ return
201
+ }
202
+ if finalErr == nil {
203
+ finalErr = err
204
+ return
205
+ }
206
+ finalErr = errors .Wrap (finalErr , err .Error ())
207
+ }()
210
208
211
- destRef , err := writer .NewReference (nil )
212
- if err != nil {
213
- return err
209
+ for _ , id := range orderedIDs {
210
+ local , exists := localImages [id ]
211
+ if ! exists {
212
+ return errors .Errorf ("internal error: saveDockerArchive: ID %s not found in local map" , id )
213
+ }
214
+
215
+ copyOpts := options .CopyOptions
216
+ copyOpts .dockerArchiveAdditionalTags = local .tags
217
+
218
+ c , err := r .newCopier (& copyOpts )
219
+ if err != nil {
220
+ return err
221
+ }
222
+ defer c .close ()
223
+
224
+ destRef , err := writer .NewReference (nil )
225
+ if err != nil {
226
+ return err
227
+ }
228
+
229
+ srcRef , err := local .image .StorageReference ()
230
+ if err != nil {
231
+ return err
232
+ }
233
+
234
+ if _ , err := c .copy (ctx , srcRef , destRef ); err != nil {
235
+ return err
236
+ }
214
237
}
215
238
216
- srcRef , err := local .image .StorageReference ()
239
+ case "oci-archive" :
240
+ writer , err := archive .NewWriter (ctx , r .systemContextCopy (), path )
217
241
if err != nil {
218
242
return err
219
243
}
244
+ defer func () {
245
+ err := writer .Close ()
246
+ if err == nil {
247
+ return
248
+ }
249
+ if finalErr == nil {
250
+ finalErr = err
251
+ }
252
+ finalErr = errors .Wrap (finalErr , err .Error ())
253
+ }()
254
+
255
+ for _ , id := range orderedIDs {
256
+ local , exists := localImages [id ]
257
+ if ! exists {
258
+ return errors .Errorf ("internal error: saveOCIArchive: ID %s not found in local map" , id )
259
+ }
260
+
261
+ copyOpts := options .CopyOptions
262
+
263
+ c , err := r .newCopier (& copyOpts )
264
+ if err != nil {
265
+ return err
266
+ }
267
+ defer c .close ()
268
+
269
+ for _ , destName := range local .destNames {
270
+ destRef , err := writer .NewReference (destName )
271
+ if err != nil {
272
+ return err
273
+ }
274
+
275
+ srcRef , err := local .image .StorageReference ()
276
+ if err != nil {
277
+ return err
278
+ }
279
+
280
+ if _ , err := c .copy (ctx , srcRef , destRef ); err != nil {
281
+ return err
282
+ }
283
+ }
220
284
221
- if _ , err := c .copy (ctx , srcRef , destRef ); err != nil {
222
- return err
223
285
}
286
+ default :
287
+ return errors .Errorf ("some error occurred %q" , format )
288
+
224
289
}
225
290
226
291
return nil
0 commit comments