Browse code

vendor: update buildkit and fsutil

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>

Tonis Tiigi authored on 2019/02/12 11:37:22
Showing 79 changed files
... ...
@@ -17,6 +17,7 @@ import (
17 17
 	units "github.com/docker/go-units"
18 18
 	"github.com/moby/buildkit/cache"
19 19
 	"github.com/moby/buildkit/cache/metadata"
20
+	"github.com/moby/buildkit/cache/remotecache"
20 21
 	registryremotecache "github.com/moby/buildkit/cache/remotecache/registry"
21 22
 	"github.com/moby/buildkit/client"
22 23
 	"github.com/moby/buildkit/control"
... ...
@@ -167,11 +168,13 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
167 167
 	}
168 168
 
169 169
 	return control.NewController(control.Opt{
170
-		SessionManager:           opt.SessionManager,
171
-		WorkerController:         wc,
172
-		Frontends:                frontends,
173
-		CacheKeyStorage:          cacheStorage,
174
-		ResolveCacheImporterFunc: registryremotecache.ResolveCacheImporterFunc(opt.SessionManager, opt.ResolverOpt),
170
+		SessionManager:   opt.SessionManager,
171
+		WorkerController: wc,
172
+		Frontends:        frontends,
173
+		CacheKeyStorage:  cacheStorage,
174
+		ResolveCacheImporterFuncs: map[string]remotecache.ResolveCacheImporterFunc{
175
+			"registry": registryremotecache.ResolveCacheImporterFunc(opt.SessionManager, opt.ResolverOpt),
176
+		},
175 177
 		// TODO: set ResolveCacheExporterFunc for exporting cache
176 178
 	})
177 179
 }
... ...
@@ -26,13 +26,14 @@ github.com/imdario/mergo v0.3.6
26 26
 golang.org/x/sync 1d60e4601c6fd243af51cc01ddf169918a5407ca
27 27
 
28 28
 # buildkit
29
-github.com/moby/buildkit 34ff9c2366a878ada7938d2f9ede71741b0a220c
30
-github.com/tonistiigi/fsutil 2862f6bc5ac9b97124e552a5c108230b38a1b0ca
29
+github.com/moby/buildkit c35410878ab9070498c66f6c67d3e8bc3b92241f
30
+github.com/tonistiigi/fsutil 1ec1983587cde7e8ac2978e354ff5360af622464
31 31
 github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
32 32
 github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7
33 33
 github.com/google/shlex 6f45313302b9c56850fc17f99e40caebce98c716
34 34
 github.com/opentracing-contrib/go-stdlib  b1a47cfbdd7543e70e9ef3e73d0802ad306cc1cc
35 35
 github.com/mitchellh/hashstructure 2bca23e0e452137f789efbc8610126fd8b94f73b
36
+github.com/gofrs/flock 7f43ea2e6a643ad441fc12d0ecc0d3388b300c53 # v0.7.0
36 37
 
37 38
 #get libnetwork packages
38 39
 
39 40
new file mode 100644
... ...
@@ -0,0 +1,492 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package content
17
+
18
+import (
19
+	"context"
20
+	"io"
21
+	"sync"
22
+
23
+	api "github.com/containerd/containerd/api/services/content/v1"
24
+	"github.com/containerd/containerd/content"
25
+	"github.com/containerd/containerd/errdefs"
26
+	"github.com/containerd/containerd/log"
27
+	"github.com/containerd/containerd/plugin"
28
+	"github.com/containerd/containerd/services"
29
+	ptypes "github.com/gogo/protobuf/types"
30
+	digest "github.com/opencontainers/go-digest"
31
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
32
+	"github.com/pkg/errors"
33
+	"github.com/sirupsen/logrus"
34
+	"google.golang.org/grpc"
35
+	"google.golang.org/grpc/codes"
36
+	"google.golang.org/grpc/status"
37
+)
38
+
39
+type service struct {
40
+	store content.Store
41
+}
42
+
43
+var bufPool = sync.Pool{
44
+	New: func() interface{} {
45
+		buffer := make([]byte, 1<<20)
46
+		return &buffer
47
+	},
48
+}
49
+
50
+var _ api.ContentServer = &service{}
51
+
52
+func init() {
53
+	plugin.Register(&plugin.Registration{
54
+		Type: plugin.GRPCPlugin,
55
+		ID:   "content",
56
+		Requires: []plugin.Type{
57
+			plugin.ServicePlugin,
58
+		},
59
+		InitFn: func(ic *plugin.InitContext) (interface{}, error) {
60
+			plugins, err := ic.GetByType(plugin.ServicePlugin)
61
+			if err != nil {
62
+				return nil, err
63
+			}
64
+			p, ok := plugins[services.ContentService]
65
+			if !ok {
66
+				return nil, errors.New("content store service not found")
67
+			}
68
+			cs, err := p.Instance()
69
+			if err != nil {
70
+				return nil, err
71
+			}
72
+			return NewService(cs.(content.Store)), nil
73
+		},
74
+	})
75
+}
76
+
77
+// NewService returns the content GRPC server
78
+func NewService(cs content.Store) api.ContentServer {
79
+	return &service{store: cs}
80
+}
81
+
82
+func (s *service) Register(server *grpc.Server) error {
83
+	api.RegisterContentServer(server, s)
84
+	return nil
85
+}
86
+
87
+func (s *service) Info(ctx context.Context, req *api.InfoRequest) (*api.InfoResponse, error) {
88
+	if err := req.Digest.Validate(); err != nil {
89
+		return nil, status.Errorf(codes.InvalidArgument, "%q failed validation", req.Digest)
90
+	}
91
+
92
+	bi, err := s.store.Info(ctx, req.Digest)
93
+	if err != nil {
94
+		return nil, errdefs.ToGRPC(err)
95
+	}
96
+
97
+	return &api.InfoResponse{
98
+		Info: infoToGRPC(bi),
99
+	}, nil
100
+}
101
+
102
+func (s *service) Update(ctx context.Context, req *api.UpdateRequest) (*api.UpdateResponse, error) {
103
+	if err := req.Info.Digest.Validate(); err != nil {
104
+		return nil, status.Errorf(codes.InvalidArgument, "%q failed validation", req.Info.Digest)
105
+	}
106
+
107
+	info, err := s.store.Update(ctx, infoFromGRPC(req.Info), req.UpdateMask.GetPaths()...)
108
+	if err != nil {
109
+		return nil, errdefs.ToGRPC(err)
110
+	}
111
+
112
+	return &api.UpdateResponse{
113
+		Info: infoToGRPC(info),
114
+	}, nil
115
+}
116
+
117
+func (s *service) List(req *api.ListContentRequest, session api.Content_ListServer) error {
118
+	var (
119
+		buffer    []api.Info
120
+		sendBlock = func(block []api.Info) error {
121
+			// send last block
122
+			return session.Send(&api.ListContentResponse{
123
+				Info: block,
124
+			})
125
+		}
126
+	)
127
+
128
+	if err := s.store.Walk(session.Context(), func(info content.Info) error {
129
+		buffer = append(buffer, api.Info{
130
+			Digest:    info.Digest,
131
+			Size_:     info.Size,
132
+			CreatedAt: info.CreatedAt,
133
+			Labels:    info.Labels,
134
+		})
135
+
136
+		if len(buffer) >= 100 {
137
+			if err := sendBlock(buffer); err != nil {
138
+				return err
139
+			}
140
+
141
+			buffer = buffer[:0]
142
+		}
143
+
144
+		return nil
145
+	}, req.Filters...); err != nil {
146
+		return err
147
+	}
148
+
149
+	if len(buffer) > 0 {
150
+		// send last block
151
+		if err := sendBlock(buffer); err != nil {
152
+			return err
153
+		}
154
+	}
155
+
156
+	return nil
157
+}
158
+
159
+func (s *service) Delete(ctx context.Context, req *api.DeleteContentRequest) (*ptypes.Empty, error) {
160
+	log.G(ctx).WithField("digest", req.Digest).Debugf("delete content")
161
+	if err := req.Digest.Validate(); err != nil {
162
+		return nil, status.Errorf(codes.InvalidArgument, err.Error())
163
+	}
164
+
165
+	if err := s.store.Delete(ctx, req.Digest); err != nil {
166
+		return nil, errdefs.ToGRPC(err)
167
+	}
168
+
169
+	return &ptypes.Empty{}, nil
170
+}
171
+
172
+func (s *service) Read(req *api.ReadContentRequest, session api.Content_ReadServer) error {
173
+	if err := req.Digest.Validate(); err != nil {
174
+		return status.Errorf(codes.InvalidArgument, "%v: %v", req.Digest, err)
175
+	}
176
+
177
+	oi, err := s.store.Info(session.Context(), req.Digest)
178
+	if err != nil {
179
+		return errdefs.ToGRPC(err)
180
+	}
181
+
182
+	ra, err := s.store.ReaderAt(session.Context(), ocispec.Descriptor{Digest: req.Digest})
183
+	if err != nil {
184
+		return errdefs.ToGRPC(err)
185
+	}
186
+	defer ra.Close()
187
+
188
+	var (
189
+		offset = req.Offset
190
+		// size is read size, not the expected size of the blob (oi.Size), which the caller might not be aware of.
191
+		// offset+size can be larger than oi.Size.
192
+		size = req.Size_
193
+
194
+		// TODO(stevvooe): Using the global buffer pool. At 32KB, it is probably
195
+		// little inefficient for work over a fast network. We can tune this later.
196
+		p = bufPool.Get().(*[]byte)
197
+	)
198
+	defer bufPool.Put(p)
199
+
200
+	if offset < 0 {
201
+		offset = 0
202
+	}
203
+
204
+	if offset > oi.Size {
205
+		return status.Errorf(codes.OutOfRange, "read past object length %v bytes", oi.Size)
206
+	}
207
+
208
+	if size <= 0 || offset+size > oi.Size {
209
+		size = oi.Size - offset
210
+	}
211
+
212
+	_, err = io.CopyBuffer(
213
+		&readResponseWriter{session: session},
214
+		io.NewSectionReader(ra, offset, size), *p)
215
+	return errdefs.ToGRPC(err)
216
+}
217
+
218
+// readResponseWriter is a writer that places the output into ReadContentRequest messages.
219
+//
220
+// This allows io.CopyBuffer to do the heavy lifting of chunking the responses
221
+// into the buffer size.
222
+type readResponseWriter struct {
223
+	offset  int64
224
+	session api.Content_ReadServer
225
+}
226
+
227
+func (rw *readResponseWriter) Write(p []byte) (n int, err error) {
228
+	if err := rw.session.Send(&api.ReadContentResponse{
229
+		Offset: rw.offset,
230
+		Data:   p,
231
+	}); err != nil {
232
+		return 0, err
233
+	}
234
+
235
+	rw.offset += int64(len(p))
236
+	return len(p), nil
237
+}
238
+
239
+func (s *service) Status(ctx context.Context, req *api.StatusRequest) (*api.StatusResponse, error) {
240
+	status, err := s.store.Status(ctx, req.Ref)
241
+	if err != nil {
242
+		return nil, errdefs.ToGRPCf(err, "could not get status for ref %q", req.Ref)
243
+	}
244
+
245
+	var resp api.StatusResponse
246
+	resp.Status = &api.Status{
247
+		StartedAt: status.StartedAt,
248
+		UpdatedAt: status.UpdatedAt,
249
+		Ref:       status.Ref,
250
+		Offset:    status.Offset,
251
+		Total:     status.Total,
252
+		Expected:  status.Expected,
253
+	}
254
+
255
+	return &resp, nil
256
+}
257
+
258
+func (s *service) ListStatuses(ctx context.Context, req *api.ListStatusesRequest) (*api.ListStatusesResponse, error) {
259
+	statuses, err := s.store.ListStatuses(ctx, req.Filters...)
260
+	if err != nil {
261
+		return nil, errdefs.ToGRPC(err)
262
+	}
263
+
264
+	var resp api.ListStatusesResponse
265
+	for _, status := range statuses {
266
+		resp.Statuses = append(resp.Statuses, api.Status{
267
+			StartedAt: status.StartedAt,
268
+			UpdatedAt: status.UpdatedAt,
269
+			Ref:       status.Ref,
270
+			Offset:    status.Offset,
271
+			Total:     status.Total,
272
+			Expected:  status.Expected,
273
+		})
274
+	}
275
+
276
+	return &resp, nil
277
+}
278
+
279
+func (s *service) Write(session api.Content_WriteServer) (err error) {
280
+	var (
281
+		ctx      = session.Context()
282
+		msg      api.WriteContentResponse
283
+		req      *api.WriteContentRequest
284
+		ref      string
285
+		total    int64
286
+		expected digest.Digest
287
+	)
288
+
289
+	defer func(msg *api.WriteContentResponse) {
290
+		// pump through the last message if no error was encountered
291
+		if err != nil {
292
+			if s, ok := status.FromError(err); ok && s.Code() != codes.AlreadyExists {
293
+				// TODO(stevvooe): Really need a log line here to track which
294
+				// errors are actually causing failure on the server side. May want
295
+				// to configure the service with an interceptor to make this work
296
+				// identically across all GRPC methods.
297
+				//
298
+				// This is pretty noisy, so we can remove it but leave it for now.
299
+				log.G(ctx).WithError(err).Error("(*service).Write failed")
300
+			}
301
+
302
+			return
303
+		}
304
+
305
+		err = session.Send(msg)
306
+	}(&msg)
307
+
308
+	// handle the very first request!
309
+	req, err = session.Recv()
310
+	if err != nil {
311
+		return err
312
+	}
313
+
314
+	ref = req.Ref
315
+
316
+	if ref == "" {
317
+		return status.Errorf(codes.InvalidArgument, "first message must have a reference")
318
+	}
319
+
320
+	fields := logrus.Fields{
321
+		"ref": ref,
322
+	}
323
+	total = req.Total
324
+	expected = req.Expected
325
+	if total > 0 {
326
+		fields["total"] = total
327
+	}
328
+
329
+	if expected != "" {
330
+		fields["expected"] = expected
331
+	}
332
+
333
+	ctx = log.WithLogger(ctx, log.G(ctx).WithFields(fields))
334
+
335
+	log.G(ctx).Debug("(*service).Write started")
336
+	// this action locks the writer for the session.
337
+	wr, err := s.store.Writer(ctx,
338
+		content.WithRef(ref),
339
+		content.WithDescriptor(ocispec.Descriptor{Size: total, Digest: expected}))
340
+	if err != nil {
341
+		return errdefs.ToGRPC(err)
342
+	}
343
+	defer wr.Close()
344
+
345
+	for {
346
+		msg.Action = req.Action
347
+		ws, err := wr.Status()
348
+		if err != nil {
349
+			return errdefs.ToGRPC(err)
350
+		}
351
+
352
+		msg.Offset = ws.Offset // always set the offset.
353
+
354
+		// NOTE(stevvooe): In general, there are two cases underwhich a remote
355
+		// writer is used.
356
+		//
357
+		// For pull, we almost always have this before fetching large content,
358
+		// through descriptors. We allow predeclaration of the expected size
359
+		// and digest.
360
+		//
361
+		// For push, it is more complex. If we want to cut through content into
362
+		// storage, we may have no expectation until we are done processing the
363
+		// content. The case here is the following:
364
+		//
365
+		// 	1. Start writing content.
366
+		// 	2. Compress inline.
367
+		// 	3. Validate digest and size (maybe).
368
+		//
369
+		// Supporting these two paths is quite awkward but it lets both API
370
+		// users use the same writer style for each with a minimum of overhead.
371
+		if req.Expected != "" {
372
+			if expected != "" && expected != req.Expected {
373
+				log.G(ctx).Debugf("commit digest differs from writer digest: %v != %v", req.Expected, expected)
374
+			}
375
+			expected = req.Expected
376
+
377
+			if _, err := s.store.Info(session.Context(), req.Expected); err == nil {
378
+				if err := wr.Close(); err != nil {
379
+					log.G(ctx).WithError(err).Error("failed to close writer")
380
+				}
381
+				if err := s.store.Abort(session.Context(), ref); err != nil {
382
+					log.G(ctx).WithError(err).Error("failed to abort write")
383
+				}
384
+
385
+				return status.Errorf(codes.AlreadyExists, "blob with expected digest %v exists", req.Expected)
386
+			}
387
+		}
388
+
389
+		if req.Total > 0 {
390
+			// Update the expected total. Typically, this could be seen at
391
+			// negotiation time or on a commit message.
392
+			if total > 0 && req.Total != total {
393
+				log.G(ctx).Debugf("commit size differs from writer size: %v != %v", req.Total, total)
394
+			}
395
+			total = req.Total
396
+		}
397
+
398
+		switch req.Action {
399
+		case api.WriteActionStat:
400
+			msg.Digest = wr.Digest()
401
+			msg.StartedAt = ws.StartedAt
402
+			msg.UpdatedAt = ws.UpdatedAt
403
+			msg.Total = total
404
+		case api.WriteActionWrite, api.WriteActionCommit:
405
+			if req.Offset > 0 {
406
+				// validate the offset if provided
407
+				if req.Offset != ws.Offset {
408
+					return status.Errorf(codes.OutOfRange, "write @%v must occur at current offset %v", req.Offset, ws.Offset)
409
+				}
410
+			}
411
+
412
+			if req.Offset == 0 && ws.Offset > 0 {
413
+				if err := wr.Truncate(req.Offset); err != nil {
414
+					return errors.Wrapf(err, "truncate failed")
415
+				}
416
+				msg.Offset = req.Offset
417
+			}
418
+
419
+			// issue the write if we actually have data.
420
+			if len(req.Data) > 0 {
421
+				// While this looks like we could use io.WriterAt here, because we
422
+				// maintain the offset as append only, we just issue the write.
423
+				n, err := wr.Write(req.Data)
424
+				if err != nil {
425
+					return errdefs.ToGRPC(err)
426
+				}
427
+
428
+				if n != len(req.Data) {
429
+					// TODO(stevvooe): Perhaps, we can recover this by including it
430
+					// in the offset on the write return.
431
+					return status.Errorf(codes.DataLoss, "wrote %v of %v bytes", n, len(req.Data))
432
+				}
433
+
434
+				msg.Offset += int64(n)
435
+			}
436
+
437
+			if req.Action == api.WriteActionCommit {
438
+				var opts []content.Opt
439
+				if req.Labels != nil {
440
+					opts = append(opts, content.WithLabels(req.Labels))
441
+				}
442
+				if err := wr.Commit(ctx, total, expected, opts...); err != nil {
443
+					return errdefs.ToGRPC(err)
444
+				}
445
+			}
446
+
447
+			msg.Digest = wr.Digest()
448
+		}
449
+
450
+		if err := session.Send(&msg); err != nil {
451
+			return err
452
+		}
453
+
454
+		req, err = session.Recv()
455
+		if err != nil {
456
+			if err == io.EOF {
457
+				return nil
458
+			}
459
+
460
+			return err
461
+		}
462
+	}
463
+}
464
+
465
+func (s *service) Abort(ctx context.Context, req *api.AbortRequest) (*ptypes.Empty, error) {
466
+	if err := s.store.Abort(ctx, req.Ref); err != nil {
467
+		return nil, errdefs.ToGRPC(err)
468
+	}
469
+
470
+	return &ptypes.Empty{}, nil
471
+}
472
+
473
+func infoToGRPC(info content.Info) api.Info {
474
+	return api.Info{
475
+		Digest:    info.Digest,
476
+		Size_:     info.Size,
477
+		CreatedAt: info.CreatedAt,
478
+		UpdatedAt: info.UpdatedAt,
479
+		Labels:    info.Labels,
480
+	}
481
+}
482
+
483
+func infoFromGRPC(info api.Info) content.Info {
484
+	return content.Info{
485
+		Digest:    info.Digest,
486
+		Size:      info.Size_,
487
+		CreatedAt: info.CreatedAt,
488
+		UpdatedAt: info.UpdatedAt,
489
+		Labels:    info.Labels,
490
+	}
491
+}
0 492
new file mode 100644
... ...
@@ -0,0 +1,71 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package content
17
+
18
+import (
19
+	"context"
20
+
21
+	eventstypes "github.com/containerd/containerd/api/events"
22
+	"github.com/containerd/containerd/content"
23
+	"github.com/containerd/containerd/events"
24
+	"github.com/containerd/containerd/metadata"
25
+	"github.com/containerd/containerd/plugin"
26
+	"github.com/containerd/containerd/services"
27
+	digest "github.com/opencontainers/go-digest"
28
+)
29
+
30
+// store wraps content.Store with proper event published.
31
+type store struct {
32
+	content.Store
33
+	publisher events.Publisher
34
+}
35
+
36
+func init() {
37
+	plugin.Register(&plugin.Registration{
38
+		Type: plugin.ServicePlugin,
39
+		ID:   services.ContentService,
40
+		Requires: []plugin.Type{
41
+			plugin.MetadataPlugin,
42
+		},
43
+		InitFn: func(ic *plugin.InitContext) (interface{}, error) {
44
+			m, err := ic.Get(plugin.MetadataPlugin)
45
+			if err != nil {
46
+				return nil, err
47
+			}
48
+
49
+			s, err := newContentStore(m.(*metadata.DB).ContentStore(), ic.Events)
50
+			return s, err
51
+		},
52
+	})
53
+}
54
+
55
+func newContentStore(cs content.Store, publisher events.Publisher) (content.Store, error) {
56
+	return &store{
57
+		Store:     cs,
58
+		publisher: publisher,
59
+	}, nil
60
+}
61
+
62
+func (s *store) Delete(ctx context.Context, dgst digest.Digest) error {
63
+	if err := s.Store.Delete(ctx, dgst); err != nil {
64
+		return err
65
+	}
66
+	// TODO: Consider whether we should return error here.
67
+	return s.publisher.Publish(ctx, "/content/delete", &eventstypes.ContentDelete{
68
+		Digest: dgst,
69
+	})
70
+}
0 71
new file mode 100644
... ...
@@ -0,0 +1,36 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package services
17
+
18
+const (
19
+	// ContentService is id of content service.
20
+	ContentService = "content-service"
21
+	// SnapshotsService is id of snapshots service.
22
+	SnapshotsService = "snapshots-service"
23
+	// ImagesService is id of images service.
24
+	ImagesService = "images-service"
25
+	// ContainersService is id of containers service.
26
+	ContainersService = "containers-service"
27
+	// TasksService is id of tasks service.
28
+	TasksService = "tasks-service"
29
+	// NamespacesService is id of namespaces service.
30
+	NamespacesService = "namespaces-service"
31
+	// LeasesService is id of leases service.
32
+	LeasesService = "leases-service"
33
+	// DiffService is id of diff service.
34
+	DiffService = "diff-service"
35
+)
0 36
new file mode 100644
... ...
@@ -0,0 +1,27 @@
0
+Copyright (c) 2015, Tim Heckman
1
+All rights reserved.
2
+
3
+Redistribution and use in source and binary forms, with or without
4
+modification, are permitted provided that the following conditions are met:
5
+
6
+* Redistributions of source code must retain the above copyright notice, this
7
+  list of conditions and the following disclaimer.
8
+
9
+* Redistributions in binary form must reproduce the above copyright notice,
10
+  this list of conditions and the following disclaimer in the documentation
11
+  and/or other materials provided with the distribution.
12
+
13
+* Neither the name of linode-netint nor the names of its
14
+  contributors may be used to endorse or promote products derived from
15
+  this software without specific prior written permission.
16
+
17
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0 27
new file mode 100644
... ...
@@ -0,0 +1,40 @@
0
+# flock
1
+[![TravisCI Build Status](https://img.shields.io/travis/gofrs/flock/master.svg?style=flat)](https://travis-ci.org/gofrs/flock)
2
+[![GoDoc](https://img.shields.io/badge/godoc-go--flock-blue.svg?style=flat)](https://godoc.org/github.com/gofrs/flock)
3
+[![License](https://img.shields.io/badge/license-BSD_3--Clause-brightgreen.svg?style=flat)](https://github.com/gofrs/flock/blob/master/LICENSE)
4
+
5
+`flock` implements a thread-safe sync.Locker interface for file locking. It also
6
+includes a non-blocking TryLock() function to allow locking without blocking execution.
7
+
8
+## License
9
+`flock` is released under the BSD 3-Clause License. See the `LICENSE` file for more details.
10
+
11
+## Go Compatibility
12
+This package makes use of the `context` package that was introduced in Go 1.7. As such, this
13
+package has an implicit dependency on Go 1.7+.
14
+
15
+## Installation
16
+```
17
+go get -u github.com/gofrs/flock
18
+```
19
+
20
+## Usage
21
+```Go
22
+import "github.com/gofrs/flock"
23
+
24
+fileLock := flock.New("/var/lock/go-lock.lock")
25
+
26
+locked, err := fileLock.TryLock()
27
+
28
+if err != nil {
29
+	// handle locking error
30
+}
31
+
32
+if locked {
33
+	// do work
34
+	fileLock.Unlock()
35
+}
36
+```
37
+
38
+For more detailed usage information take a look at the package API docs on
39
+[GoDoc](https://godoc.org/github.com/gofrs/flock).
0 40
new file mode 100644
... ...
@@ -0,0 +1,127 @@
0
+// Copyright 2015 Tim Heckman. All rights reserved.
1
+// Use of this source code is governed by the BSD 3-Clause
2
+// license that can be found in the LICENSE file.
3
+
4
+// Package flock implements a thread-safe sync.Locker interface for file locking.
5
+// It also includes a non-blocking TryLock() function to allow locking
6
+// without blocking execution.
7
+//
8
+// Package flock is released under the BSD 3-Clause License. See the LICENSE file
9
+// for more details.
10
+//
11
+// While using this library, remember that the locking behaviors are not
12
+// guaranteed to be the same on each platform. For example, some UNIX-like
13
+// operating systems will transparently convert a shared lock to an exclusive
14
+// lock. If you Unlock() the flock from a location where you believe that you
15
+// have the shared lock, you may accidently drop the exclusive lock.
16
+package flock
17
+
18
+import (
19
+	"context"
20
+	"os"
21
+	"sync"
22
+	"time"
23
+)
24
+
25
+// Flock is the struct type to handle file locking. All fields are unexported,
26
+// with access to some of the fields provided by getter methods (Path() and Locked()).
27
+type Flock struct {
28
+	path string
29
+	m    sync.RWMutex
30
+	fh   *os.File
31
+	l    bool
32
+	r    bool
33
+}
34
+
35
+// New returns a new instance of *Flock. The only parameter
36
+// it takes is the path to the desired lockfile.
37
+func New(path string) *Flock {
38
+	return &Flock{path: path}
39
+}
40
+
41
+// NewFlock returns a new instance of *Flock. The only parameter
42
+// it takes is the path to the desired lockfile.
43
+//
44
+// Deprecated: Use New instead.
45
+func NewFlock(path string) *Flock {
46
+	return New(path)
47
+}
48
+
49
+// Close is equivalent to calling Unlock.
50
+//
51
+// This will release the lock and close the underlying file descriptor.
52
+// It will not remove the file from disk, that's up to your application.
53
+func (f *Flock) Close() error {
54
+	return f.Unlock()
55
+}
56
+
57
+// Path returns the path as provided in NewFlock().
58
+func (f *Flock) Path() string {
59
+	return f.path
60
+}
61
+
62
+// Locked returns the lock state (locked: true, unlocked: false).
63
+//
64
+// Warning: by the time you use the returned value, the state may have changed.
65
+func (f *Flock) Locked() bool {
66
+	f.m.RLock()
67
+	defer f.m.RUnlock()
68
+	return f.l
69
+}
70
+
71
+// RLocked returns the read lock state (locked: true, unlocked: false).
72
+//
73
+// Warning: by the time you use the returned value, the state may have changed.
74
+func (f *Flock) RLocked() bool {
75
+	f.m.RLock()
76
+	defer f.m.RUnlock()
77
+	return f.r
78
+}
79
+
80
+func (f *Flock) String() string {
81
+	return f.path
82
+}
83
+
84
+// TryLockContext repeatedly tries to take an exclusive lock until one of the
85
+// conditions is met: TryLock succeeds, TryLock fails with error, or Context
86
+// Done channel is closed.
87
+func (f *Flock) TryLockContext(ctx context.Context, retryDelay time.Duration) (bool, error) {
88
+	return tryCtx(f.TryLock, ctx, retryDelay)
89
+}
90
+
91
+// TryRLockContext repeatedly tries to take a shared lock until one of the
92
+// conditions is met: TryRLock succeeds, TryRLock fails with error, or Context
93
+// Done channel is closed.
94
+func (f *Flock) TryRLockContext(ctx context.Context, retryDelay time.Duration) (bool, error) {
95
+	return tryCtx(f.TryRLock, ctx, retryDelay)
96
+}
97
+
98
+func tryCtx(fn func() (bool, error), ctx context.Context, retryDelay time.Duration) (bool, error) {
99
+	if ctx.Err() != nil {
100
+		return false, ctx.Err()
101
+	}
102
+	for {
103
+		if ok, err := fn(); ok || err != nil {
104
+			return ok, err
105
+		}
106
+		select {
107
+		case <-ctx.Done():
108
+			return false, ctx.Err()
109
+		case <-time.After(retryDelay):
110
+			// try again
111
+		}
112
+	}
113
+}
114
+
115
+func (f *Flock) setFh() error {
116
+	// open a new os.File instance
117
+	// create it if it doesn't exist, and open the file read-only.
118
+	fh, err := os.OpenFile(f.path, os.O_CREATE|os.O_RDONLY, os.FileMode(0600))
119
+	if err != nil {
120
+		return err
121
+	}
122
+
123
+	// set the filehandle on the struct
124
+	f.fh = fh
125
+	return nil
126
+}
0 127
new file mode 100644
... ...
@@ -0,0 +1,195 @@
0
+// Copyright 2015 Tim Heckman. All rights reserved.
1
+// Use of this source code is governed by the BSD 3-Clause
2
+// license that can be found in the LICENSE file.
3
+
4
+// +build !windows
5
+
6
+package flock
7
+
8
+import (
9
+	"os"
10
+	"syscall"
11
+)
12
+
13
+// Lock is a blocking call to try and take an exclusive file lock. It will wait
14
+// until it is able to obtain the exclusive file lock. It's recommended that
15
+// TryLock() be used over this function. This function may block the ability to
16
+// query the current Locked() or RLocked() status due to a RW-mutex lock.
17
+//
18
+// If we are already exclusive-locked, this function short-circuits and returns
19
+// immediately assuming it can take the mutex lock.
20
+//
21
+// If the *Flock has a shared lock (RLock), this may transparently replace the
22
+// shared lock with an exclusive lock on some UNIX-like operating systems. Be
23
+// careful when using exclusive locks in conjunction with shared locks
24
+// (RLock()), because calling Unlock() may accidentally release the exclusive
25
+// lock that was once a shared lock.
26
+func (f *Flock) Lock() error {
27
+	return f.lock(&f.l, syscall.LOCK_EX)
28
+}
29
+
30
+// RLock is a blocking call to try and take a shared file lock. It will wait
31
+// until it is able to obtain the shared file lock. It's recommended that
32
+// TryRLock() be used over this function. This function may block the ability to
33
+// query the current Locked() or RLocked() status due to a RW-mutex lock.
34
+//
35
+// If we are already shared-locked, this function short-circuits and returns
36
+// immediately assuming it can take the mutex lock.
37
+func (f *Flock) RLock() error {
38
+	return f.lock(&f.r, syscall.LOCK_SH)
39
+}
40
+
41
+func (f *Flock) lock(locked *bool, flag int) error {
42
+	f.m.Lock()
43
+	defer f.m.Unlock()
44
+
45
+	if *locked {
46
+		return nil
47
+	}
48
+
49
+	if f.fh == nil {
50
+		if err := f.setFh(); err != nil {
51
+			return err
52
+		}
53
+	}
54
+
55
+	if err := syscall.Flock(int(f.fh.Fd()), flag); err != nil {
56
+		shouldRetry, reopenErr := f.reopenFDOnError(err)
57
+		if reopenErr != nil {
58
+			return reopenErr
59
+		}
60
+
61
+		if !shouldRetry {
62
+			return err
63
+		}
64
+
65
+		if err = syscall.Flock(int(f.fh.Fd()), flag); err != nil {
66
+			return err
67
+		}
68
+	}
69
+
70
+	*locked = true
71
+	return nil
72
+}
73
+
74
+// Unlock is a function to unlock the file. This file takes a RW-mutex lock, so
75
+// while it is running the Locked() and RLocked() functions will be blocked.
76
+//
77
+// This function short-circuits if we are unlocked already. If not, it calls
78
+// syscall.LOCK_UN on the file and closes the file descriptor. It does not
79
+// remove the file from disk. It's up to your application to do.
80
+//
81
+// Please note, if your shared lock became an exclusive lock this may
82
+// unintentionally drop the exclusive lock if called by the consumer that
83
+// believes they have a shared lock. Please see Lock() for more details.
84
+func (f *Flock) Unlock() error {
85
+	f.m.Lock()
86
+	defer f.m.Unlock()
87
+
88
+	// if we aren't locked or if the lockfile instance is nil
89
+	// just return a nil error because we are unlocked
90
+	if (!f.l && !f.r) || f.fh == nil {
91
+		return nil
92
+	}
93
+
94
+	// mark the file as unlocked
95
+	if err := syscall.Flock(int(f.fh.Fd()), syscall.LOCK_UN); err != nil {
96
+		return err
97
+	}
98
+
99
+	f.fh.Close()
100
+
101
+	f.l = false
102
+	f.r = false
103
+	f.fh = nil
104
+
105
+	return nil
106
+}
107
+
108
+// TryLock is the preferred function for taking an exclusive file lock. This
109
+// function takes an RW-mutex lock before it tries to lock the file, so there is
110
+// the possibility that this function may block for a short time if another
111
+// goroutine is trying to take any action.
112
+//
113
+// The actual file lock is non-blocking. If we are unable to get the exclusive
114
+// file lock, the function will return false instead of waiting for the lock. If
115
+// we get the lock, we also set the *Flock instance as being exclusive-locked.
116
+func (f *Flock) TryLock() (bool, error) {
117
+	return f.try(&f.l, syscall.LOCK_EX)
118
+}
119
+
120
+// TryRLock is the preferred function for taking a shared file lock. This
121
+// function takes an RW-mutex lock before it tries to lock the file, so there is
122
+// the possibility that this function may block for a short time if another
123
+// goroutine is trying to take any action.
124
+//
125
+// The actual file lock is non-blocking. If we are unable to get the shared file
126
+// lock, the function will return false instead of waiting for the lock. If we
127
+// get the lock, we also set the *Flock instance as being share-locked.
128
+func (f *Flock) TryRLock() (bool, error) {
129
+	return f.try(&f.r, syscall.LOCK_SH)
130
+}
131
+
132
+func (f *Flock) try(locked *bool, flag int) (bool, error) {
133
+	f.m.Lock()
134
+	defer f.m.Unlock()
135
+
136
+	if *locked {
137
+		return true, nil
138
+	}
139
+
140
+	if f.fh == nil {
141
+		if err := f.setFh(); err != nil {
142
+			return false, err
143
+		}
144
+	}
145
+
146
+	var retried bool
147
+retry:
148
+	err := syscall.Flock(int(f.fh.Fd()), flag|syscall.LOCK_NB)
149
+
150
+	switch err {
151
+	case syscall.EWOULDBLOCK:
152
+		return false, nil
153
+	case nil:
154
+		*locked = true
155
+		return true, nil
156
+	}
157
+	if !retried {
158
+		if shouldRetry, reopenErr := f.reopenFDOnError(err); reopenErr != nil {
159
+			return false, reopenErr
160
+		} else if shouldRetry {
161
+			retried = true
162
+			goto retry
163
+		}
164
+	}
165
+
166
+	return false, err
167
+}
168
+
169
+// reopenFDOnError determines whether we should reopen the file handle
170
+// in readwrite mode and try again. This comes from util-linux/sys-utils/flock.c:
171
+//  Since Linux 3.4 (commit 55725513)
172
+//  Probably NFSv4 where flock() is emulated by fcntl().
173
+func (f *Flock) reopenFDOnError(err error) (bool, error) {
174
+	if err != syscall.EIO && err != syscall.EBADF {
175
+		return false, nil
176
+	}
177
+	if st, err := f.fh.Stat(); err == nil {
178
+		// if the file is able to be read and written
179
+		if st.Mode()&0600 == 0600 {
180
+			f.fh.Close()
181
+			f.fh = nil
182
+
183
+			// reopen in read-write mode and set the filehandle
184
+			fh, err := os.OpenFile(f.path, os.O_CREATE|os.O_RDWR, os.FileMode(0600))
185
+			if err != nil {
186
+				return false, err
187
+			}
188
+			f.fh = fh
189
+			return true, nil
190
+		}
191
+	}
192
+
193
+	return false, nil
194
+}
0 195
new file mode 100644
... ...
@@ -0,0 +1,76 @@
0
+// Copyright 2015 Tim Heckman. All rights reserved.
1
+// Use of this source code is governed by the BSD 3-Clause
2
+// license that can be found in the LICENSE file.
3
+
4
+// +build windows
5
+
6
+package flock
7
+
8
+import (
9
+	"syscall"
10
+	"unsafe"
11
+)
12
+
13
+var (
14
+	kernel32, _         = syscall.LoadLibrary("kernel32.dll")
15
+	procLockFileEx, _   = syscall.GetProcAddress(kernel32, "LockFileEx")
16
+	procUnlockFileEx, _ = syscall.GetProcAddress(kernel32, "UnlockFileEx")
17
+)
18
+
19
+const (
20
+	winLockfileFailImmediately = 0x00000001
21
+	winLockfileExclusiveLock   = 0x00000002
22
+	winLockfileSharedLock      = 0x00000000
23
+)
24
+
25
+// Use of 0x00000000 for the shared lock is a guess based on some the MS Windows
26
+// `LockFileEX` docs, which document the `LOCKFILE_EXCLUSIVE_LOCK` flag as:
27
+//
28
+// > The function requests an exclusive lock. Otherwise, it requests a shared
29
+// > lock.
30
+//
31
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx
32
+
33
+func lockFileEx(handle syscall.Handle, flags uint32, reserved uint32, numberOfBytesToLockLow uint32, numberOfBytesToLockHigh uint32, offset *syscall.Overlapped) (bool, syscall.Errno) {
34
+	r1, _, errNo := syscall.Syscall6(
35
+		uintptr(procLockFileEx),
36
+		6,
37
+		uintptr(handle),
38
+		uintptr(flags),
39
+		uintptr(reserved),
40
+		uintptr(numberOfBytesToLockLow),
41
+		uintptr(numberOfBytesToLockHigh),
42
+		uintptr(unsafe.Pointer(offset)))
43
+
44
+	if r1 != 1 {
45
+		if errNo == 0 {
46
+			return false, syscall.EINVAL
47
+		}
48
+
49
+		return false, errNo
50
+	}
51
+
52
+	return true, 0
53
+}
54
+
55
+func unlockFileEx(handle syscall.Handle, reserved uint32, numberOfBytesToLockLow uint32, numberOfBytesToLockHigh uint32, offset *syscall.Overlapped) (bool, syscall.Errno) {
56
+	r1, _, errNo := syscall.Syscall6(
57
+		uintptr(procUnlockFileEx),
58
+		5,
59
+		uintptr(handle),
60
+		uintptr(reserved),
61
+		uintptr(numberOfBytesToLockLow),
62
+		uintptr(numberOfBytesToLockHigh),
63
+		uintptr(unsafe.Pointer(offset)),
64
+		0)
65
+
66
+	if r1 != 1 {
67
+		if errNo == 0 {
68
+			return false, syscall.EINVAL
69
+		}
70
+
71
+		return false, errNo
72
+	}
73
+
74
+	return true, 0
75
+}
0 76
new file mode 100644
... ...
@@ -0,0 +1,140 @@
0
+// Copyright 2015 Tim Heckman. All rights reserved.
1
+// Use of this source code is governed by the BSD 3-Clause
2
+// license that can be found in the LICENSE file.
3
+
4
+package flock
5
+
6
+import (
7
+	"syscall"
8
+)
9
+
10
+// ErrorLockViolation is the error code returned from the Windows syscall when a
11
+// lock would block and you ask to fail immediately.
12
+const ErrorLockViolation syscall.Errno = 0x21 // 33
13
+
14
+// Lock is a blocking call to try and take an exclusive file lock. It will wait
15
+// until it is able to obtain the exclusive file lock. It's recommended that
16
+// TryLock() be used over this function. This function may block the ability to
17
+// query the current Locked() or RLocked() status due to a RW-mutex lock.
18
+//
19
+// If we are already locked, this function short-circuits and returns
20
+// immediately assuming it can take the mutex lock.
21
+func (f *Flock) Lock() error {
22
+	return f.lock(&f.l, winLockfileExclusiveLock)
23
+}
24
+
25
+// RLock is a blocking call to try and take a shared file lock. It will wait
26
+// until it is able to obtain the shared file lock. It's recommended that
27
+// TryRLock() be used over this function. This function may block the ability to
28
+// query the current Locked() or RLocked() status due to a RW-mutex lock.
29
+//
30
+// If we are already locked, this function short-circuits and returns
31
+// immediately assuming it can take the mutex lock.
32
+func (f *Flock) RLock() error {
33
+	return f.lock(&f.r, winLockfileSharedLock)
34
+}
35
+
36
+func (f *Flock) lock(locked *bool, flag uint32) error {
37
+	f.m.Lock()
38
+	defer f.m.Unlock()
39
+
40
+	if *locked {
41
+		return nil
42
+	}
43
+
44
+	if f.fh == nil {
45
+		if err := f.setFh(); err != nil {
46
+			return err
47
+		}
48
+	}
49
+
50
+	if _, errNo := lockFileEx(syscall.Handle(f.fh.Fd()), flag, 0, 1, 0, &syscall.Overlapped{}); errNo > 0 {
51
+		return errNo
52
+	}
53
+
54
+	*locked = true
55
+	return nil
56
+}
57
+
58
+// Unlock is a function to unlock the file. This file takes a RW-mutex lock, so
59
+// while it is running the Locked() and RLocked() functions will be blocked.
60
+//
61
+// This function short-circuits if we are unlocked already. If not, it calls
62
+// UnlockFileEx() on the file and closes the file descriptor. It does not remove
63
+// the file from disk. It's up to your application to do.
64
+func (f *Flock) Unlock() error {
65
+	f.m.Lock()
66
+	defer f.m.Unlock()
67
+
68
+	// if we aren't locked or if the lockfile instance is nil
69
+	// just return a nil error because we are unlocked
70
+	if (!f.l && !f.r) || f.fh == nil {
71
+		return nil
72
+	}
73
+
74
+	// mark the file as unlocked
75
+	if _, errNo := unlockFileEx(syscall.Handle(f.fh.Fd()), 0, 1, 0, &syscall.Overlapped{}); errNo > 0 {
76
+		return errNo
77
+	}
78
+
79
+	f.fh.Close()
80
+
81
+	f.l = false
82
+	f.r = false
83
+	f.fh = nil
84
+
85
+	return nil
86
+}
87
+
88
+// TryLock is the preferred function for taking an exclusive file lock. This
89
+// function does take a RW-mutex lock before it tries to lock the file, so there
90
+// is the possibility that this function may block for a short time if another
91
+// goroutine is trying to take any action.
92
+//
93
+// The actual file lock is non-blocking. If we are unable to get the exclusive
94
+// file lock, the function will return false instead of waiting for the lock. If
95
+// we get the lock, we also set the *Flock instance as being exclusive-locked.
96
+func (f *Flock) TryLock() (bool, error) {
97
+	return f.try(&f.l, winLockfileExclusiveLock)
98
+}
99
+
100
+// TryRLock is the preferred function for taking a shared file lock. This
101
+// function does take a RW-mutex lock before it tries to lock the file, so there
102
+// is the possibility that this function may block for a short time if another
103
+// goroutine is trying to take any action.
104
+//
105
+// The actual file lock is non-blocking. If we are unable to get the shared file
106
+// lock, the function will return false instead of waiting for the lock. If we
107
+// get the lock, we also set the *Flock instance as being shared-locked.
108
+func (f *Flock) TryRLock() (bool, error) {
109
+	return f.try(&f.r, winLockfileSharedLock)
110
+}
111
+
112
+func (f *Flock) try(locked *bool, flag uint32) (bool, error) {
113
+	f.m.Lock()
114
+	defer f.m.Unlock()
115
+
116
+	if *locked {
117
+		return true, nil
118
+	}
119
+
120
+	if f.fh == nil {
121
+		if err := f.setFh(); err != nil {
122
+			return false, err
123
+		}
124
+	}
125
+
126
+	_, errNo := lockFileEx(syscall.Handle(f.fh.Fd()), flag|winLockfileFailImmediately, 0, 1, 0, &syscall.Overlapped{})
127
+
128
+	if errNo > 0 {
129
+		if errNo == ErrorLockViolation || errNo == syscall.ERROR_IO_PENDING {
130
+			return false, nil
131
+		}
132
+
133
+		return false, errNo
134
+	}
135
+
136
+	*locked = true
137
+
138
+	return true, nil
139
+}
... ...
@@ -122,7 +122,7 @@ During development, Dockerfile frontend (dockerfile.v0) is also part of the Buil
122 122
 
123 123
 ```
124 124
 buildctl build --frontend=dockerfile.v0 --local context=. --local dockerfile=.
125
-buildctl build --frontend=dockerfile.v0 --local context=. --local dockerfile=. --frontend-opt target=foo --frontend-opt build-arg:foo=bar
125
+buildctl build --frontend=dockerfile.v0 --local context=. --local dockerfile=. --opt target=foo --opt build-arg:foo=bar
126 126
 ```
127 127
 
128 128
 `--local` exposes local source files from client to the builder. `context` and `dockerfile` are the names Dockerfile frontend looks for build context and Dockerfile location.
... ...
@@ -146,31 +146,31 @@ docker inspect myimage
146 146
 External versions of the Dockerfile frontend are pushed to https://hub.docker.com/r/docker/dockerfile-upstream and https://hub.docker.com/r/docker/dockerfile and can be used with the gateway frontend. The source for the external frontend is currently located in `./frontend/dockerfile/cmd/dockerfile-frontend` but will move out of this repository in the future ([#163](https://github.com/moby/buildkit/issues/163)). For automatic build from master branch of this repository `docker/dockerfile-upsteam:master` or `docker/dockerfile-upstream:master-experimental` image can be used.
147 147
 
148 148
 ```
149
-buildctl build --frontend=gateway.v0 --frontend-opt=source=docker/dockerfile --local context=. --local dockerfile=.
150
-buildctl build --frontend gateway.v0 --frontend-opt=source=docker/dockerfile --frontend-opt=context=git://github.com/moby/moby --frontend-opt build-arg:APT_MIRROR=cdn-fastly.deb.debian.org
149
+buildctl build --frontend gateway.v0 --opt source=docker/dockerfile --local context=. --local dockerfile=.
150
+buildctl build --frontend gateway.v0 --opt source=docker/dockerfile --opt context=git://github.com/moby/moby --opt build-arg:APT_MIRROR=cdn-fastly.deb.debian.org
151 151
 ````
152 152
 
153 153
 ##### Building a Dockerfile with experimental features like `RUN --mount=type=(bind|cache|tmpfs|secret|ssh)`
154 154
 
155 155
 See [`frontend/dockerfile/docs/experimental.md`](frontend/dockerfile/docs/experimental.md).
156 156
 
157
-### Exporters
157
+### Output
158 158
 
159
-By default, the build result and intermediate cache will only remain internally in BuildKit. Exporter needs to be specified to retrieve the result.
159
+By default, the build result and intermediate cache will only remain internally in BuildKit. An output needs to be specified to retrieve the result.
160 160
 
161 161
 ##### Exporting resulting image to containerd
162 162
 
163 163
 The containerd worker needs to be used
164 164
 
165 165
 ```
166
-buildctl build ... --exporter=image --exporter-opt name=docker.io/username/image
166
+buildctl build ... --output type=image,name=docker.io/username/image
167 167
 ctr --namespace=buildkit images ls
168 168
 ```
169 169
 
170 170
 ##### Push resulting image to registry
171 171
 
172 172
 ```
173
-buildctl build ... --exporter=image --exporter-opt name=docker.io/username/image --exporter-opt push=true
173
+buildctl build ... --output type=image,name=docker.io/username/image,push=true
174 174
 ```
175 175
 
176 176
 If credentials are required, `buildctl` will attempt to read Docker configuration file.
... ...
@@ -181,23 +181,52 @@ If credentials are required, `buildctl` will attempt to read Docker configuratio
181 181
 The local client will copy the files directly to the client. This is useful if BuildKit is being used for building something else than container images.
182 182
 
183 183
 ```
184
-buildctl build ... --exporter=local --exporter-opt output=path/to/output-dir
184
+buildctl build ... --output type=local,dest=path/to/output-dir
185 185
 ```
186 186
 
187 187
 ##### Exporting built image to Docker
188 188
 
189 189
 ```
190 190
 # exported tarball is also compatible with OCI spec
191
-buildctl build ... --exporter=docker --exporter-opt name=myimage | docker load
191
+buildctl build ... --output type=docker,name=myimage | docker load
192 192
 ```
193 193
 
194 194
 ##### Exporting [OCI Image Format](https://github.com/opencontainers/image-spec) tarball to client
195 195
 
196 196
 ```
197
-buildctl build ... --exporter=oci --exporter-opt output=path/to/output.tar
198
-buildctl build ... --exporter=oci > output.tar
197
+buildctl build ... --output type=oci,dest=path/to/output.tar
198
+buildctl build ... --output type=oci > output.tar
199 199
 ```
200 200
 
201
+### Exporting/Importing build cache (not image itself)
202
+
203
+#### To/From registry
204
+
205
+```
206
+buildctl build ... --export-cache type=registry,ref=localhost:5000/myrepo:buildcache
207
+buildctl build ... --import-cache type=registry,ref=localhost:5000/myrepo:buildcache
208
+```
209
+
210
+#### To/From local filesystem
211
+
212
+```
213
+buildctl build ... --export-cache type=local,src=path/to/input-dir
214
+buildctl build ... --import-cache type=local,dest=path/to/output-dir
215
+```
216
+
217
+The directory layout conforms to OCI Image Spec v1.0.
218
+
219
+#### `--export-cache` options
220
+* `mode=min` (default): only export layers for the resulting image
221
+* `mode=max`: export all the layers of all intermediate steps
222
+* `ref=docker.io/user/image:tag`: reference for `registry` cache exporter
223
+* `src=path/to/output-dir`: directory for `local` cache exporter
224
+
225
+#### `--import-cache` options
226
+* `ref=docker.io/user/image:tag`: reference for `registry` cache importer
227
+* `dest=path/to/input-dir`: directory for `local` cache importer
228
+* `digest=sha256:deadbeef`: digest of the manifest list to import for `local` cache importer. Defaults to the digest of "latest" tag in `index.json`
229
+
201 230
 ### Other
202 231
 
203 232
 #### View build cache
... ...
@@ -232,6 +261,7 @@ buildctl build --help
232 232
 ```
233 233
 
234 234
 The images can be also built locally using `./hack/dockerfiles/test.Dockerfile` (or `./hack/dockerfiles/test.buildkit.Dockerfile` if you already have BuildKit).
235
+Run `make images` to build the images as `moby/buildkit:local` and `moby/buildkit:local-rootless`.
235 236
 
236 237
 ### Opentracing support
237 238
 
... ...
@@ -1,29 +1,6 @@
1 1
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
2 2
 // source: control.proto
3 3
 
4
-/*
5
-	Package moby_buildkit_v1 is a generated protocol buffer package.
6
-
7
-	It is generated from these files:
8
-		control.proto
9
-
10
-	It has these top-level messages:
11
-		PruneRequest
12
-		DiskUsageRequest
13
-		DiskUsageResponse
14
-		UsageRecord
15
-		SolveRequest
16
-		CacheOptions
17
-		SolveResponse
18
-		StatusRequest
19
-		StatusResponse
20
-		Vertex
21
-		VertexStatus
22
-		VertexLog
23
-		BytesMessage
24
-		ListWorkersRequest
25
-		ListWorkersResponse
26
-*/
27 4
 package moby_buildkit_v1
28 5
 
29 6
 import proto "github.com/gogo/protobuf/proto"
... ...
@@ -31,17 +8,19 @@ import fmt "fmt"
31 31
 import math "math"
32 32
 import _ "github.com/gogo/protobuf/gogoproto"
33 33
 import _ "github.com/golang/protobuf/ptypes/timestamp"
34
+import types "github.com/moby/buildkit/api/types"
34 35
 import pb "github.com/moby/buildkit/solver/pb"
35
-import moby_buildkit_v1_types "github.com/moby/buildkit/api/types"
36 36
 
37 37
 import time "time"
38 38
 import github_com_moby_buildkit_util_entitlements "github.com/moby/buildkit/util/entitlements"
39 39
 import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest"
40 40
 
41
-import context "golang.org/x/net/context"
42
-import grpc "google.golang.org/grpc"
41
+import (
42
+	context "golang.org/x/net/context"
43
+	grpc "google.golang.org/grpc"
44
+)
43 45
 
44
-import types "github.com/gogo/protobuf/types"
46
+import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
45 47
 
46 48
 import io "io"
47 49
 
... ...
@@ -58,16 +37,47 @@ var _ = time.Kitchen
58 58
 const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
59 59
 
60 60
 type PruneRequest struct {
61
-	Filter       []string `protobuf:"bytes,1,rep,name=filter" json:"filter,omitempty"`
62
-	All          bool     `protobuf:"varint,2,opt,name=all,proto3" json:"all,omitempty"`
63
-	KeepDuration int64    `protobuf:"varint,3,opt,name=keepDuration,proto3" json:"keepDuration,omitempty"`
64
-	KeepBytes    int64    `protobuf:"varint,4,opt,name=keepBytes,proto3" json:"keepBytes,omitempty"`
61
+	Filter               []string `protobuf:"bytes,1,rep,name=filter,proto3" json:"filter,omitempty"`
62
+	All                  bool     `protobuf:"varint,2,opt,name=all,proto3" json:"all,omitempty"`
63
+	KeepDuration         int64    `protobuf:"varint,3,opt,name=keepDuration,proto3" json:"keepDuration,omitempty"`
64
+	KeepBytes            int64    `protobuf:"varint,4,opt,name=keepBytes,proto3" json:"keepBytes,omitempty"`
65
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
66
+	XXX_unrecognized     []byte   `json:"-"`
67
+	XXX_sizecache        int32    `json:"-"`
68
+}
69
+
70
+func (m *PruneRequest) Reset()         { *m = PruneRequest{} }
71
+func (m *PruneRequest) String() string { return proto.CompactTextString(m) }
72
+func (*PruneRequest) ProtoMessage()    {}
73
+func (*PruneRequest) Descriptor() ([]byte, []int) {
74
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{0}
75
+}
76
+func (m *PruneRequest) XXX_Unmarshal(b []byte) error {
77
+	return m.Unmarshal(b)
78
+}
79
+func (m *PruneRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
80
+	if deterministic {
81
+		return xxx_messageInfo_PruneRequest.Marshal(b, m, deterministic)
82
+	} else {
83
+		b = b[:cap(b)]
84
+		n, err := m.MarshalTo(b)
85
+		if err != nil {
86
+			return nil, err
87
+		}
88
+		return b[:n], nil
89
+	}
90
+}
91
+func (dst *PruneRequest) XXX_Merge(src proto.Message) {
92
+	xxx_messageInfo_PruneRequest.Merge(dst, src)
93
+}
94
+func (m *PruneRequest) XXX_Size() int {
95
+	return m.Size()
96
+}
97
+func (m *PruneRequest) XXX_DiscardUnknown() {
98
+	xxx_messageInfo_PruneRequest.DiscardUnknown(m)
65 99
 }
66 100
 
67
-func (m *PruneRequest) Reset()                    { *m = PruneRequest{} }
68
-func (m *PruneRequest) String() string            { return proto.CompactTextString(m) }
69
-func (*PruneRequest) ProtoMessage()               {}
70
-func (*PruneRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{0} }
101
+var xxx_messageInfo_PruneRequest proto.InternalMessageInfo
71 102
 
72 103
 func (m *PruneRequest) GetFilter() []string {
73 104
 	if m != nil {
... ...
@@ -98,13 +108,44 @@ func (m *PruneRequest) GetKeepBytes() int64 {
98 98
 }
99 99
 
100 100
 type DiskUsageRequest struct {
101
-	Filter []string `protobuf:"bytes,1,rep,name=filter" json:"filter,omitempty"`
101
+	Filter               []string `protobuf:"bytes,1,rep,name=filter,proto3" json:"filter,omitempty"`
102
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
103
+	XXX_unrecognized     []byte   `json:"-"`
104
+	XXX_sizecache        int32    `json:"-"`
105
+}
106
+
107
+func (m *DiskUsageRequest) Reset()         { *m = DiskUsageRequest{} }
108
+func (m *DiskUsageRequest) String() string { return proto.CompactTextString(m) }
109
+func (*DiskUsageRequest) ProtoMessage()    {}
110
+func (*DiskUsageRequest) Descriptor() ([]byte, []int) {
111
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{1}
112
+}
113
+func (m *DiskUsageRequest) XXX_Unmarshal(b []byte) error {
114
+	return m.Unmarshal(b)
115
+}
116
+func (m *DiskUsageRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
117
+	if deterministic {
118
+		return xxx_messageInfo_DiskUsageRequest.Marshal(b, m, deterministic)
119
+	} else {
120
+		b = b[:cap(b)]
121
+		n, err := m.MarshalTo(b)
122
+		if err != nil {
123
+			return nil, err
124
+		}
125
+		return b[:n], nil
126
+	}
127
+}
128
+func (dst *DiskUsageRequest) XXX_Merge(src proto.Message) {
129
+	xxx_messageInfo_DiskUsageRequest.Merge(dst, src)
130
+}
131
+func (m *DiskUsageRequest) XXX_Size() int {
132
+	return m.Size()
133
+}
134
+func (m *DiskUsageRequest) XXX_DiscardUnknown() {
135
+	xxx_messageInfo_DiskUsageRequest.DiscardUnknown(m)
102 136
 }
103 137
 
104
-func (m *DiskUsageRequest) Reset()                    { *m = DiskUsageRequest{} }
105
-func (m *DiskUsageRequest) String() string            { return proto.CompactTextString(m) }
106
-func (*DiskUsageRequest) ProtoMessage()               {}
107
-func (*DiskUsageRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{1} }
138
+var xxx_messageInfo_DiskUsageRequest proto.InternalMessageInfo
108 139
 
109 140
 func (m *DiskUsageRequest) GetFilter() []string {
110 141
 	if m != nil {
... ...
@@ -114,13 +155,44 @@ func (m *DiskUsageRequest) GetFilter() []string {
114 114
 }
115 115
 
116 116
 type DiskUsageResponse struct {
117
-	Record []*UsageRecord `protobuf:"bytes,1,rep,name=record" json:"record,omitempty"`
117
+	Record               []*UsageRecord `protobuf:"bytes,1,rep,name=record,proto3" json:"record,omitempty"`
118
+	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
119
+	XXX_unrecognized     []byte         `json:"-"`
120
+	XXX_sizecache        int32          `json:"-"`
121
+}
122
+
123
+func (m *DiskUsageResponse) Reset()         { *m = DiskUsageResponse{} }
124
+func (m *DiskUsageResponse) String() string { return proto.CompactTextString(m) }
125
+func (*DiskUsageResponse) ProtoMessage()    {}
126
+func (*DiskUsageResponse) Descriptor() ([]byte, []int) {
127
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{2}
128
+}
129
+func (m *DiskUsageResponse) XXX_Unmarshal(b []byte) error {
130
+	return m.Unmarshal(b)
131
+}
132
+func (m *DiskUsageResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
133
+	if deterministic {
134
+		return xxx_messageInfo_DiskUsageResponse.Marshal(b, m, deterministic)
135
+	} else {
136
+		b = b[:cap(b)]
137
+		n, err := m.MarshalTo(b)
138
+		if err != nil {
139
+			return nil, err
140
+		}
141
+		return b[:n], nil
142
+	}
143
+}
144
+func (dst *DiskUsageResponse) XXX_Merge(src proto.Message) {
145
+	xxx_messageInfo_DiskUsageResponse.Merge(dst, src)
146
+}
147
+func (m *DiskUsageResponse) XXX_Size() int {
148
+	return m.Size()
149
+}
150
+func (m *DiskUsageResponse) XXX_DiscardUnknown() {
151
+	xxx_messageInfo_DiskUsageResponse.DiscardUnknown(m)
118 152
 }
119 153
 
120
-func (m *DiskUsageResponse) Reset()                    { *m = DiskUsageResponse{} }
121
-func (m *DiskUsageResponse) String() string            { return proto.CompactTextString(m) }
122
-func (*DiskUsageResponse) ProtoMessage()               {}
123
-func (*DiskUsageResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{2} }
154
+var xxx_messageInfo_DiskUsageResponse proto.InternalMessageInfo
124 155
 
125 156
 func (m *DiskUsageResponse) GetRecord() []*UsageRecord {
126 157
 	if m != nil {
... ...
@@ -130,23 +202,54 @@ func (m *DiskUsageResponse) GetRecord() []*UsageRecord {
130 130
 }
131 131
 
132 132
 type UsageRecord struct {
133
-	ID          string     `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
134
-	Mutable     bool       `protobuf:"varint,2,opt,name=Mutable,proto3" json:"Mutable,omitempty"`
135
-	InUse       bool       `protobuf:"varint,3,opt,name=InUse,proto3" json:"InUse,omitempty"`
136
-	Size_       int64      `protobuf:"varint,4,opt,name=Size,proto3" json:"Size,omitempty"`
137
-	Parent      string     `protobuf:"bytes,5,opt,name=Parent,proto3" json:"Parent,omitempty"`
138
-	CreatedAt   time.Time  `protobuf:"bytes,6,opt,name=CreatedAt,stdtime" json:"CreatedAt"`
139
-	LastUsedAt  *time.Time `protobuf:"bytes,7,opt,name=LastUsedAt,stdtime" json:"LastUsedAt,omitempty"`
140
-	UsageCount  int64      `protobuf:"varint,8,opt,name=UsageCount,proto3" json:"UsageCount,omitempty"`
141
-	Description string     `protobuf:"bytes,9,opt,name=Description,proto3" json:"Description,omitempty"`
142
-	RecordType  string     `protobuf:"bytes,10,opt,name=RecordType,proto3" json:"RecordType,omitempty"`
143
-	Shared      bool       `protobuf:"varint,11,opt,name=Shared,proto3" json:"Shared,omitempty"`
144
-}
145
-
146
-func (m *UsageRecord) Reset()                    { *m = UsageRecord{} }
147
-func (m *UsageRecord) String() string            { return proto.CompactTextString(m) }
148
-func (*UsageRecord) ProtoMessage()               {}
149
-func (*UsageRecord) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{3} }
133
+	ID                   string     `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
134
+	Mutable              bool       `protobuf:"varint,2,opt,name=Mutable,proto3" json:"Mutable,omitempty"`
135
+	InUse                bool       `protobuf:"varint,3,opt,name=InUse,proto3" json:"InUse,omitempty"`
136
+	Size_                int64      `protobuf:"varint,4,opt,name=Size,proto3" json:"Size,omitempty"`
137
+	Parent               string     `protobuf:"bytes,5,opt,name=Parent,proto3" json:"Parent,omitempty"`
138
+	CreatedAt            time.Time  `protobuf:"bytes,6,opt,name=CreatedAt,proto3,stdtime" json:"CreatedAt"`
139
+	LastUsedAt           *time.Time `protobuf:"bytes,7,opt,name=LastUsedAt,proto3,stdtime" json:"LastUsedAt,omitempty"`
140
+	UsageCount           int64      `protobuf:"varint,8,opt,name=UsageCount,proto3" json:"UsageCount,omitempty"`
141
+	Description          string     `protobuf:"bytes,9,opt,name=Description,proto3" json:"Description,omitempty"`
142
+	RecordType           string     `protobuf:"bytes,10,opt,name=RecordType,proto3" json:"RecordType,omitempty"`
143
+	Shared               bool       `protobuf:"varint,11,opt,name=Shared,proto3" json:"Shared,omitempty"`
144
+	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
145
+	XXX_unrecognized     []byte     `json:"-"`
146
+	XXX_sizecache        int32      `json:"-"`
147
+}
148
+
149
+func (m *UsageRecord) Reset()         { *m = UsageRecord{} }
150
+func (m *UsageRecord) String() string { return proto.CompactTextString(m) }
151
+func (*UsageRecord) ProtoMessage()    {}
152
+func (*UsageRecord) Descriptor() ([]byte, []int) {
153
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{3}
154
+}
155
+func (m *UsageRecord) XXX_Unmarshal(b []byte) error {
156
+	return m.Unmarshal(b)
157
+}
158
+func (m *UsageRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
159
+	if deterministic {
160
+		return xxx_messageInfo_UsageRecord.Marshal(b, m, deterministic)
161
+	} else {
162
+		b = b[:cap(b)]
163
+		n, err := m.MarshalTo(b)
164
+		if err != nil {
165
+			return nil, err
166
+		}
167
+		return b[:n], nil
168
+	}
169
+}
170
+func (dst *UsageRecord) XXX_Merge(src proto.Message) {
171
+	xxx_messageInfo_UsageRecord.Merge(dst, src)
172
+}
173
+func (m *UsageRecord) XXX_Size() int {
174
+	return m.Size()
175
+}
176
+func (m *UsageRecord) XXX_DiscardUnknown() {
177
+	xxx_messageInfo_UsageRecord.DiscardUnknown(m)
178
+}
179
+
180
+var xxx_messageInfo_UsageRecord proto.InternalMessageInfo
150 181
 
151 182
 func (m *UsageRecord) GetID() string {
152 183
 	if m != nil {
... ...
@@ -226,21 +329,52 @@ func (m *UsageRecord) GetShared() bool {
226 226
 }
227 227
 
228 228
 type SolveRequest struct {
229
-	Ref           string                                                   `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
230
-	Definition    *pb.Definition                                           `protobuf:"bytes,2,opt,name=Definition" json:"Definition,omitempty"`
231
-	Exporter      string                                                   `protobuf:"bytes,3,opt,name=Exporter,proto3" json:"Exporter,omitempty"`
232
-	ExporterAttrs map[string]string                                        `protobuf:"bytes,4,rep,name=ExporterAttrs" json:"ExporterAttrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
233
-	Session       string                                                   `protobuf:"bytes,5,opt,name=Session,proto3" json:"Session,omitempty"`
234
-	Frontend      string                                                   `protobuf:"bytes,6,opt,name=Frontend,proto3" json:"Frontend,omitempty"`
235
-	FrontendAttrs map[string]string                                        `protobuf:"bytes,7,rep,name=FrontendAttrs" json:"FrontendAttrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
236
-	Cache         CacheOptions                                             `protobuf:"bytes,8,opt,name=Cache" json:"Cache"`
237
-	Entitlements  []github_com_moby_buildkit_util_entitlements.Entitlement `protobuf:"bytes,9,rep,name=Entitlements,customtype=github.com/moby/buildkit/util/entitlements.Entitlement" json:"Entitlements,omitempty"`
238
-}
239
-
240
-func (m *SolveRequest) Reset()                    { *m = SolveRequest{} }
241
-func (m *SolveRequest) String() string            { return proto.CompactTextString(m) }
242
-func (*SolveRequest) ProtoMessage()               {}
243
-func (*SolveRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{4} }
229
+	Ref                  string                                                   `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
230
+	Definition           *pb.Definition                                           `protobuf:"bytes,2,opt,name=Definition,proto3" json:"Definition,omitempty"`
231
+	Exporter             string                                                   `protobuf:"bytes,3,opt,name=Exporter,proto3" json:"Exporter,omitempty"`
232
+	ExporterAttrs        map[string]string                                        `protobuf:"bytes,4,rep,name=ExporterAttrs,proto3" json:"ExporterAttrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
233
+	Session              string                                                   `protobuf:"bytes,5,opt,name=Session,proto3" json:"Session,omitempty"`
234
+	Frontend             string                                                   `protobuf:"bytes,6,opt,name=Frontend,proto3" json:"Frontend,omitempty"`
235
+	FrontendAttrs        map[string]string                                        `protobuf:"bytes,7,rep,name=FrontendAttrs,proto3" json:"FrontendAttrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
236
+	Cache                CacheOptions                                             `protobuf:"bytes,8,opt,name=Cache,proto3" json:"Cache"`
237
+	Entitlements         []github_com_moby_buildkit_util_entitlements.Entitlement `protobuf:"bytes,9,rep,name=Entitlements,proto3,customtype=github.com/moby/buildkit/util/entitlements.Entitlement" json:"Entitlements,omitempty"`
238
+	XXX_NoUnkeyedLiteral struct{}                                                 `json:"-"`
239
+	XXX_unrecognized     []byte                                                   `json:"-"`
240
+	XXX_sizecache        int32                                                    `json:"-"`
241
+}
242
+
243
+func (m *SolveRequest) Reset()         { *m = SolveRequest{} }
244
+func (m *SolveRequest) String() string { return proto.CompactTextString(m) }
245
+func (*SolveRequest) ProtoMessage()    {}
246
+func (*SolveRequest) Descriptor() ([]byte, []int) {
247
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{4}
248
+}
249
+func (m *SolveRequest) XXX_Unmarshal(b []byte) error {
250
+	return m.Unmarshal(b)
251
+}
252
+func (m *SolveRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
253
+	if deterministic {
254
+		return xxx_messageInfo_SolveRequest.Marshal(b, m, deterministic)
255
+	} else {
256
+		b = b[:cap(b)]
257
+		n, err := m.MarshalTo(b)
258
+		if err != nil {
259
+			return nil, err
260
+		}
261
+		return b[:n], nil
262
+	}
263
+}
264
+func (dst *SolveRequest) XXX_Merge(src proto.Message) {
265
+	xxx_messageInfo_SolveRequest.Merge(dst, src)
266
+}
267
+func (m *SolveRequest) XXX_Size() int {
268
+	return m.Size()
269
+}
270
+func (m *SolveRequest) XXX_DiscardUnknown() {
271
+	xxx_messageInfo_SolveRequest.DiscardUnknown(m)
272
+}
273
+
274
+var xxx_messageInfo_SolveRequest proto.InternalMessageInfo
244 275
 
245 276
 func (m *SolveRequest) GetRef() string {
246 277
 	if m != nil {
... ...
@@ -299,45 +433,193 @@ func (m *SolveRequest) GetCache() CacheOptions {
299 299
 }
300 300
 
301 301
 type CacheOptions struct {
302
-	ExportRef   string            `protobuf:"bytes,1,opt,name=ExportRef,proto3" json:"ExportRef,omitempty"`
303
-	ImportRefs  []string          `protobuf:"bytes,2,rep,name=ImportRefs" json:"ImportRefs,omitempty"`
304
-	ExportAttrs map[string]string `protobuf:"bytes,3,rep,name=ExportAttrs" json:"ExportAttrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
302
+	// ExportRefDeprecated is deprecated in favor or the new Exports since BuildKit v0.4.0.
303
+	// When ExportRefDeprecated is set, the solver appends
304
+	// {.Type = "registry", .Attrs = ExportAttrs.add("ref", ExportRef)}
305
+	// to Exports for compatibility. (planned to be removed)
306
+	ExportRefDeprecated string `protobuf:"bytes,1,opt,name=ExportRefDeprecated,proto3" json:"ExportRefDeprecated,omitempty"`
307
+	// ImportRefsDeprecated is deprecated in favor or the new Imports since BuildKit v0.4.0.
308
+	// When ImportRefsDeprecated is set, the solver appends
309
+	// {.Type = "registry", .Attrs = {"ref": importRef}}
310
+	// for each of the ImportRefs entry to Imports for compatibility. (planned to be removed)
311
+	ImportRefsDeprecated []string `protobuf:"bytes,2,rep,name=ImportRefsDeprecated,proto3" json:"ImportRefsDeprecated,omitempty"`
312
+	// ExportAttrsDeprecated is deprecated since BuildKit v0.4.0.
313
+	// See the description of ExportRefDeprecated.
314
+	ExportAttrsDeprecated map[string]string `protobuf:"bytes,3,rep,name=ExportAttrsDeprecated,proto3" json:"ExportAttrsDeprecated,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
315
+	// Exports was introduced in BuildKit v0.4.0.
316
+	Exports []*CacheOptionsEntry `protobuf:"bytes,4,rep,name=Exports,proto3" json:"Exports,omitempty"`
317
+	// Imports was introduced in BuildKit v0.4.0.
318
+	Imports              []*CacheOptionsEntry `protobuf:"bytes,5,rep,name=Imports,proto3" json:"Imports,omitempty"`
319
+	XXX_NoUnkeyedLiteral struct{}             `json:"-"`
320
+	XXX_unrecognized     []byte               `json:"-"`
321
+	XXX_sizecache        int32                `json:"-"`
322
+}
323
+
324
+func (m *CacheOptions) Reset()         { *m = CacheOptions{} }
325
+func (m *CacheOptions) String() string { return proto.CompactTextString(m) }
326
+func (*CacheOptions) ProtoMessage()    {}
327
+func (*CacheOptions) Descriptor() ([]byte, []int) {
328
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{5}
329
+}
330
+func (m *CacheOptions) XXX_Unmarshal(b []byte) error {
331
+	return m.Unmarshal(b)
332
+}
333
+func (m *CacheOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
334
+	if deterministic {
335
+		return xxx_messageInfo_CacheOptions.Marshal(b, m, deterministic)
336
+	} else {
337
+		b = b[:cap(b)]
338
+		n, err := m.MarshalTo(b)
339
+		if err != nil {
340
+			return nil, err
341
+		}
342
+		return b[:n], nil
343
+	}
344
+}
345
+func (dst *CacheOptions) XXX_Merge(src proto.Message) {
346
+	xxx_messageInfo_CacheOptions.Merge(dst, src)
347
+}
348
+func (m *CacheOptions) XXX_Size() int {
349
+	return m.Size()
350
+}
351
+func (m *CacheOptions) XXX_DiscardUnknown() {
352
+	xxx_messageInfo_CacheOptions.DiscardUnknown(m)
305 353
 }
306 354
 
307
-func (m *CacheOptions) Reset()                    { *m = CacheOptions{} }
308
-func (m *CacheOptions) String() string            { return proto.CompactTextString(m) }
309
-func (*CacheOptions) ProtoMessage()               {}
310
-func (*CacheOptions) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{5} }
355
+var xxx_messageInfo_CacheOptions proto.InternalMessageInfo
311 356
 
312
-func (m *CacheOptions) GetExportRef() string {
357
+func (m *CacheOptions) GetExportRefDeprecated() string {
313 358
 	if m != nil {
314
-		return m.ExportRef
359
+		return m.ExportRefDeprecated
315 360
 	}
316 361
 	return ""
317 362
 }
318 363
 
319
-func (m *CacheOptions) GetImportRefs() []string {
364
+func (m *CacheOptions) GetImportRefsDeprecated() []string {
365
+	if m != nil {
366
+		return m.ImportRefsDeprecated
367
+	}
368
+	return nil
369
+}
370
+
371
+func (m *CacheOptions) GetExportAttrsDeprecated() map[string]string {
320 372
 	if m != nil {
321
-		return m.ImportRefs
373
+		return m.ExportAttrsDeprecated
322 374
 	}
323 375
 	return nil
324 376
 }
325 377
 
326
-func (m *CacheOptions) GetExportAttrs() map[string]string {
378
+func (m *CacheOptions) GetExports() []*CacheOptionsEntry {
327 379
 	if m != nil {
328
-		return m.ExportAttrs
380
+		return m.Exports
381
+	}
382
+	return nil
383
+}
384
+
385
+func (m *CacheOptions) GetImports() []*CacheOptionsEntry {
386
+	if m != nil {
387
+		return m.Imports
388
+	}
389
+	return nil
390
+}
391
+
392
+type CacheOptionsEntry struct {
393
+	// Type is like "registry" or "local"
394
+	Type string `protobuf:"bytes,1,opt,name=Type,proto3" json:"Type,omitempty"`
395
+	// Attrs are like mode=(min,max), ref=example.com:5000/foo/bar .
396
+	// See cache importer/exporter implementations' documentation.
397
+	Attrs                map[string]string `protobuf:"bytes,2,rep,name=Attrs,proto3" json:"Attrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
398
+	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
399
+	XXX_unrecognized     []byte            `json:"-"`
400
+	XXX_sizecache        int32             `json:"-"`
401
+}
402
+
403
+func (m *CacheOptionsEntry) Reset()         { *m = CacheOptionsEntry{} }
404
+func (m *CacheOptionsEntry) String() string { return proto.CompactTextString(m) }
405
+func (*CacheOptionsEntry) ProtoMessage()    {}
406
+func (*CacheOptionsEntry) Descriptor() ([]byte, []int) {
407
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{6}
408
+}
409
+func (m *CacheOptionsEntry) XXX_Unmarshal(b []byte) error {
410
+	return m.Unmarshal(b)
411
+}
412
+func (m *CacheOptionsEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
413
+	if deterministic {
414
+		return xxx_messageInfo_CacheOptionsEntry.Marshal(b, m, deterministic)
415
+	} else {
416
+		b = b[:cap(b)]
417
+		n, err := m.MarshalTo(b)
418
+		if err != nil {
419
+			return nil, err
420
+		}
421
+		return b[:n], nil
422
+	}
423
+}
424
+func (dst *CacheOptionsEntry) XXX_Merge(src proto.Message) {
425
+	xxx_messageInfo_CacheOptionsEntry.Merge(dst, src)
426
+}
427
+func (m *CacheOptionsEntry) XXX_Size() int {
428
+	return m.Size()
429
+}
430
+func (m *CacheOptionsEntry) XXX_DiscardUnknown() {
431
+	xxx_messageInfo_CacheOptionsEntry.DiscardUnknown(m)
432
+}
433
+
434
+var xxx_messageInfo_CacheOptionsEntry proto.InternalMessageInfo
435
+
436
+func (m *CacheOptionsEntry) GetType() string {
437
+	if m != nil {
438
+		return m.Type
439
+	}
440
+	return ""
441
+}
442
+
443
+func (m *CacheOptionsEntry) GetAttrs() map[string]string {
444
+	if m != nil {
445
+		return m.Attrs
329 446
 	}
330 447
 	return nil
331 448
 }
332 449
 
333 450
 type SolveResponse struct {
334
-	ExporterResponse map[string]string `protobuf:"bytes,1,rep,name=ExporterResponse" json:"ExporterResponse,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
451
+	ExporterResponse     map[string]string `protobuf:"bytes,1,rep,name=ExporterResponse,proto3" json:"ExporterResponse,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
452
+	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
453
+	XXX_unrecognized     []byte            `json:"-"`
454
+	XXX_sizecache        int32             `json:"-"`
455
+}
456
+
457
+func (m *SolveResponse) Reset()         { *m = SolveResponse{} }
458
+func (m *SolveResponse) String() string { return proto.CompactTextString(m) }
459
+func (*SolveResponse) ProtoMessage()    {}
460
+func (*SolveResponse) Descriptor() ([]byte, []int) {
461
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{7}
462
+}
463
+func (m *SolveResponse) XXX_Unmarshal(b []byte) error {
464
+	return m.Unmarshal(b)
465
+}
466
+func (m *SolveResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
467
+	if deterministic {
468
+		return xxx_messageInfo_SolveResponse.Marshal(b, m, deterministic)
469
+	} else {
470
+		b = b[:cap(b)]
471
+		n, err := m.MarshalTo(b)
472
+		if err != nil {
473
+			return nil, err
474
+		}
475
+		return b[:n], nil
476
+	}
477
+}
478
+func (dst *SolveResponse) XXX_Merge(src proto.Message) {
479
+	xxx_messageInfo_SolveResponse.Merge(dst, src)
480
+}
481
+func (m *SolveResponse) XXX_Size() int {
482
+	return m.Size()
483
+}
484
+func (m *SolveResponse) XXX_DiscardUnknown() {
485
+	xxx_messageInfo_SolveResponse.DiscardUnknown(m)
335 486
 }
336 487
 
337
-func (m *SolveResponse) Reset()                    { *m = SolveResponse{} }
338
-func (m *SolveResponse) String() string            { return proto.CompactTextString(m) }
339
-func (*SolveResponse) ProtoMessage()               {}
340
-func (*SolveResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{6} }
488
+var xxx_messageInfo_SolveResponse proto.InternalMessageInfo
341 489
 
342 490
 func (m *SolveResponse) GetExporterResponse() map[string]string {
343 491
 	if m != nil {
... ...
@@ -347,13 +629,44 @@ func (m *SolveResponse) GetExporterResponse() map[string]string {
347 347
 }
348 348
 
349 349
 type StatusRequest struct {
350
-	Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
350
+	Ref                  string   `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
351
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
352
+	XXX_unrecognized     []byte   `json:"-"`
353
+	XXX_sizecache        int32    `json:"-"`
354
+}
355
+
356
+func (m *StatusRequest) Reset()         { *m = StatusRequest{} }
357
+func (m *StatusRequest) String() string { return proto.CompactTextString(m) }
358
+func (*StatusRequest) ProtoMessage()    {}
359
+func (*StatusRequest) Descriptor() ([]byte, []int) {
360
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{8}
361
+}
362
+func (m *StatusRequest) XXX_Unmarshal(b []byte) error {
363
+	return m.Unmarshal(b)
364
+}
365
+func (m *StatusRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
366
+	if deterministic {
367
+		return xxx_messageInfo_StatusRequest.Marshal(b, m, deterministic)
368
+	} else {
369
+		b = b[:cap(b)]
370
+		n, err := m.MarshalTo(b)
371
+		if err != nil {
372
+			return nil, err
373
+		}
374
+		return b[:n], nil
375
+	}
376
+}
377
+func (dst *StatusRequest) XXX_Merge(src proto.Message) {
378
+	xxx_messageInfo_StatusRequest.Merge(dst, src)
379
+}
380
+func (m *StatusRequest) XXX_Size() int {
381
+	return m.Size()
382
+}
383
+func (m *StatusRequest) XXX_DiscardUnknown() {
384
+	xxx_messageInfo_StatusRequest.DiscardUnknown(m)
351 385
 }
352 386
 
353
-func (m *StatusRequest) Reset()                    { *m = StatusRequest{} }
354
-func (m *StatusRequest) String() string            { return proto.CompactTextString(m) }
355
-func (*StatusRequest) ProtoMessage()               {}
356
-func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{7} }
387
+var xxx_messageInfo_StatusRequest proto.InternalMessageInfo
357 388
 
358 389
 func (m *StatusRequest) GetRef() string {
359 390
 	if m != nil {
... ...
@@ -363,15 +676,46 @@ func (m *StatusRequest) GetRef() string {
363 363
 }
364 364
 
365 365
 type StatusResponse struct {
366
-	Vertexes []*Vertex       `protobuf:"bytes,1,rep,name=vertexes" json:"vertexes,omitempty"`
367
-	Statuses []*VertexStatus `protobuf:"bytes,2,rep,name=statuses" json:"statuses,omitempty"`
368
-	Logs     []*VertexLog    `protobuf:"bytes,3,rep,name=logs" json:"logs,omitempty"`
366
+	Vertexes             []*Vertex       `protobuf:"bytes,1,rep,name=vertexes,proto3" json:"vertexes,omitempty"`
367
+	Statuses             []*VertexStatus `protobuf:"bytes,2,rep,name=statuses,proto3" json:"statuses,omitempty"`
368
+	Logs                 []*VertexLog    `protobuf:"bytes,3,rep,name=logs,proto3" json:"logs,omitempty"`
369
+	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
370
+	XXX_unrecognized     []byte          `json:"-"`
371
+	XXX_sizecache        int32           `json:"-"`
372
+}
373
+
374
+func (m *StatusResponse) Reset()         { *m = StatusResponse{} }
375
+func (m *StatusResponse) String() string { return proto.CompactTextString(m) }
376
+func (*StatusResponse) ProtoMessage()    {}
377
+func (*StatusResponse) Descriptor() ([]byte, []int) {
378
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{9}
379
+}
380
+func (m *StatusResponse) XXX_Unmarshal(b []byte) error {
381
+	return m.Unmarshal(b)
382
+}
383
+func (m *StatusResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
384
+	if deterministic {
385
+		return xxx_messageInfo_StatusResponse.Marshal(b, m, deterministic)
386
+	} else {
387
+		b = b[:cap(b)]
388
+		n, err := m.MarshalTo(b)
389
+		if err != nil {
390
+			return nil, err
391
+		}
392
+		return b[:n], nil
393
+	}
394
+}
395
+func (dst *StatusResponse) XXX_Merge(src proto.Message) {
396
+	xxx_messageInfo_StatusResponse.Merge(dst, src)
397
+}
398
+func (m *StatusResponse) XXX_Size() int {
399
+	return m.Size()
400
+}
401
+func (m *StatusResponse) XXX_DiscardUnknown() {
402
+	xxx_messageInfo_StatusResponse.DiscardUnknown(m)
369 403
 }
370 404
 
371
-func (m *StatusResponse) Reset()                    { *m = StatusResponse{} }
372
-func (m *StatusResponse) String() string            { return proto.CompactTextString(m) }
373
-func (*StatusResponse) ProtoMessage()               {}
374
-func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{8} }
405
+var xxx_messageInfo_StatusResponse proto.InternalMessageInfo
375 406
 
376 407
 func (m *StatusResponse) GetVertexes() []*Vertex {
377 408
 	if m != nil {
... ...
@@ -395,19 +739,50 @@ func (m *StatusResponse) GetLogs() []*VertexLog {
395 395
 }
396 396
 
397 397
 type Vertex struct {
398
-	Digest    github_com_opencontainers_go_digest.Digest   `protobuf:"bytes,1,opt,name=digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"digest"`
399
-	Inputs    []github_com_opencontainers_go_digest.Digest `protobuf:"bytes,2,rep,name=inputs,customtype=github.com/opencontainers/go-digest.Digest" json:"inputs"`
400
-	Name      string                                       `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
401
-	Cached    bool                                         `protobuf:"varint,4,opt,name=cached,proto3" json:"cached,omitempty"`
402
-	Started   *time.Time                                   `protobuf:"bytes,5,opt,name=started,stdtime" json:"started,omitempty"`
403
-	Completed *time.Time                                   `protobuf:"bytes,6,opt,name=completed,stdtime" json:"completed,omitempty"`
404
-	Error     string                                       `protobuf:"bytes,7,opt,name=error,proto3" json:"error,omitempty"`
398
+	Digest               github_com_opencontainers_go_digest.Digest   `protobuf:"bytes,1,opt,name=digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"digest"`
399
+	Inputs               []github_com_opencontainers_go_digest.Digest `protobuf:"bytes,2,rep,name=inputs,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"inputs"`
400
+	Name                 string                                       `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
401
+	Cached               bool                                         `protobuf:"varint,4,opt,name=cached,proto3" json:"cached,omitempty"`
402
+	Started              *time.Time                                   `protobuf:"bytes,5,opt,name=started,proto3,stdtime" json:"started,omitempty"`
403
+	Completed            *time.Time                                   `protobuf:"bytes,6,opt,name=completed,proto3,stdtime" json:"completed,omitempty"`
404
+	Error                string                                       `protobuf:"bytes,7,opt,name=error,proto3" json:"error,omitempty"`
405
+	XXX_NoUnkeyedLiteral struct{}                                     `json:"-"`
406
+	XXX_unrecognized     []byte                                       `json:"-"`
407
+	XXX_sizecache        int32                                        `json:"-"`
408
+}
409
+
410
+func (m *Vertex) Reset()         { *m = Vertex{} }
411
+func (m *Vertex) String() string { return proto.CompactTextString(m) }
412
+func (*Vertex) ProtoMessage()    {}
413
+func (*Vertex) Descriptor() ([]byte, []int) {
414
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{10}
415
+}
416
+func (m *Vertex) XXX_Unmarshal(b []byte) error {
417
+	return m.Unmarshal(b)
418
+}
419
+func (m *Vertex) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
420
+	if deterministic {
421
+		return xxx_messageInfo_Vertex.Marshal(b, m, deterministic)
422
+	} else {
423
+		b = b[:cap(b)]
424
+		n, err := m.MarshalTo(b)
425
+		if err != nil {
426
+			return nil, err
427
+		}
428
+		return b[:n], nil
429
+	}
430
+}
431
+func (dst *Vertex) XXX_Merge(src proto.Message) {
432
+	xxx_messageInfo_Vertex.Merge(dst, src)
433
+}
434
+func (m *Vertex) XXX_Size() int {
435
+	return m.Size()
436
+}
437
+func (m *Vertex) XXX_DiscardUnknown() {
438
+	xxx_messageInfo_Vertex.DiscardUnknown(m)
405 439
 }
406 440
 
407
-func (m *Vertex) Reset()                    { *m = Vertex{} }
408
-func (m *Vertex) String() string            { return proto.CompactTextString(m) }
409
-func (*Vertex) ProtoMessage()               {}
410
-func (*Vertex) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{9} }
441
+var xxx_messageInfo_Vertex proto.InternalMessageInfo
411 442
 
412 443
 func (m *Vertex) GetName() string {
413 444
 	if m != nil {
... ...
@@ -451,15 +826,46 @@ type VertexStatus struct {
451 451
 	Current int64                                      `protobuf:"varint,4,opt,name=current,proto3" json:"current,omitempty"`
452 452
 	Total   int64                                      `protobuf:"varint,5,opt,name=total,proto3" json:"total,omitempty"`
453 453
 	// TODO: add started, completed
454
-	Timestamp time.Time  `protobuf:"bytes,6,opt,name=timestamp,stdtime" json:"timestamp"`
455
-	Started   *time.Time `protobuf:"bytes,7,opt,name=started,stdtime" json:"started,omitempty"`
456
-	Completed *time.Time `protobuf:"bytes,8,opt,name=completed,stdtime" json:"completed,omitempty"`
454
+	Timestamp            time.Time  `protobuf:"bytes,6,opt,name=timestamp,proto3,stdtime" json:"timestamp"`
455
+	Started              *time.Time `protobuf:"bytes,7,opt,name=started,proto3,stdtime" json:"started,omitempty"`
456
+	Completed            *time.Time `protobuf:"bytes,8,opt,name=completed,proto3,stdtime" json:"completed,omitempty"`
457
+	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
458
+	XXX_unrecognized     []byte     `json:"-"`
459
+	XXX_sizecache        int32      `json:"-"`
460
+}
461
+
462
+func (m *VertexStatus) Reset()         { *m = VertexStatus{} }
463
+func (m *VertexStatus) String() string { return proto.CompactTextString(m) }
464
+func (*VertexStatus) ProtoMessage()    {}
465
+func (*VertexStatus) Descriptor() ([]byte, []int) {
466
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{11}
467
+}
468
+func (m *VertexStatus) XXX_Unmarshal(b []byte) error {
469
+	return m.Unmarshal(b)
470
+}
471
+func (m *VertexStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
472
+	if deterministic {
473
+		return xxx_messageInfo_VertexStatus.Marshal(b, m, deterministic)
474
+	} else {
475
+		b = b[:cap(b)]
476
+		n, err := m.MarshalTo(b)
477
+		if err != nil {
478
+			return nil, err
479
+		}
480
+		return b[:n], nil
481
+	}
482
+}
483
+func (dst *VertexStatus) XXX_Merge(src proto.Message) {
484
+	xxx_messageInfo_VertexStatus.Merge(dst, src)
485
+}
486
+func (m *VertexStatus) XXX_Size() int {
487
+	return m.Size()
488
+}
489
+func (m *VertexStatus) XXX_DiscardUnknown() {
490
+	xxx_messageInfo_VertexStatus.DiscardUnknown(m)
457 491
 }
458 492
 
459
-func (m *VertexStatus) Reset()                    { *m = VertexStatus{} }
460
-func (m *VertexStatus) String() string            { return proto.CompactTextString(m) }
461
-func (*VertexStatus) ProtoMessage()               {}
462
-func (*VertexStatus) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{10} }
493
+var xxx_messageInfo_VertexStatus proto.InternalMessageInfo
463 494
 
464 495
 func (m *VertexStatus) GetID() string {
465 496
 	if m != nil {
... ...
@@ -511,16 +917,47 @@ func (m *VertexStatus) GetCompleted() *time.Time {
511 511
 }
512 512
 
513 513
 type VertexLog struct {
514
-	Vertex    github_com_opencontainers_go_digest.Digest `protobuf:"bytes,1,opt,name=vertex,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"vertex"`
515
-	Timestamp time.Time                                  `protobuf:"bytes,2,opt,name=timestamp,stdtime" json:"timestamp"`
516
-	Stream    int64                                      `protobuf:"varint,3,opt,name=stream,proto3" json:"stream,omitempty"`
517
-	Msg       []byte                                     `protobuf:"bytes,4,opt,name=msg,proto3" json:"msg,omitempty"`
514
+	Vertex               github_com_opencontainers_go_digest.Digest `protobuf:"bytes,1,opt,name=vertex,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"vertex"`
515
+	Timestamp            time.Time                                  `protobuf:"bytes,2,opt,name=timestamp,proto3,stdtime" json:"timestamp"`
516
+	Stream               int64                                      `protobuf:"varint,3,opt,name=stream,proto3" json:"stream,omitempty"`
517
+	Msg                  []byte                                     `protobuf:"bytes,4,opt,name=msg,proto3" json:"msg,omitempty"`
518
+	XXX_NoUnkeyedLiteral struct{}                                   `json:"-"`
519
+	XXX_unrecognized     []byte                                     `json:"-"`
520
+	XXX_sizecache        int32                                      `json:"-"`
521
+}
522
+
523
+func (m *VertexLog) Reset()         { *m = VertexLog{} }
524
+func (m *VertexLog) String() string { return proto.CompactTextString(m) }
525
+func (*VertexLog) ProtoMessage()    {}
526
+func (*VertexLog) Descriptor() ([]byte, []int) {
527
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{12}
528
+}
529
+func (m *VertexLog) XXX_Unmarshal(b []byte) error {
530
+	return m.Unmarshal(b)
531
+}
532
+func (m *VertexLog) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
533
+	if deterministic {
534
+		return xxx_messageInfo_VertexLog.Marshal(b, m, deterministic)
535
+	} else {
536
+		b = b[:cap(b)]
537
+		n, err := m.MarshalTo(b)
538
+		if err != nil {
539
+			return nil, err
540
+		}
541
+		return b[:n], nil
542
+	}
543
+}
544
+func (dst *VertexLog) XXX_Merge(src proto.Message) {
545
+	xxx_messageInfo_VertexLog.Merge(dst, src)
546
+}
547
+func (m *VertexLog) XXX_Size() int {
548
+	return m.Size()
549
+}
550
+func (m *VertexLog) XXX_DiscardUnknown() {
551
+	xxx_messageInfo_VertexLog.DiscardUnknown(m)
518 552
 }
519 553
 
520
-func (m *VertexLog) Reset()                    { *m = VertexLog{} }
521
-func (m *VertexLog) String() string            { return proto.CompactTextString(m) }
522
-func (*VertexLog) ProtoMessage()               {}
523
-func (*VertexLog) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{11} }
554
+var xxx_messageInfo_VertexLog proto.InternalMessageInfo
524 555
 
525 556
 func (m *VertexLog) GetTimestamp() time.Time {
526 557
 	if m != nil {
... ...
@@ -544,13 +981,44 @@ func (m *VertexLog) GetMsg() []byte {
544 544
 }
545 545
 
546 546
 type BytesMessage struct {
547
-	Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
547
+	Data                 []byte   `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
548
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
549
+	XXX_unrecognized     []byte   `json:"-"`
550
+	XXX_sizecache        int32    `json:"-"`
551
+}
552
+
553
+func (m *BytesMessage) Reset()         { *m = BytesMessage{} }
554
+func (m *BytesMessage) String() string { return proto.CompactTextString(m) }
555
+func (*BytesMessage) ProtoMessage()    {}
556
+func (*BytesMessage) Descriptor() ([]byte, []int) {
557
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{13}
558
+}
559
+func (m *BytesMessage) XXX_Unmarshal(b []byte) error {
560
+	return m.Unmarshal(b)
561
+}
562
+func (m *BytesMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
563
+	if deterministic {
564
+		return xxx_messageInfo_BytesMessage.Marshal(b, m, deterministic)
565
+	} else {
566
+		b = b[:cap(b)]
567
+		n, err := m.MarshalTo(b)
568
+		if err != nil {
569
+			return nil, err
570
+		}
571
+		return b[:n], nil
572
+	}
573
+}
574
+func (dst *BytesMessage) XXX_Merge(src proto.Message) {
575
+	xxx_messageInfo_BytesMessage.Merge(dst, src)
576
+}
577
+func (m *BytesMessage) XXX_Size() int {
578
+	return m.Size()
579
+}
580
+func (m *BytesMessage) XXX_DiscardUnknown() {
581
+	xxx_messageInfo_BytesMessage.DiscardUnknown(m)
548 582
 }
549 583
 
550
-func (m *BytesMessage) Reset()                    { *m = BytesMessage{} }
551
-func (m *BytesMessage) String() string            { return proto.CompactTextString(m) }
552
-func (*BytesMessage) ProtoMessage()               {}
553
-func (*BytesMessage) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{12} }
584
+var xxx_messageInfo_BytesMessage proto.InternalMessageInfo
554 585
 
555 586
 func (m *BytesMessage) GetData() []byte {
556 587
 	if m != nil {
... ...
@@ -560,13 +1028,44 @@ func (m *BytesMessage) GetData() []byte {
560 560
 }
561 561
 
562 562
 type ListWorkersRequest struct {
563
-	Filter []string `protobuf:"bytes,1,rep,name=filter" json:"filter,omitempty"`
563
+	Filter               []string `protobuf:"bytes,1,rep,name=filter,proto3" json:"filter,omitempty"`
564
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
565
+	XXX_unrecognized     []byte   `json:"-"`
566
+	XXX_sizecache        int32    `json:"-"`
567
+}
568
+
569
+func (m *ListWorkersRequest) Reset()         { *m = ListWorkersRequest{} }
570
+func (m *ListWorkersRequest) String() string { return proto.CompactTextString(m) }
571
+func (*ListWorkersRequest) ProtoMessage()    {}
572
+func (*ListWorkersRequest) Descriptor() ([]byte, []int) {
573
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{14}
574
+}
575
+func (m *ListWorkersRequest) XXX_Unmarshal(b []byte) error {
576
+	return m.Unmarshal(b)
577
+}
578
+func (m *ListWorkersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
579
+	if deterministic {
580
+		return xxx_messageInfo_ListWorkersRequest.Marshal(b, m, deterministic)
581
+	} else {
582
+		b = b[:cap(b)]
583
+		n, err := m.MarshalTo(b)
584
+		if err != nil {
585
+			return nil, err
586
+		}
587
+		return b[:n], nil
588
+	}
589
+}
590
+func (dst *ListWorkersRequest) XXX_Merge(src proto.Message) {
591
+	xxx_messageInfo_ListWorkersRequest.Merge(dst, src)
592
+}
593
+func (m *ListWorkersRequest) XXX_Size() int {
594
+	return m.Size()
595
+}
596
+func (m *ListWorkersRequest) XXX_DiscardUnknown() {
597
+	xxx_messageInfo_ListWorkersRequest.DiscardUnknown(m)
564 598
 }
565 599
 
566
-func (m *ListWorkersRequest) Reset()                    { *m = ListWorkersRequest{} }
567
-func (m *ListWorkersRequest) String() string            { return proto.CompactTextString(m) }
568
-func (*ListWorkersRequest) ProtoMessage()               {}
569
-func (*ListWorkersRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{13} }
600
+var xxx_messageInfo_ListWorkersRequest proto.InternalMessageInfo
570 601
 
571 602
 func (m *ListWorkersRequest) GetFilter() []string {
572 603
 	if m != nil {
... ...
@@ -576,15 +1075,46 @@ func (m *ListWorkersRequest) GetFilter() []string {
576 576
 }
577 577
 
578 578
 type ListWorkersResponse struct {
579
-	Record []*moby_buildkit_v1_types.WorkerRecord `protobuf:"bytes,1,rep,name=record" json:"record,omitempty"`
579
+	Record               []*types.WorkerRecord `protobuf:"bytes,1,rep,name=record,proto3" json:"record,omitempty"`
580
+	XXX_NoUnkeyedLiteral struct{}              `json:"-"`
581
+	XXX_unrecognized     []byte                `json:"-"`
582
+	XXX_sizecache        int32                 `json:"-"`
583
+}
584
+
585
+func (m *ListWorkersResponse) Reset()         { *m = ListWorkersResponse{} }
586
+func (m *ListWorkersResponse) String() string { return proto.CompactTextString(m) }
587
+func (*ListWorkersResponse) ProtoMessage()    {}
588
+func (*ListWorkersResponse) Descriptor() ([]byte, []int) {
589
+	return fileDescriptor_control_86d7f5d7b8f10de2, []int{15}
590
+}
591
+func (m *ListWorkersResponse) XXX_Unmarshal(b []byte) error {
592
+	return m.Unmarshal(b)
593
+}
594
+func (m *ListWorkersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
595
+	if deterministic {
596
+		return xxx_messageInfo_ListWorkersResponse.Marshal(b, m, deterministic)
597
+	} else {
598
+		b = b[:cap(b)]
599
+		n, err := m.MarshalTo(b)
600
+		if err != nil {
601
+			return nil, err
602
+		}
603
+		return b[:n], nil
604
+	}
605
+}
606
+func (dst *ListWorkersResponse) XXX_Merge(src proto.Message) {
607
+	xxx_messageInfo_ListWorkersResponse.Merge(dst, src)
608
+}
609
+func (m *ListWorkersResponse) XXX_Size() int {
610
+	return m.Size()
611
+}
612
+func (m *ListWorkersResponse) XXX_DiscardUnknown() {
613
+	xxx_messageInfo_ListWorkersResponse.DiscardUnknown(m)
580 614
 }
581 615
 
582
-func (m *ListWorkersResponse) Reset()                    { *m = ListWorkersResponse{} }
583
-func (m *ListWorkersResponse) String() string            { return proto.CompactTextString(m) }
584
-func (*ListWorkersResponse) ProtoMessage()               {}
585
-func (*ListWorkersResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{14} }
616
+var xxx_messageInfo_ListWorkersResponse proto.InternalMessageInfo
586 617
 
587
-func (m *ListWorkersResponse) GetRecord() []*moby_buildkit_v1_types.WorkerRecord {
618
+func (m *ListWorkersResponse) GetRecord() []*types.WorkerRecord {
588 619
 	if m != nil {
589 620
 		return m.Record
590 621
 	}
... ...
@@ -597,8 +1127,14 @@ func init() {
597 597
 	proto.RegisterType((*DiskUsageResponse)(nil), "moby.buildkit.v1.DiskUsageResponse")
598 598
 	proto.RegisterType((*UsageRecord)(nil), "moby.buildkit.v1.UsageRecord")
599 599
 	proto.RegisterType((*SolveRequest)(nil), "moby.buildkit.v1.SolveRequest")
600
+	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.SolveRequest.ExporterAttrsEntry")
601
+	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.SolveRequest.FrontendAttrsEntry")
600 602
 	proto.RegisterType((*CacheOptions)(nil), "moby.buildkit.v1.CacheOptions")
603
+	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.CacheOptions.ExportAttrsDeprecatedEntry")
604
+	proto.RegisterType((*CacheOptionsEntry)(nil), "moby.buildkit.v1.CacheOptionsEntry")
605
+	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.CacheOptionsEntry.AttrsEntry")
601 606
 	proto.RegisterType((*SolveResponse)(nil), "moby.buildkit.v1.SolveResponse")
607
+	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.SolveResponse.ExporterResponseEntry")
602 608
 	proto.RegisterType((*StatusRequest)(nil), "moby.buildkit.v1.StatusRequest")
603 609
 	proto.RegisterType((*StatusResponse)(nil), "moby.buildkit.v1.StatusResponse")
604 610
 	proto.RegisterType((*Vertex)(nil), "moby.buildkit.v1.Vertex")
... ...
@@ -617,8 +1153,9 @@ var _ grpc.ClientConn
617 617
 // is compatible with the grpc package it is being compiled against.
618 618
 const _ = grpc.SupportPackageIsVersion4
619 619
 
620
-// Client API for Control service
621
-
620
+// ControlClient is the client API for Control service.
621
+//
622
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
622 623
 type ControlClient interface {
623 624
 	DiskUsage(ctx context.Context, in *DiskUsageRequest, opts ...grpc.CallOption) (*DiskUsageResponse, error)
624 625
 	Prune(ctx context.Context, in *PruneRequest, opts ...grpc.CallOption) (Control_PruneClient, error)
... ...
@@ -638,7 +1175,7 @@ func NewControlClient(cc *grpc.ClientConn) ControlClient {
638 638
 
639 639
 func (c *controlClient) DiskUsage(ctx context.Context, in *DiskUsageRequest, opts ...grpc.CallOption) (*DiskUsageResponse, error) {
640 640
 	out := new(DiskUsageResponse)
641
-	err := grpc.Invoke(ctx, "/moby.buildkit.v1.Control/DiskUsage", in, out, c.cc, opts...)
641
+	err := c.cc.Invoke(ctx, "/moby.buildkit.v1.Control/DiskUsage", in, out, opts...)
642 642
 	if err != nil {
643 643
 		return nil, err
644 644
 	}
... ...
@@ -646,7 +1183,7 @@ func (c *controlClient) DiskUsage(ctx context.Context, in *DiskUsageRequest, opt
646 646
 }
647 647
 
648 648
 func (c *controlClient) Prune(ctx context.Context, in *PruneRequest, opts ...grpc.CallOption) (Control_PruneClient, error) {
649
-	stream, err := grpc.NewClientStream(ctx, &_Control_serviceDesc.Streams[0], c.cc, "/moby.buildkit.v1.Control/Prune", opts...)
649
+	stream, err := c.cc.NewStream(ctx, &_Control_serviceDesc.Streams[0], "/moby.buildkit.v1.Control/Prune", opts...)
650 650
 	if err != nil {
651 651
 		return nil, err
652 652
 	}
... ...
@@ -679,7 +1216,7 @@ func (x *controlPruneClient) Recv() (*UsageRecord, error) {
679 679
 
680 680
 func (c *controlClient) Solve(ctx context.Context, in *SolveRequest, opts ...grpc.CallOption) (*SolveResponse, error) {
681 681
 	out := new(SolveResponse)
682
-	err := grpc.Invoke(ctx, "/moby.buildkit.v1.Control/Solve", in, out, c.cc, opts...)
682
+	err := c.cc.Invoke(ctx, "/moby.buildkit.v1.Control/Solve", in, out, opts...)
683 683
 	if err != nil {
684 684
 		return nil, err
685 685
 	}
... ...
@@ -687,7 +1224,7 @@ func (c *controlClient) Solve(ctx context.Context, in *SolveRequest, opts ...grp
687 687
 }
688 688
 
689 689
 func (c *controlClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (Control_StatusClient, error) {
690
-	stream, err := grpc.NewClientStream(ctx, &_Control_serviceDesc.Streams[1], c.cc, "/moby.buildkit.v1.Control/Status", opts...)
690
+	stream, err := c.cc.NewStream(ctx, &_Control_serviceDesc.Streams[1], "/moby.buildkit.v1.Control/Status", opts...)
691 691
 	if err != nil {
692 692
 		return nil, err
693 693
 	}
... ...
@@ -719,7 +1256,7 @@ func (x *controlStatusClient) Recv() (*StatusResponse, error) {
719 719
 }
720 720
 
721 721
 func (c *controlClient) Session(ctx context.Context, opts ...grpc.CallOption) (Control_SessionClient, error) {
722
-	stream, err := grpc.NewClientStream(ctx, &_Control_serviceDesc.Streams[2], c.cc, "/moby.buildkit.v1.Control/Session", opts...)
722
+	stream, err := c.cc.NewStream(ctx, &_Control_serviceDesc.Streams[2], "/moby.buildkit.v1.Control/Session", opts...)
723 723
 	if err != nil {
724 724
 		return nil, err
725 725
 	}
... ...
@@ -751,15 +1288,14 @@ func (x *controlSessionClient) Recv() (*BytesMessage, error) {
751 751
 
752 752
 func (c *controlClient) ListWorkers(ctx context.Context, in *ListWorkersRequest, opts ...grpc.CallOption) (*ListWorkersResponse, error) {
753 753
 	out := new(ListWorkersResponse)
754
-	err := grpc.Invoke(ctx, "/moby.buildkit.v1.Control/ListWorkers", in, out, c.cc, opts...)
754
+	err := c.cc.Invoke(ctx, "/moby.buildkit.v1.Control/ListWorkers", in, out, opts...)
755 755
 	if err != nil {
756 756
 		return nil, err
757 757
 	}
758 758
 	return out, nil
759 759
 }
760 760
 
761
-// Server API for Control service
762
-
761
+// ControlServer is the server API for Control service.
763 762
 type ControlServer interface {
764 763
 	DiskUsage(context.Context, *DiskUsageRequest) (*DiskUsageResponse, error)
765 764
 	Prune(*PruneRequest, Control_PruneServer) error
... ...
@@ -983,6 +1519,9 @@ func (m *PruneRequest) MarshalTo(dAtA []byte) (int, error) {
983 983
 		i++
984 984
 		i = encodeVarintControl(dAtA, i, uint64(m.KeepBytes))
985 985
 	}
986
+	if m.XXX_unrecognized != nil {
987
+		i += copy(dAtA[i:], m.XXX_unrecognized)
988
+	}
986 989
 	return i, nil
987 990
 }
988 991
 
... ...
@@ -1016,6 +1555,9 @@ func (m *DiskUsageRequest) MarshalTo(dAtA []byte) (int, error) {
1016 1016
 			i += copy(dAtA[i:], s)
1017 1017
 		}
1018 1018
 	}
1019
+	if m.XXX_unrecognized != nil {
1020
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1021
+	}
1019 1022
 	return i, nil
1020 1023
 }
1021 1024
 
... ...
@@ -1046,6 +1588,9 @@ func (m *DiskUsageResponse) MarshalTo(dAtA []byte) (int, error) {
1046 1046
 			i += n
1047 1047
 		}
1048 1048
 	}
1049
+	if m.XXX_unrecognized != nil {
1050
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1051
+	}
1049 1052
 	return i, nil
1050 1053
 }
1051 1054
 
... ...
@@ -1103,8 +1648,8 @@ func (m *UsageRecord) MarshalTo(dAtA []byte) (int, error) {
1103 1103
 	}
1104 1104
 	dAtA[i] = 0x32
1105 1105
 	i++
1106
-	i = encodeVarintControl(dAtA, i, uint64(types.SizeOfStdTime(m.CreatedAt)))
1107
-	n1, err := types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
1106
+	i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt)))
1107
+	n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
1108 1108
 	if err != nil {
1109 1109
 		return 0, err
1110 1110
 	}
... ...
@@ -1112,8 +1657,8 @@ func (m *UsageRecord) MarshalTo(dAtA []byte) (int, error) {
1112 1112
 	if m.LastUsedAt != nil {
1113 1113
 		dAtA[i] = 0x3a
1114 1114
 		i++
1115
-		i = encodeVarintControl(dAtA, i, uint64(types.SizeOfStdTime(*m.LastUsedAt)))
1116
-		n2, err := types.StdTimeMarshalTo(*m.LastUsedAt, dAtA[i:])
1115
+		i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.LastUsedAt)))
1116
+		n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.LastUsedAt, dAtA[i:])
1117 1117
 		if err != nil {
1118 1118
 			return 0, err
1119 1119
 		}
... ...
@@ -1146,6 +1691,9 @@ func (m *UsageRecord) MarshalTo(dAtA []byte) (int, error) {
1146 1146
 		}
1147 1147
 		i++
1148 1148
 	}
1149
+	if m.XXX_unrecognized != nil {
1150
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1151
+	}
1149 1152
 	return i, nil
1150 1153
 }
1151 1154
 
... ...
@@ -1255,6 +1803,9 @@ func (m *SolveRequest) MarshalTo(dAtA []byte) (int, error) {
1255 1255
 			i += copy(dAtA[i:], s)
1256 1256
 		}
1257 1257
 	}
1258
+	if m.XXX_unrecognized != nil {
1259
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1260
+	}
1258 1261
 	return i, nil
1259 1262
 }
1260 1263
 
... ...
@@ -1273,14 +1824,14 @@ func (m *CacheOptions) MarshalTo(dAtA []byte) (int, error) {
1273 1273
 	_ = i
1274 1274
 	var l int
1275 1275
 	_ = l
1276
-	if len(m.ExportRef) > 0 {
1276
+	if len(m.ExportRefDeprecated) > 0 {
1277 1277
 		dAtA[i] = 0xa
1278 1278
 		i++
1279
-		i = encodeVarintControl(dAtA, i, uint64(len(m.ExportRef)))
1280
-		i += copy(dAtA[i:], m.ExportRef)
1279
+		i = encodeVarintControl(dAtA, i, uint64(len(m.ExportRefDeprecated)))
1280
+		i += copy(dAtA[i:], m.ExportRefDeprecated)
1281 1281
 	}
1282
-	if len(m.ImportRefs) > 0 {
1283
-		for _, s := range m.ImportRefs {
1282
+	if len(m.ImportRefsDeprecated) > 0 {
1283
+		for _, s := range m.ImportRefsDeprecated {
1284 1284
 			dAtA[i] = 0x12
1285 1285
 			i++
1286 1286
 			l = len(s)
... ...
@@ -1294,11 +1845,79 @@ func (m *CacheOptions) MarshalTo(dAtA []byte) (int, error) {
1294 1294
 			i += copy(dAtA[i:], s)
1295 1295
 		}
1296 1296
 	}
1297
-	if len(m.ExportAttrs) > 0 {
1298
-		for k, _ := range m.ExportAttrs {
1297
+	if len(m.ExportAttrsDeprecated) > 0 {
1298
+		for k, _ := range m.ExportAttrsDeprecated {
1299 1299
 			dAtA[i] = 0x1a
1300 1300
 			i++
1301
-			v := m.ExportAttrs[k]
1301
+			v := m.ExportAttrsDeprecated[k]
1302
+			mapSize := 1 + len(k) + sovControl(uint64(len(k))) + 1 + len(v) + sovControl(uint64(len(v)))
1303
+			i = encodeVarintControl(dAtA, i, uint64(mapSize))
1304
+			dAtA[i] = 0xa
1305
+			i++
1306
+			i = encodeVarintControl(dAtA, i, uint64(len(k)))
1307
+			i += copy(dAtA[i:], k)
1308
+			dAtA[i] = 0x12
1309
+			i++
1310
+			i = encodeVarintControl(dAtA, i, uint64(len(v)))
1311
+			i += copy(dAtA[i:], v)
1312
+		}
1313
+	}
1314
+	if len(m.Exports) > 0 {
1315
+		for _, msg := range m.Exports {
1316
+			dAtA[i] = 0x22
1317
+			i++
1318
+			i = encodeVarintControl(dAtA, i, uint64(msg.Size()))
1319
+			n, err := msg.MarshalTo(dAtA[i:])
1320
+			if err != nil {
1321
+				return 0, err
1322
+			}
1323
+			i += n
1324
+		}
1325
+	}
1326
+	if len(m.Imports) > 0 {
1327
+		for _, msg := range m.Imports {
1328
+			dAtA[i] = 0x2a
1329
+			i++
1330
+			i = encodeVarintControl(dAtA, i, uint64(msg.Size()))
1331
+			n, err := msg.MarshalTo(dAtA[i:])
1332
+			if err != nil {
1333
+				return 0, err
1334
+			}
1335
+			i += n
1336
+		}
1337
+	}
1338
+	if m.XXX_unrecognized != nil {
1339
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1340
+	}
1341
+	return i, nil
1342
+}
1343
+
1344
+func (m *CacheOptionsEntry) Marshal() (dAtA []byte, err error) {
1345
+	size := m.Size()
1346
+	dAtA = make([]byte, size)
1347
+	n, err := m.MarshalTo(dAtA)
1348
+	if err != nil {
1349
+		return nil, err
1350
+	}
1351
+	return dAtA[:n], nil
1352
+}
1353
+
1354
+func (m *CacheOptionsEntry) MarshalTo(dAtA []byte) (int, error) {
1355
+	var i int
1356
+	_ = i
1357
+	var l int
1358
+	_ = l
1359
+	if len(m.Type) > 0 {
1360
+		dAtA[i] = 0xa
1361
+		i++
1362
+		i = encodeVarintControl(dAtA, i, uint64(len(m.Type)))
1363
+		i += copy(dAtA[i:], m.Type)
1364
+	}
1365
+	if len(m.Attrs) > 0 {
1366
+		for k, _ := range m.Attrs {
1367
+			dAtA[i] = 0x12
1368
+			i++
1369
+			v := m.Attrs[k]
1302 1370
 			mapSize := 1 + len(k) + sovControl(uint64(len(k))) + 1 + len(v) + sovControl(uint64(len(v)))
1303 1371
 			i = encodeVarintControl(dAtA, i, uint64(mapSize))
1304 1372
 			dAtA[i] = 0xa
... ...
@@ -1311,6 +1930,9 @@ func (m *CacheOptions) MarshalTo(dAtA []byte) (int, error) {
1311 1311
 			i += copy(dAtA[i:], v)
1312 1312
 		}
1313 1313
 	}
1314
+	if m.XXX_unrecognized != nil {
1315
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1316
+	}
1314 1317
 	return i, nil
1315 1318
 }
1316 1319
 
... ...
@@ -1346,6 +1968,9 @@ func (m *SolveResponse) MarshalTo(dAtA []byte) (int, error) {
1346 1346
 			i += copy(dAtA[i:], v)
1347 1347
 		}
1348 1348
 	}
1349
+	if m.XXX_unrecognized != nil {
1350
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1351
+	}
1349 1352
 	return i, nil
1350 1353
 }
1351 1354
 
... ...
@@ -1370,6 +1995,9 @@ func (m *StatusRequest) MarshalTo(dAtA []byte) (int, error) {
1370 1370
 		i = encodeVarintControl(dAtA, i, uint64(len(m.Ref)))
1371 1371
 		i += copy(dAtA[i:], m.Ref)
1372 1372
 	}
1373
+	if m.XXX_unrecognized != nil {
1374
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1375
+	}
1373 1376
 	return i, nil
1374 1377
 }
1375 1378
 
... ...
@@ -1424,6 +2052,9 @@ func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) {
1424 1424
 			i += n
1425 1425
 		}
1426 1426
 	}
1427
+	if m.XXX_unrecognized != nil {
1428
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1429
+	}
1427 1430
 	return i, nil
1428 1431
 }
1429 1432
 
... ...
@@ -1482,8 +2113,8 @@ func (m *Vertex) MarshalTo(dAtA []byte) (int, error) {
1482 1482
 	if m.Started != nil {
1483 1483
 		dAtA[i] = 0x2a
1484 1484
 		i++
1485
-		i = encodeVarintControl(dAtA, i, uint64(types.SizeOfStdTime(*m.Started)))
1486
-		n5, err := types.StdTimeMarshalTo(*m.Started, dAtA[i:])
1485
+		i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.Started)))
1486
+		n5, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Started, dAtA[i:])
1487 1487
 		if err != nil {
1488 1488
 			return 0, err
1489 1489
 		}
... ...
@@ -1492,8 +2123,8 @@ func (m *Vertex) MarshalTo(dAtA []byte) (int, error) {
1492 1492
 	if m.Completed != nil {
1493 1493
 		dAtA[i] = 0x32
1494 1494
 		i++
1495
-		i = encodeVarintControl(dAtA, i, uint64(types.SizeOfStdTime(*m.Completed)))
1496
-		n6, err := types.StdTimeMarshalTo(*m.Completed, dAtA[i:])
1495
+		i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.Completed)))
1496
+		n6, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Completed, dAtA[i:])
1497 1497
 		if err != nil {
1498 1498
 			return 0, err
1499 1499
 		}
... ...
@@ -1505,6 +2136,9 @@ func (m *Vertex) MarshalTo(dAtA []byte) (int, error) {
1505 1505
 		i = encodeVarintControl(dAtA, i, uint64(len(m.Error)))
1506 1506
 		i += copy(dAtA[i:], m.Error)
1507 1507
 	}
1508
+	if m.XXX_unrecognized != nil {
1509
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1510
+	}
1508 1511
 	return i, nil
1509 1512
 }
1510 1513
 
... ...
@@ -1553,8 +2187,8 @@ func (m *VertexStatus) MarshalTo(dAtA []byte) (int, error) {
1553 1553
 	}
1554 1554
 	dAtA[i] = 0x32
1555 1555
 	i++
1556
-	i = encodeVarintControl(dAtA, i, uint64(types.SizeOfStdTime(m.Timestamp)))
1557
-	n7, err := types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
1556
+	i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp)))
1557
+	n7, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
1558 1558
 	if err != nil {
1559 1559
 		return 0, err
1560 1560
 	}
... ...
@@ -1562,8 +2196,8 @@ func (m *VertexStatus) MarshalTo(dAtA []byte) (int, error) {
1562 1562
 	if m.Started != nil {
1563 1563
 		dAtA[i] = 0x3a
1564 1564
 		i++
1565
-		i = encodeVarintControl(dAtA, i, uint64(types.SizeOfStdTime(*m.Started)))
1566
-		n8, err := types.StdTimeMarshalTo(*m.Started, dAtA[i:])
1565
+		i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.Started)))
1566
+		n8, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Started, dAtA[i:])
1567 1567
 		if err != nil {
1568 1568
 			return 0, err
1569 1569
 		}
... ...
@@ -1572,13 +2206,16 @@ func (m *VertexStatus) MarshalTo(dAtA []byte) (int, error) {
1572 1572
 	if m.Completed != nil {
1573 1573
 		dAtA[i] = 0x42
1574 1574
 		i++
1575
-		i = encodeVarintControl(dAtA, i, uint64(types.SizeOfStdTime(*m.Completed)))
1576
-		n9, err := types.StdTimeMarshalTo(*m.Completed, dAtA[i:])
1575
+		i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.Completed)))
1576
+		n9, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Completed, dAtA[i:])
1577 1577
 		if err != nil {
1578 1578
 			return 0, err
1579 1579
 		}
1580 1580
 		i += n9
1581 1581
 	}
1582
+	if m.XXX_unrecognized != nil {
1583
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1584
+	}
1582 1585
 	return i, nil
1583 1586
 }
1584 1587
 
... ...
@@ -1605,8 +2242,8 @@ func (m *VertexLog) MarshalTo(dAtA []byte) (int, error) {
1605 1605
 	}
1606 1606
 	dAtA[i] = 0x12
1607 1607
 	i++
1608
-	i = encodeVarintControl(dAtA, i, uint64(types.SizeOfStdTime(m.Timestamp)))
1609
-	n10, err := types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
1608
+	i = encodeVarintControl(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp)))
1609
+	n10, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
1610 1610
 	if err != nil {
1611 1611
 		return 0, err
1612 1612
 	}
... ...
@@ -1622,6 +2259,9 @@ func (m *VertexLog) MarshalTo(dAtA []byte) (int, error) {
1622 1622
 		i = encodeVarintControl(dAtA, i, uint64(len(m.Msg)))
1623 1623
 		i += copy(dAtA[i:], m.Msg)
1624 1624
 	}
1625
+	if m.XXX_unrecognized != nil {
1626
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1627
+	}
1625 1628
 	return i, nil
1626 1629
 }
1627 1630
 
... ...
@@ -1646,6 +2286,9 @@ func (m *BytesMessage) MarshalTo(dAtA []byte) (int, error) {
1646 1646
 		i = encodeVarintControl(dAtA, i, uint64(len(m.Data)))
1647 1647
 		i += copy(dAtA[i:], m.Data)
1648 1648
 	}
1649
+	if m.XXX_unrecognized != nil {
1650
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1651
+	}
1649 1652
 	return i, nil
1650 1653
 }
1651 1654
 
... ...
@@ -1679,6 +2322,9 @@ func (m *ListWorkersRequest) MarshalTo(dAtA []byte) (int, error) {
1679 1679
 			i += copy(dAtA[i:], s)
1680 1680
 		}
1681 1681
 	}
1682
+	if m.XXX_unrecognized != nil {
1683
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1684
+	}
1682 1685
 	return i, nil
1683 1686
 }
1684 1687
 
... ...
@@ -1709,6 +2355,9 @@ func (m *ListWorkersResponse) MarshalTo(dAtA []byte) (int, error) {
1709 1709
 			i += n
1710 1710
 		}
1711 1711
 	}
1712
+	if m.XXX_unrecognized != nil {
1713
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1714
+	}
1712 1715
 	return i, nil
1713 1716
 }
1714 1717
 
... ...
@@ -1722,6 +2371,9 @@ func encodeVarintControl(dAtA []byte, offset int, v uint64) int {
1722 1722
 	return offset + 1
1723 1723
 }
1724 1724
 func (m *PruneRequest) Size() (n int) {
1725
+	if m == nil {
1726
+		return 0
1727
+	}
1725 1728
 	var l int
1726 1729
 	_ = l
1727 1730
 	if len(m.Filter) > 0 {
... ...
@@ -1739,10 +2391,16 @@ func (m *PruneRequest) Size() (n int) {
1739 1739
 	if m.KeepBytes != 0 {
1740 1740
 		n += 1 + sovControl(uint64(m.KeepBytes))
1741 1741
 	}
1742
+	if m.XXX_unrecognized != nil {
1743
+		n += len(m.XXX_unrecognized)
1744
+	}
1742 1745
 	return n
1743 1746
 }
1744 1747
 
1745 1748
 func (m *DiskUsageRequest) Size() (n int) {
1749
+	if m == nil {
1750
+		return 0
1751
+	}
1746 1752
 	var l int
1747 1753
 	_ = l
1748 1754
 	if len(m.Filter) > 0 {
... ...
@@ -1751,10 +2409,16 @@ func (m *DiskUsageRequest) Size() (n int) {
1751 1751
 			n += 1 + l + sovControl(uint64(l))
1752 1752
 		}
1753 1753
 	}
1754
+	if m.XXX_unrecognized != nil {
1755
+		n += len(m.XXX_unrecognized)
1756
+	}
1754 1757
 	return n
1755 1758
 }
1756 1759
 
1757 1760
 func (m *DiskUsageResponse) Size() (n int) {
1761
+	if m == nil {
1762
+		return 0
1763
+	}
1758 1764
 	var l int
1759 1765
 	_ = l
1760 1766
 	if len(m.Record) > 0 {
... ...
@@ -1763,10 +2427,16 @@ func (m *DiskUsageResponse) Size() (n int) {
1763 1763
 			n += 1 + l + sovControl(uint64(l))
1764 1764
 		}
1765 1765
 	}
1766
+	if m.XXX_unrecognized != nil {
1767
+		n += len(m.XXX_unrecognized)
1768
+	}
1766 1769
 	return n
1767 1770
 }
1768 1771
 
1769 1772
 func (m *UsageRecord) Size() (n int) {
1773
+	if m == nil {
1774
+		return 0
1775
+	}
1770 1776
 	var l int
1771 1777
 	_ = l
1772 1778
 	l = len(m.ID)
... ...
@@ -1786,10 +2456,10 @@ func (m *UsageRecord) Size() (n int) {
1786 1786
 	if l > 0 {
1787 1787
 		n += 1 + l + sovControl(uint64(l))
1788 1788
 	}
1789
-	l = types.SizeOfStdTime(m.CreatedAt)
1789
+	l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt)
1790 1790
 	n += 1 + l + sovControl(uint64(l))
1791 1791
 	if m.LastUsedAt != nil {
1792
-		l = types.SizeOfStdTime(*m.LastUsedAt)
1792
+		l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.LastUsedAt)
1793 1793
 		n += 1 + l + sovControl(uint64(l))
1794 1794
 	}
1795 1795
 	if m.UsageCount != 0 {
... ...
@@ -1806,10 +2476,16 @@ func (m *UsageRecord) Size() (n int) {
1806 1806
 	if m.Shared {
1807 1807
 		n += 2
1808 1808
 	}
1809
+	if m.XXX_unrecognized != nil {
1810
+		n += len(m.XXX_unrecognized)
1811
+	}
1809 1812
 	return n
1810 1813
 }
1811 1814
 
1812 1815
 func (m *SolveRequest) Size() (n int) {
1816
+	if m == nil {
1817
+		return 0
1818
+	}
1813 1819
 	var l int
1814 1820
 	_ = l
1815 1821
 	l = len(m.Ref)
... ...
@@ -1856,34 +2532,82 @@ func (m *SolveRequest) Size() (n int) {
1856 1856
 			n += 1 + l + sovControl(uint64(l))
1857 1857
 		}
1858 1858
 	}
1859
+	if m.XXX_unrecognized != nil {
1860
+		n += len(m.XXX_unrecognized)
1861
+	}
1859 1862
 	return n
1860 1863
 }
1861 1864
 
1862 1865
 func (m *CacheOptions) Size() (n int) {
1866
+	if m == nil {
1867
+		return 0
1868
+	}
1863 1869
 	var l int
1864 1870
 	_ = l
1865
-	l = len(m.ExportRef)
1871
+	l = len(m.ExportRefDeprecated)
1866 1872
 	if l > 0 {
1867 1873
 		n += 1 + l + sovControl(uint64(l))
1868 1874
 	}
1869
-	if len(m.ImportRefs) > 0 {
1870
-		for _, s := range m.ImportRefs {
1875
+	if len(m.ImportRefsDeprecated) > 0 {
1876
+		for _, s := range m.ImportRefsDeprecated {
1871 1877
 			l = len(s)
1872 1878
 			n += 1 + l + sovControl(uint64(l))
1873 1879
 		}
1874 1880
 	}
1875
-	if len(m.ExportAttrs) > 0 {
1876
-		for k, v := range m.ExportAttrs {
1881
+	if len(m.ExportAttrsDeprecated) > 0 {
1882
+		for k, v := range m.ExportAttrsDeprecated {
1877 1883
 			_ = k
1878 1884
 			_ = v
1879 1885
 			mapEntrySize := 1 + len(k) + sovControl(uint64(len(k))) + 1 + len(v) + sovControl(uint64(len(v)))
1880 1886
 			n += mapEntrySize + 1 + sovControl(uint64(mapEntrySize))
1881 1887
 		}
1882 1888
 	}
1889
+	if len(m.Exports) > 0 {
1890
+		for _, e := range m.Exports {
1891
+			l = e.Size()
1892
+			n += 1 + l + sovControl(uint64(l))
1893
+		}
1894
+	}
1895
+	if len(m.Imports) > 0 {
1896
+		for _, e := range m.Imports {
1897
+			l = e.Size()
1898
+			n += 1 + l + sovControl(uint64(l))
1899
+		}
1900
+	}
1901
+	if m.XXX_unrecognized != nil {
1902
+		n += len(m.XXX_unrecognized)
1903
+	}
1904
+	return n
1905
+}
1906
+
1907
+func (m *CacheOptionsEntry) Size() (n int) {
1908
+	if m == nil {
1909
+		return 0
1910
+	}
1911
+	var l int
1912
+	_ = l
1913
+	l = len(m.Type)
1914
+	if l > 0 {
1915
+		n += 1 + l + sovControl(uint64(l))
1916
+	}
1917
+	if len(m.Attrs) > 0 {
1918
+		for k, v := range m.Attrs {
1919
+			_ = k
1920
+			_ = v
1921
+			mapEntrySize := 1 + len(k) + sovControl(uint64(len(k))) + 1 + len(v) + sovControl(uint64(len(v)))
1922
+			n += mapEntrySize + 1 + sovControl(uint64(mapEntrySize))
1923
+		}
1924
+	}
1925
+	if m.XXX_unrecognized != nil {
1926
+		n += len(m.XXX_unrecognized)
1927
+	}
1883 1928
 	return n
1884 1929
 }
1885 1930
 
1886 1931
 func (m *SolveResponse) Size() (n int) {
1932
+	if m == nil {
1933
+		return 0
1934
+	}
1887 1935
 	var l int
1888 1936
 	_ = l
1889 1937
 	if len(m.ExporterResponse) > 0 {
... ...
@@ -1894,20 +2618,32 @@ func (m *SolveResponse) Size() (n int) {
1894 1894
 			n += mapEntrySize + 1 + sovControl(uint64(mapEntrySize))
1895 1895
 		}
1896 1896
 	}
1897
+	if m.XXX_unrecognized != nil {
1898
+		n += len(m.XXX_unrecognized)
1899
+	}
1897 1900
 	return n
1898 1901
 }
1899 1902
 
1900 1903
 func (m *StatusRequest) Size() (n int) {
1904
+	if m == nil {
1905
+		return 0
1906
+	}
1901 1907
 	var l int
1902 1908
 	_ = l
1903 1909
 	l = len(m.Ref)
1904 1910
 	if l > 0 {
1905 1911
 		n += 1 + l + sovControl(uint64(l))
1906 1912
 	}
1913
+	if m.XXX_unrecognized != nil {
1914
+		n += len(m.XXX_unrecognized)
1915
+	}
1907 1916
 	return n
1908 1917
 }
1909 1918
 
1910 1919
 func (m *StatusResponse) Size() (n int) {
1920
+	if m == nil {
1921
+		return 0
1922
+	}
1911 1923
 	var l int
1912 1924
 	_ = l
1913 1925
 	if len(m.Vertexes) > 0 {
... ...
@@ -1928,10 +2664,16 @@ func (m *StatusResponse) Size() (n int) {
1928 1928
 			n += 1 + l + sovControl(uint64(l))
1929 1929
 		}
1930 1930
 	}
1931
+	if m.XXX_unrecognized != nil {
1932
+		n += len(m.XXX_unrecognized)
1933
+	}
1931 1934
 	return n
1932 1935
 }
1933 1936
 
1934 1937
 func (m *Vertex) Size() (n int) {
1938
+	if m == nil {
1939
+		return 0
1940
+	}
1935 1941
 	var l int
1936 1942
 	_ = l
1937 1943
 	l = len(m.Digest)
... ...
@@ -1952,21 +2694,27 @@ func (m *Vertex) Size() (n int) {
1952 1952
 		n += 2
1953 1953
 	}
1954 1954
 	if m.Started != nil {
1955
-		l = types.SizeOfStdTime(*m.Started)
1955
+		l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.Started)
1956 1956
 		n += 1 + l + sovControl(uint64(l))
1957 1957
 	}
1958 1958
 	if m.Completed != nil {
1959
-		l = types.SizeOfStdTime(*m.Completed)
1959
+		l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.Completed)
1960 1960
 		n += 1 + l + sovControl(uint64(l))
1961 1961
 	}
1962 1962
 	l = len(m.Error)
1963 1963
 	if l > 0 {
1964 1964
 		n += 1 + l + sovControl(uint64(l))
1965 1965
 	}
1966
+	if m.XXX_unrecognized != nil {
1967
+		n += len(m.XXX_unrecognized)
1968
+	}
1966 1969
 	return n
1967 1970
 }
1968 1971
 
1969 1972
 func (m *VertexStatus) Size() (n int) {
1973
+	if m == nil {
1974
+		return 0
1975
+	}
1970 1976
 	var l int
1971 1977
 	_ = l
1972 1978
 	l = len(m.ID)
... ...
@@ -1987,27 +2735,33 @@ func (m *VertexStatus) Size() (n int) {
1987 1987
 	if m.Total != 0 {
1988 1988
 		n += 1 + sovControl(uint64(m.Total))
1989 1989
 	}
1990
-	l = types.SizeOfStdTime(m.Timestamp)
1990
+	l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp)
1991 1991
 	n += 1 + l + sovControl(uint64(l))
1992 1992
 	if m.Started != nil {
1993
-		l = types.SizeOfStdTime(*m.Started)
1993
+		l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.Started)
1994 1994
 		n += 1 + l + sovControl(uint64(l))
1995 1995
 	}
1996 1996
 	if m.Completed != nil {
1997
-		l = types.SizeOfStdTime(*m.Completed)
1997
+		l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.Completed)
1998 1998
 		n += 1 + l + sovControl(uint64(l))
1999 1999
 	}
2000
+	if m.XXX_unrecognized != nil {
2001
+		n += len(m.XXX_unrecognized)
2002
+	}
2000 2003
 	return n
2001 2004
 }
2002 2005
 
2003 2006
 func (m *VertexLog) Size() (n int) {
2007
+	if m == nil {
2008
+		return 0
2009
+	}
2004 2010
 	var l int
2005 2011
 	_ = l
2006 2012
 	l = len(m.Vertex)
2007 2013
 	if l > 0 {
2008 2014
 		n += 1 + l + sovControl(uint64(l))
2009 2015
 	}
2010
-	l = types.SizeOfStdTime(m.Timestamp)
2016
+	l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp)
2011 2017
 	n += 1 + l + sovControl(uint64(l))
2012 2018
 	if m.Stream != 0 {
2013 2019
 		n += 1 + sovControl(uint64(m.Stream))
... ...
@@ -2016,20 +2770,32 @@ func (m *VertexLog) Size() (n int) {
2016 2016
 	if l > 0 {
2017 2017
 		n += 1 + l + sovControl(uint64(l))
2018 2018
 	}
2019
+	if m.XXX_unrecognized != nil {
2020
+		n += len(m.XXX_unrecognized)
2021
+	}
2019 2022
 	return n
2020 2023
 }
2021 2024
 
2022 2025
 func (m *BytesMessage) Size() (n int) {
2026
+	if m == nil {
2027
+		return 0
2028
+	}
2023 2029
 	var l int
2024 2030
 	_ = l
2025 2031
 	l = len(m.Data)
2026 2032
 	if l > 0 {
2027 2033
 		n += 1 + l + sovControl(uint64(l))
2028 2034
 	}
2035
+	if m.XXX_unrecognized != nil {
2036
+		n += len(m.XXX_unrecognized)
2037
+	}
2029 2038
 	return n
2030 2039
 }
2031 2040
 
2032 2041
 func (m *ListWorkersRequest) Size() (n int) {
2042
+	if m == nil {
2043
+		return 0
2044
+	}
2033 2045
 	var l int
2034 2046
 	_ = l
2035 2047
 	if len(m.Filter) > 0 {
... ...
@@ -2038,10 +2804,16 @@ func (m *ListWorkersRequest) Size() (n int) {
2038 2038
 			n += 1 + l + sovControl(uint64(l))
2039 2039
 		}
2040 2040
 	}
2041
+	if m.XXX_unrecognized != nil {
2042
+		n += len(m.XXX_unrecognized)
2043
+	}
2041 2044
 	return n
2042 2045
 }
2043 2046
 
2044 2047
 func (m *ListWorkersResponse) Size() (n int) {
2048
+	if m == nil {
2049
+		return 0
2050
+	}
2045 2051
 	var l int
2046 2052
 	_ = l
2047 2053
 	if len(m.Record) > 0 {
... ...
@@ -2050,6 +2822,9 @@ func (m *ListWorkersResponse) Size() (n int) {
2050 2050
 			n += 1 + l + sovControl(uint64(l))
2051 2051
 		}
2052 2052
 	}
2053
+	if m.XXX_unrecognized != nil {
2054
+		n += len(m.XXX_unrecognized)
2055
+	}
2053 2056
 	return n
2054 2057
 }
2055 2058
 
... ...
@@ -2194,6 +2969,7 @@ func (m *PruneRequest) Unmarshal(dAtA []byte) error {
2194 2194
 			if (iNdEx + skippy) > l {
2195 2195
 				return io.ErrUnexpectedEOF
2196 2196
 			}
2197
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
2197 2198
 			iNdEx += skippy
2198 2199
 		}
2199 2200
 	}
... ...
@@ -2273,6 +3049,7 @@ func (m *DiskUsageRequest) Unmarshal(dAtA []byte) error {
2273 2273
 			if (iNdEx + skippy) > l {
2274 2274
 				return io.ErrUnexpectedEOF
2275 2275
 			}
2276
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
2276 2277
 			iNdEx += skippy
2277 2278
 		}
2278 2279
 	}
... ...
@@ -2354,6 +3131,7 @@ func (m *DiskUsageResponse) Unmarshal(dAtA []byte) error {
2354 2354
 			if (iNdEx + skippy) > l {
2355 2355
 				return io.ErrUnexpectedEOF
2356 2356
 			}
2357
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
2357 2358
 			iNdEx += skippy
2358 2359
 		}
2359 2360
 	}
... ...
@@ -2535,7 +3313,7 @@ func (m *UsageRecord) Unmarshal(dAtA []byte) error {
2535 2535
 			if postIndex > l {
2536 2536
 				return io.ErrUnexpectedEOF
2537 2537
 			}
2538
-			if err := types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
2538
+			if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
2539 2539
 				return err
2540 2540
 			}
2541 2541
 			iNdEx = postIndex
... ...
@@ -2568,7 +3346,7 @@ func (m *UsageRecord) Unmarshal(dAtA []byte) error {
2568 2568
 			if m.LastUsedAt == nil {
2569 2569
 				m.LastUsedAt = new(time.Time)
2570 2570
 			}
2571
-			if err := types.StdTimeUnmarshal(m.LastUsedAt, dAtA[iNdEx:postIndex]); err != nil {
2571
+			if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.LastUsedAt, dAtA[iNdEx:postIndex]); err != nil {
2572 2572
 				return err
2573 2573
 			}
2574 2574
 			iNdEx = postIndex
... ...
@@ -2681,6 +3459,7 @@ func (m *UsageRecord) Unmarshal(dAtA []byte) error {
2681 2681
 			if (iNdEx + skippy) > l {
2682 2682
 				return io.ErrUnexpectedEOF
2683 2683
 			}
2684
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
2684 2685
 			iNdEx += skippy
2685 2686
 		}
2686 2687
 	}
... ...
@@ -3175,6 +3954,7 @@ func (m *SolveRequest) Unmarshal(dAtA []byte) error {
3175 3175
 			if (iNdEx + skippy) > l {
3176 3176
 				return io.ErrUnexpectedEOF
3177 3177
 			}
3178
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3178 3179
 			iNdEx += skippy
3179 3180
 		}
3180 3181
 	}
... ...
@@ -3215,7 +3995,7 @@ func (m *CacheOptions) Unmarshal(dAtA []byte) error {
3215 3215
 		switch fieldNum {
3216 3216
 		case 1:
3217 3217
 			if wireType != 2 {
3218
-				return fmt.Errorf("proto: wrong wireType = %d for field ExportRef", wireType)
3218
+				return fmt.Errorf("proto: wrong wireType = %d for field ExportRefDeprecated", wireType)
3219 3219
 			}
3220 3220
 			var stringLen uint64
3221 3221
 			for shift := uint(0); ; shift += 7 {
... ...
@@ -3240,11 +4020,11 @@ func (m *CacheOptions) Unmarshal(dAtA []byte) error {
3240 3240
 			if postIndex > l {
3241 3241
 				return io.ErrUnexpectedEOF
3242 3242
 			}
3243
-			m.ExportRef = string(dAtA[iNdEx:postIndex])
3243
+			m.ExportRefDeprecated = string(dAtA[iNdEx:postIndex])
3244 3244
 			iNdEx = postIndex
3245 3245
 		case 2:
3246 3246
 			if wireType != 2 {
3247
-				return fmt.Errorf("proto: wrong wireType = %d for field ImportRefs", wireType)
3247
+				return fmt.Errorf("proto: wrong wireType = %d for field ImportRefsDeprecated", wireType)
3248 3248
 			}
3249 3249
 			var stringLen uint64
3250 3250
 			for shift := uint(0); ; shift += 7 {
... ...
@@ -3269,11 +4049,271 @@ func (m *CacheOptions) Unmarshal(dAtA []byte) error {
3269 3269
 			if postIndex > l {
3270 3270
 				return io.ErrUnexpectedEOF
3271 3271
 			}
3272
-			m.ImportRefs = append(m.ImportRefs, string(dAtA[iNdEx:postIndex]))
3272
+			m.ImportRefsDeprecated = append(m.ImportRefsDeprecated, string(dAtA[iNdEx:postIndex]))
3273 3273
 			iNdEx = postIndex
3274 3274
 		case 3:
3275 3275
 			if wireType != 2 {
3276
-				return fmt.Errorf("proto: wrong wireType = %d for field ExportAttrs", wireType)
3276
+				return fmt.Errorf("proto: wrong wireType = %d for field ExportAttrsDeprecated", wireType)
3277
+			}
3278
+			var msglen int
3279
+			for shift := uint(0); ; shift += 7 {
3280
+				if shift >= 64 {
3281
+					return ErrIntOverflowControl
3282
+				}
3283
+				if iNdEx >= l {
3284
+					return io.ErrUnexpectedEOF
3285
+				}
3286
+				b := dAtA[iNdEx]
3287
+				iNdEx++
3288
+				msglen |= (int(b) & 0x7F) << shift
3289
+				if b < 0x80 {
3290
+					break
3291
+				}
3292
+			}
3293
+			if msglen < 0 {
3294
+				return ErrInvalidLengthControl
3295
+			}
3296
+			postIndex := iNdEx + msglen
3297
+			if postIndex > l {
3298
+				return io.ErrUnexpectedEOF
3299
+			}
3300
+			if m.ExportAttrsDeprecated == nil {
3301
+				m.ExportAttrsDeprecated = make(map[string]string)
3302
+			}
3303
+			var mapkey string
3304
+			var mapvalue string
3305
+			for iNdEx < postIndex {
3306
+				entryPreIndex := iNdEx
3307
+				var wire uint64
3308
+				for shift := uint(0); ; shift += 7 {
3309
+					if shift >= 64 {
3310
+						return ErrIntOverflowControl
3311
+					}
3312
+					if iNdEx >= l {
3313
+						return io.ErrUnexpectedEOF
3314
+					}
3315
+					b := dAtA[iNdEx]
3316
+					iNdEx++
3317
+					wire |= (uint64(b) & 0x7F) << shift
3318
+					if b < 0x80 {
3319
+						break
3320
+					}
3321
+				}
3322
+				fieldNum := int32(wire >> 3)
3323
+				if fieldNum == 1 {
3324
+					var stringLenmapkey uint64
3325
+					for shift := uint(0); ; shift += 7 {
3326
+						if shift >= 64 {
3327
+							return ErrIntOverflowControl
3328
+						}
3329
+						if iNdEx >= l {
3330
+							return io.ErrUnexpectedEOF
3331
+						}
3332
+						b := dAtA[iNdEx]
3333
+						iNdEx++
3334
+						stringLenmapkey |= (uint64(b) & 0x7F) << shift
3335
+						if b < 0x80 {
3336
+							break
3337
+						}
3338
+					}
3339
+					intStringLenmapkey := int(stringLenmapkey)
3340
+					if intStringLenmapkey < 0 {
3341
+						return ErrInvalidLengthControl
3342
+					}
3343
+					postStringIndexmapkey := iNdEx + intStringLenmapkey
3344
+					if postStringIndexmapkey > l {
3345
+						return io.ErrUnexpectedEOF
3346
+					}
3347
+					mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
3348
+					iNdEx = postStringIndexmapkey
3349
+				} else if fieldNum == 2 {
3350
+					var stringLenmapvalue uint64
3351
+					for shift := uint(0); ; shift += 7 {
3352
+						if shift >= 64 {
3353
+							return ErrIntOverflowControl
3354
+						}
3355
+						if iNdEx >= l {
3356
+							return io.ErrUnexpectedEOF
3357
+						}
3358
+						b := dAtA[iNdEx]
3359
+						iNdEx++
3360
+						stringLenmapvalue |= (uint64(b) & 0x7F) << shift
3361
+						if b < 0x80 {
3362
+							break
3363
+						}
3364
+					}
3365
+					intStringLenmapvalue := int(stringLenmapvalue)
3366
+					if intStringLenmapvalue < 0 {
3367
+						return ErrInvalidLengthControl
3368
+					}
3369
+					postStringIndexmapvalue := iNdEx + intStringLenmapvalue
3370
+					if postStringIndexmapvalue > l {
3371
+						return io.ErrUnexpectedEOF
3372
+					}
3373
+					mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue])
3374
+					iNdEx = postStringIndexmapvalue
3375
+				} else {
3376
+					iNdEx = entryPreIndex
3377
+					skippy, err := skipControl(dAtA[iNdEx:])
3378
+					if err != nil {
3379
+						return err
3380
+					}
3381
+					if skippy < 0 {
3382
+						return ErrInvalidLengthControl
3383
+					}
3384
+					if (iNdEx + skippy) > postIndex {
3385
+						return io.ErrUnexpectedEOF
3386
+					}
3387
+					iNdEx += skippy
3388
+				}
3389
+			}
3390
+			m.ExportAttrsDeprecated[mapkey] = mapvalue
3391
+			iNdEx = postIndex
3392
+		case 4:
3393
+			if wireType != 2 {
3394
+				return fmt.Errorf("proto: wrong wireType = %d for field Exports", wireType)
3395
+			}
3396
+			var msglen int
3397
+			for shift := uint(0); ; shift += 7 {
3398
+				if shift >= 64 {
3399
+					return ErrIntOverflowControl
3400
+				}
3401
+				if iNdEx >= l {
3402
+					return io.ErrUnexpectedEOF
3403
+				}
3404
+				b := dAtA[iNdEx]
3405
+				iNdEx++
3406
+				msglen |= (int(b) & 0x7F) << shift
3407
+				if b < 0x80 {
3408
+					break
3409
+				}
3410
+			}
3411
+			if msglen < 0 {
3412
+				return ErrInvalidLengthControl
3413
+			}
3414
+			postIndex := iNdEx + msglen
3415
+			if postIndex > l {
3416
+				return io.ErrUnexpectedEOF
3417
+			}
3418
+			m.Exports = append(m.Exports, &CacheOptionsEntry{})
3419
+			if err := m.Exports[len(m.Exports)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
3420
+				return err
3421
+			}
3422
+			iNdEx = postIndex
3423
+		case 5:
3424
+			if wireType != 2 {
3425
+				return fmt.Errorf("proto: wrong wireType = %d for field Imports", wireType)
3426
+			}
3427
+			var msglen int
3428
+			for shift := uint(0); ; shift += 7 {
3429
+				if shift >= 64 {
3430
+					return ErrIntOverflowControl
3431
+				}
3432
+				if iNdEx >= l {
3433
+					return io.ErrUnexpectedEOF
3434
+				}
3435
+				b := dAtA[iNdEx]
3436
+				iNdEx++
3437
+				msglen |= (int(b) & 0x7F) << shift
3438
+				if b < 0x80 {
3439
+					break
3440
+				}
3441
+			}
3442
+			if msglen < 0 {
3443
+				return ErrInvalidLengthControl
3444
+			}
3445
+			postIndex := iNdEx + msglen
3446
+			if postIndex > l {
3447
+				return io.ErrUnexpectedEOF
3448
+			}
3449
+			m.Imports = append(m.Imports, &CacheOptionsEntry{})
3450
+			if err := m.Imports[len(m.Imports)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
3451
+				return err
3452
+			}
3453
+			iNdEx = postIndex
3454
+		default:
3455
+			iNdEx = preIndex
3456
+			skippy, err := skipControl(dAtA[iNdEx:])
3457
+			if err != nil {
3458
+				return err
3459
+			}
3460
+			if skippy < 0 {
3461
+				return ErrInvalidLengthControl
3462
+			}
3463
+			if (iNdEx + skippy) > l {
3464
+				return io.ErrUnexpectedEOF
3465
+			}
3466
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3467
+			iNdEx += skippy
3468
+		}
3469
+	}
3470
+
3471
+	if iNdEx > l {
3472
+		return io.ErrUnexpectedEOF
3473
+	}
3474
+	return nil
3475
+}
3476
+func (m *CacheOptionsEntry) Unmarshal(dAtA []byte) error {
3477
+	l := len(dAtA)
3478
+	iNdEx := 0
3479
+	for iNdEx < l {
3480
+		preIndex := iNdEx
3481
+		var wire uint64
3482
+		for shift := uint(0); ; shift += 7 {
3483
+			if shift >= 64 {
3484
+				return ErrIntOverflowControl
3485
+			}
3486
+			if iNdEx >= l {
3487
+				return io.ErrUnexpectedEOF
3488
+			}
3489
+			b := dAtA[iNdEx]
3490
+			iNdEx++
3491
+			wire |= (uint64(b) & 0x7F) << shift
3492
+			if b < 0x80 {
3493
+				break
3494
+			}
3495
+		}
3496
+		fieldNum := int32(wire >> 3)
3497
+		wireType := int(wire & 0x7)
3498
+		if wireType == 4 {
3499
+			return fmt.Errorf("proto: CacheOptionsEntry: wiretype end group for non-group")
3500
+		}
3501
+		if fieldNum <= 0 {
3502
+			return fmt.Errorf("proto: CacheOptionsEntry: illegal tag %d (wire type %d)", fieldNum, wire)
3503
+		}
3504
+		switch fieldNum {
3505
+		case 1:
3506
+			if wireType != 2 {
3507
+				return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
3508
+			}
3509
+			var stringLen uint64
3510
+			for shift := uint(0); ; shift += 7 {
3511
+				if shift >= 64 {
3512
+					return ErrIntOverflowControl
3513
+				}
3514
+				if iNdEx >= l {
3515
+					return io.ErrUnexpectedEOF
3516
+				}
3517
+				b := dAtA[iNdEx]
3518
+				iNdEx++
3519
+				stringLen |= (uint64(b) & 0x7F) << shift
3520
+				if b < 0x80 {
3521
+					break
3522
+				}
3523
+			}
3524
+			intStringLen := int(stringLen)
3525
+			if intStringLen < 0 {
3526
+				return ErrInvalidLengthControl
3527
+			}
3528
+			postIndex := iNdEx + intStringLen
3529
+			if postIndex > l {
3530
+				return io.ErrUnexpectedEOF
3531
+			}
3532
+			m.Type = string(dAtA[iNdEx:postIndex])
3533
+			iNdEx = postIndex
3534
+		case 2:
3535
+			if wireType != 2 {
3536
+				return fmt.Errorf("proto: wrong wireType = %d for field Attrs", wireType)
3277 3537
 			}
3278 3538
 			var msglen int
3279 3539
 			for shift := uint(0); ; shift += 7 {
... ...
@@ -3297,8 +4337,8 @@ func (m *CacheOptions) Unmarshal(dAtA []byte) error {
3297 3297
 			if postIndex > l {
3298 3298
 				return io.ErrUnexpectedEOF
3299 3299
 			}
3300
-			if m.ExportAttrs == nil {
3301
-				m.ExportAttrs = make(map[string]string)
3300
+			if m.Attrs == nil {
3301
+				m.Attrs = make(map[string]string)
3302 3302
 			}
3303 3303
 			var mapkey string
3304 3304
 			var mapvalue string
... ...
@@ -3387,7 +4427,7 @@ func (m *CacheOptions) Unmarshal(dAtA []byte) error {
3387 3387
 					iNdEx += skippy
3388 3388
 				}
3389 3389
 			}
3390
-			m.ExportAttrs[mapkey] = mapvalue
3390
+			m.Attrs[mapkey] = mapvalue
3391 3391
 			iNdEx = postIndex
3392 3392
 		default:
3393 3393
 			iNdEx = preIndex
... ...
@@ -3401,6 +4441,7 @@ func (m *CacheOptions) Unmarshal(dAtA []byte) error {
3401 3401
 			if (iNdEx + skippy) > l {
3402 3402
 				return io.ErrUnexpectedEOF
3403 3403
 			}
3404
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3404 3405
 			iNdEx += skippy
3405 3406
 		}
3406 3407
 	}
... ...
@@ -3569,6 +4610,7 @@ func (m *SolveResponse) Unmarshal(dAtA []byte) error {
3569 3569
 			if (iNdEx + skippy) > l {
3570 3570
 				return io.ErrUnexpectedEOF
3571 3571
 			}
3572
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3572 3573
 			iNdEx += skippy
3573 3574
 		}
3574 3575
 	}
... ...
@@ -3648,6 +4690,7 @@ func (m *StatusRequest) Unmarshal(dAtA []byte) error {
3648 3648
 			if (iNdEx + skippy) > l {
3649 3649
 				return io.ErrUnexpectedEOF
3650 3650
 			}
3651
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3651 3652
 			iNdEx += skippy
3652 3653
 		}
3653 3654
 	}
... ...
@@ -3791,6 +4834,7 @@ func (m *StatusResponse) Unmarshal(dAtA []byte) error {
3791 3791
 			if (iNdEx + skippy) > l {
3792 3792
 				return io.ErrUnexpectedEOF
3793 3793
 			}
3794
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3794 3795
 			iNdEx += skippy
3795 3796
 		}
3796 3797
 	}
... ...
@@ -3965,7 +5009,7 @@ func (m *Vertex) Unmarshal(dAtA []byte) error {
3965 3965
 			if m.Started == nil {
3966 3966
 				m.Started = new(time.Time)
3967 3967
 			}
3968
-			if err := types.StdTimeUnmarshal(m.Started, dAtA[iNdEx:postIndex]); err != nil {
3968
+			if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.Started, dAtA[iNdEx:postIndex]); err != nil {
3969 3969
 				return err
3970 3970
 			}
3971 3971
 			iNdEx = postIndex
... ...
@@ -3998,7 +5042,7 @@ func (m *Vertex) Unmarshal(dAtA []byte) error {
3998 3998
 			if m.Completed == nil {
3999 3999
 				m.Completed = new(time.Time)
4000 4000
 			}
4001
-			if err := types.StdTimeUnmarshal(m.Completed, dAtA[iNdEx:postIndex]); err != nil {
4001
+			if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.Completed, dAtA[iNdEx:postIndex]); err != nil {
4002 4002
 				return err
4003 4003
 			}
4004 4004
 			iNdEx = postIndex
... ...
@@ -4043,6 +5087,7 @@ func (m *Vertex) Unmarshal(dAtA []byte) error {
4043 4043
 			if (iNdEx + skippy) > l {
4044 4044
 				return io.ErrUnexpectedEOF
4045 4045
 			}
4046
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
4046 4047
 			iNdEx += skippy
4047 4048
 		}
4048 4049
 	}
... ...
@@ -4232,7 +5277,7 @@ func (m *VertexStatus) Unmarshal(dAtA []byte) error {
4232 4232
 			if postIndex > l {
4233 4233
 				return io.ErrUnexpectedEOF
4234 4234
 			}
4235
-			if err := types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil {
4235
+			if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil {
4236 4236
 				return err
4237 4237
 			}
4238 4238
 			iNdEx = postIndex
... ...
@@ -4265,7 +5310,7 @@ func (m *VertexStatus) Unmarshal(dAtA []byte) error {
4265 4265
 			if m.Started == nil {
4266 4266
 				m.Started = new(time.Time)
4267 4267
 			}
4268
-			if err := types.StdTimeUnmarshal(m.Started, dAtA[iNdEx:postIndex]); err != nil {
4268
+			if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.Started, dAtA[iNdEx:postIndex]); err != nil {
4269 4269
 				return err
4270 4270
 			}
4271 4271
 			iNdEx = postIndex
... ...
@@ -4298,7 +5343,7 @@ func (m *VertexStatus) Unmarshal(dAtA []byte) error {
4298 4298
 			if m.Completed == nil {
4299 4299
 				m.Completed = new(time.Time)
4300 4300
 			}
4301
-			if err := types.StdTimeUnmarshal(m.Completed, dAtA[iNdEx:postIndex]); err != nil {
4301
+			if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.Completed, dAtA[iNdEx:postIndex]); err != nil {
4302 4302
 				return err
4303 4303
 			}
4304 4304
 			iNdEx = postIndex
... ...
@@ -4314,6 +5359,7 @@ func (m *VertexStatus) Unmarshal(dAtA []byte) error {
4314 4314
 			if (iNdEx + skippy) > l {
4315 4315
 				return io.ErrUnexpectedEOF
4316 4316
 			}
4317
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
4317 4318
 			iNdEx += skippy
4318 4319
 		}
4319 4320
 	}
... ...
@@ -4407,7 +5453,7 @@ func (m *VertexLog) Unmarshal(dAtA []byte) error {
4407 4407
 			if postIndex > l {
4408 4408
 				return io.ErrUnexpectedEOF
4409 4409
 			}
4410
-			if err := types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil {
4410
+			if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil {
4411 4411
 				return err
4412 4412
 			}
4413 4413
 			iNdEx = postIndex
... ...
@@ -4473,6 +5519,7 @@ func (m *VertexLog) Unmarshal(dAtA []byte) error {
4473 4473
 			if (iNdEx + skippy) > l {
4474 4474
 				return io.ErrUnexpectedEOF
4475 4475
 			}
4476
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
4476 4477
 			iNdEx += skippy
4477 4478
 		}
4478 4479
 	}
... ...
@@ -4554,6 +5601,7 @@ func (m *BytesMessage) Unmarshal(dAtA []byte) error {
4554 4554
 			if (iNdEx + skippy) > l {
4555 4555
 				return io.ErrUnexpectedEOF
4556 4556
 			}
4557
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
4557 4558
 			iNdEx += skippy
4558 4559
 		}
4559 4560
 	}
... ...
@@ -4633,6 +5681,7 @@ func (m *ListWorkersRequest) Unmarshal(dAtA []byte) error {
4633 4633
 			if (iNdEx + skippy) > l {
4634 4634
 				return io.ErrUnexpectedEOF
4635 4635
 			}
4636
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
4636 4637
 			iNdEx += skippy
4637 4638
 		}
4638 4639
 	}
... ...
@@ -4697,7 +5746,7 @@ func (m *ListWorkersResponse) Unmarshal(dAtA []byte) error {
4697 4697
 			if postIndex > l {
4698 4698
 				return io.ErrUnexpectedEOF
4699 4699
 			}
4700
-			m.Record = append(m.Record, &moby_buildkit_v1_types.WorkerRecord{})
4700
+			m.Record = append(m.Record, &types.WorkerRecord{})
4701 4701
 			if err := m.Record[len(m.Record)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
4702 4702
 				return err
4703 4703
 			}
... ...
@@ -4714,6 +5763,7 @@ func (m *ListWorkersResponse) Unmarshal(dAtA []byte) error {
4714 4714
 			if (iNdEx + skippy) > l {
4715 4715
 				return io.ErrUnexpectedEOF
4716 4716
 			}
4717
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
4717 4718
 			iNdEx += skippy
4718 4719
 		}
4719 4720
 	}
... ...
@@ -4828,88 +5878,93 @@ var (
4828 4828
 	ErrIntOverflowControl   = fmt.Errorf("proto: integer overflow")
4829 4829
 )
4830 4830
 
4831
-func init() { proto.RegisterFile("control.proto", fileDescriptorControl) }
4832
-
4833
-var fileDescriptorControl = []byte{
4834
-	// 1279 bytes of a gzipped FileDescriptorProto
4835
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0x4f, 0x6f, 0x1b, 0x45,
4836
-	0x14, 0xef, 0xda, 0x89, 0xed, 0x7d, 0x76, 0xaa, 0x30, 0x40, 0xb5, 0x5a, 0x20, 0x31, 0x0b, 0x48,
4837
-	0x56, 0xd5, 0xee, 0xb6, 0x81, 0x22, 0x14, 0xa1, 0xaa, 0x75, 0x5c, 0x44, 0xaa, 0x46, 0x94, 0x49,
4838
-	0x4b, 0x25, 0x0e, 0x48, 0x6b, 0x7b, 0xe2, 0xae, 0xb2, 0xde, 0x59, 0x66, 0x66, 0x43, 0xcd, 0x07,
4839
-	0xe0, 0xcc, 0x77, 0xe1, 0xc0, 0x27, 0x40, 0xea, 0x91, 0x73, 0x0f, 0x29, 0xea, 0x1d, 0x4e, 0x5c,
4840
-	0xb8, 0xa1, 0xf9, 0xb3, 0xce, 0x38, 0x76, 0xea, 0xa6, 0x3d, 0x65, 0xde, 0xe4, 0xf7, 0x7e, 0xfb,
4841
-	0xfe, 0xcd, 0x7b, 0xcf, 0xb0, 0x36, 0xa0, 0x99, 0x60, 0x34, 0x0d, 0x73, 0x46, 0x05, 0x45, 0xeb,
4842
-	0x63, 0xda, 0x9f, 0x84, 0xfd, 0x22, 0x49, 0x87, 0x87, 0x89, 0x08, 0x8f, 0xae, 0xfb, 0x57, 0x47,
4843
-	0x89, 0x78, 0x5c, 0xf4, 0xc3, 0x01, 0x1d, 0x47, 0x23, 0x3a, 0xa2, 0x91, 0x02, 0xf6, 0x8b, 0x03,
4844
-	0x25, 0x29, 0x41, 0x9d, 0x34, 0x81, 0xbf, 0x39, 0xa2, 0x74, 0x94, 0x92, 0x13, 0x94, 0x48, 0xc6,
4845
-	0x84, 0x8b, 0x78, 0x9c, 0x1b, 0xc0, 0x15, 0x8b, 0x4f, 0x7e, 0x2c, 0x2a, 0x3f, 0x16, 0x71, 0x9a,
4846
-	0x1e, 0x11, 0x16, 0xe5, 0xfd, 0x88, 0xe6, 0xdc, 0xa0, 0xa3, 0x33, 0xd1, 0x71, 0x9e, 0x44, 0x62,
4847
-	0x92, 0x13, 0x1e, 0xfd, 0x44, 0xd9, 0x21, 0x61, 0x5a, 0x21, 0xf8, 0xc5, 0x81, 0xd6, 0x7d, 0x56,
4848
-	0x64, 0x04, 0x93, 0x1f, 0x0b, 0xc2, 0x05, 0xba, 0x04, 0xb5, 0x83, 0x24, 0x15, 0x84, 0x79, 0x4e,
4849
-	0xbb, 0xda, 0x71, 0xb1, 0x91, 0xd0, 0x3a, 0x54, 0xe3, 0x34, 0xf5, 0x2a, 0x6d, 0xa7, 0xd3, 0xc0,
4850
-	0xf2, 0x88, 0x3a, 0xd0, 0x3a, 0x24, 0x24, 0xef, 0x15, 0x2c, 0x16, 0x09, 0xcd, 0xbc, 0x6a, 0xdb,
4851
-	0xe9, 0x54, 0xbb, 0x2b, 0x4f, 0x8f, 0x37, 0x1d, 0x3c, 0xf3, 0x1f, 0x14, 0x80, 0x2b, 0xe5, 0xee,
4852
-	0x44, 0x10, 0xee, 0xad, 0x58, 0xb0, 0x93, 0xeb, 0xe0, 0x32, 0xac, 0xf7, 0x12, 0x7e, 0xf8, 0x90,
4853
-	0xc7, 0xa3, 0x65, 0xb6, 0x04, 0x77, 0xe1, 0x2d, 0x0b, 0xcb, 0x73, 0x9a, 0x71, 0x82, 0x6e, 0x40,
4854
-	0x8d, 0x91, 0x01, 0x65, 0x43, 0x05, 0x6e, 0x6e, 0x7d, 0x10, 0x9e, 0xce, 0x4d, 0x68, 0x14, 0x24,
4855
-	0x08, 0x1b, 0x70, 0xf0, 0x5f, 0x05, 0x9a, 0xd6, 0x3d, 0xba, 0x08, 0x95, 0xdd, 0x9e, 0xe7, 0xb4,
4856
-	0x9d, 0x8e, 0x8b, 0x2b, 0xbb, 0x3d, 0xe4, 0x41, 0x7d, 0xaf, 0x10, 0x71, 0x3f, 0x25, 0xc6, 0xf7,
4857
-	0x52, 0x44, 0xef, 0xc0, 0xea, 0x6e, 0xf6, 0x90, 0x13, 0xe5, 0x78, 0x03, 0x6b, 0x01, 0x21, 0x58,
4858
-	0xd9, 0x4f, 0x7e, 0x26, 0xda, 0x4d, 0xac, 0xce, 0xd2, 0x8f, 0xfb, 0x31, 0x23, 0x99, 0xf0, 0x56,
4859
-	0x15, 0xaf, 0x91, 0x50, 0x17, 0xdc, 0x1d, 0x46, 0x62, 0x41, 0x86, 0xb7, 0x85, 0x57, 0x6b, 0x3b,
4860
-	0x9d, 0xe6, 0x96, 0x1f, 0xea, 0x82, 0x08, 0xcb, 0x82, 0x08, 0x1f, 0x94, 0x05, 0xd1, 0x6d, 0x3c,
4861
-	0x3d, 0xde, 0xbc, 0xf0, 0xeb, 0x73, 0x19, 0xb7, 0xa9, 0x1a, 0xba, 0x05, 0x70, 0x2f, 0xe6, 0xe2,
4862
-	0x21, 0x57, 0x24, 0xf5, 0xa5, 0x24, 0x2b, 0x8a, 0xc0, 0xd2, 0x41, 0x1b, 0x00, 0x2a, 0x00, 0x3b,
4863
-	0xb4, 0xc8, 0x84, 0xd7, 0x50, 0x76, 0x5b, 0x37, 0xa8, 0x0d, 0xcd, 0x1e, 0xe1, 0x03, 0x96, 0xe4,
4864
-	0x2a, 0xcd, 0xae, 0x72, 0xc1, 0xbe, 0x92, 0x0c, 0x3a, 0x7a, 0x0f, 0x26, 0x39, 0xf1, 0x40, 0x01,
4865
-	0xac, 0x1b, 0xe9, 0xff, 0xfe, 0xe3, 0x98, 0x91, 0xa1, 0xd7, 0x54, 0xa1, 0x32, 0x52, 0xf0, 0xef,
4866
-	0x0a, 0xb4, 0xf6, 0x65, 0x15, 0x97, 0x09, 0x5f, 0x87, 0x2a, 0x26, 0x07, 0x26, 0xfa, 0xf2, 0x88,
4867
-	0x42, 0x80, 0x1e, 0x39, 0x48, 0xb2, 0x44, 0x7d, 0xbb, 0xa2, 0xdc, 0xbb, 0x18, 0xe6, 0xfd, 0xf0,
4868
-	0xe4, 0x16, 0x5b, 0x08, 0xe4, 0x43, 0xe3, 0xce, 0x93, 0x9c, 0x32, 0x59, 0x34, 0x55, 0x45, 0x33,
4869
-	0x95, 0xd1, 0x23, 0x58, 0x2b, 0xcf, 0xb7, 0x85, 0x60, 0xb2, 0x14, 0x65, 0xa1, 0x5c, 0x9f, 0x2f,
4870
-	0x14, 0xdb, 0xa8, 0x70, 0x46, 0xe7, 0x4e, 0x26, 0xd8, 0x04, 0xcf, 0xf2, 0xc8, 0x1a, 0xd9, 0x27,
4871
-	0x9c, 0x4b, 0x0b, 0x75, 0x82, 0x4b, 0x51, 0x9a, 0xf3, 0x15, 0xa3, 0x99, 0x20, 0xd9, 0x50, 0x25,
4872
-	0xd8, 0xc5, 0x53, 0x59, 0x9a, 0x53, 0x9e, 0xb5, 0x39, 0xf5, 0x57, 0x32, 0x67, 0x46, 0xc7, 0x98,
4873
-	0x33, 0x73, 0x87, 0xb6, 0x61, 0x75, 0x27, 0x1e, 0x3c, 0x26, 0x2a, 0x97, 0xcd, 0xad, 0x8d, 0x79,
4874
-	0x42, 0xf5, 0xef, 0x6f, 0x54, 0xf2, 0xb8, 0x7a, 0x8a, 0x17, 0xb0, 0x56, 0x41, 0x3f, 0x40, 0xeb,
4875
-	0x4e, 0x26, 0x12, 0x91, 0x92, 0x31, 0xc9, 0x04, 0xf7, 0x5c, 0xf9, 0xf0, 0xba, 0xdb, 0xcf, 0x8e,
4876
-	0x37, 0x3f, 0x3f, 0xb3, 0xb5, 0x14, 0x22, 0x49, 0x23, 0x62, 0x69, 0x85, 0x16, 0x05, 0x9e, 0xe1,
4877
-	0xf3, 0x6f, 0x01, 0x9a, 0x8f, 0xa7, 0xcc, 0xfb, 0x21, 0x99, 0x94, 0x79, 0x3f, 0x24, 0x13, 0xf9,
4878
-	0xb8, 0x8e, 0xe2, 0xb4, 0xd0, 0x8f, 0xce, 0xc5, 0x5a, 0xd8, 0xae, 0x7c, 0xe1, 0x48, 0x86, 0xf9,
4879
-	0x10, 0x9c, 0x87, 0x21, 0x78, 0xee, 0x40, 0xcb, 0x8e, 0x00, 0x7a, 0x1f, 0x5c, 0x6d, 0xd4, 0x49,
4880
-	0xf1, 0x9d, 0x5c, 0xc8, 0xea, 0xde, 0x1d, 0x1b, 0x81, 0x7b, 0x15, 0xd5, 0x89, 0xac, 0x1b, 0xf4,
4881
-	0x2d, 0x34, 0x35, 0x58, 0x67, 0xb1, 0xaa, 0xb2, 0x18, 0xbd, 0x3c, 0xe8, 0xa1, 0xa5, 0xa1, 0x73,
4882
-	0x68, 0x73, 0xf8, 0x37, 0x61, 0xfd, 0x34, 0xe0, 0x5c, 0x1e, 0xfe, 0xee, 0xc0, 0x9a, 0x29, 0x1a,
4883
-	0xd3, 0x1d, 0xe3, 0x92, 0x91, 0xb0, 0xf2, 0xce, 0xf4, 0xc9, 0x1b, 0x67, 0xd6, 0x9b, 0x86, 0x85,
4884
-	0xa7, 0xf5, 0xb4, 0xbd, 0x73, 0x74, 0xfe, 0x0e, 0xbc, 0xbb, 0x10, 0x7a, 0x2e, 0xcb, 0x3f, 0x84,
4885
-	0xb5, 0x7d, 0x11, 0x8b, 0x82, 0x9f, 0xd9, 0x12, 0x82, 0xdf, 0x1c, 0xb8, 0x58, 0x62, 0x8c, 0x77,
4886
-	0x9f, 0x41, 0xe3, 0x88, 0x30, 0x41, 0x9e, 0x10, 0x6e, 0xbc, 0xf2, 0xe6, 0xbd, 0xfa, 0x4e, 0x21,
4887
-	0xf0, 0x14, 0x89, 0xb6, 0xa1, 0xc1, 0x15, 0x0f, 0xd1, 0x69, 0x5d, 0xf8, 0x54, 0xb4, 0x96, 0xf9,
4888
-	0xde, 0x14, 0x8f, 0x22, 0x58, 0x49, 0xe9, 0xa8, 0xcc, 0xf6, 0x7b, 0x67, 0xe9, 0xdd, 0xa3, 0x23,
4889
-	0xac, 0x80, 0xc1, 0x71, 0x05, 0x6a, 0xfa, 0x0e, 0xdd, 0x85, 0xda, 0x30, 0x19, 0x11, 0x2e, 0xb4,
4890
-	0x57, 0xdd, 0x2d, 0xf9, 0x00, 0x9f, 0x1d, 0x6f, 0x5e, 0xb6, 0x5e, 0x18, 0xcd, 0x49, 0x26, 0x57,
4891
-	0x8d, 0x38, 0xc9, 0x08, 0xe3, 0xd1, 0x88, 0x5e, 0xd5, 0x2a, 0x61, 0x4f, 0xfd, 0xc1, 0x86, 0x41,
4892
-	0x72, 0x25, 0x59, 0x5e, 0x08, 0x53, 0x98, 0xaf, 0xc7, 0xa5, 0x19, 0xe4, 0xe8, 0xca, 0xe2, 0x31,
4893
-	0x31, 0x7d, 0x53, 0x9d, 0x65, 0xeb, 0x1e, 0xc8, 0xba, 0x1d, 0xaa, 0x81, 0xd6, 0xc0, 0x46, 0x42,
4894
-	0xdb, 0x50, 0xe7, 0x22, 0x66, 0x82, 0x0c, 0x55, 0xcb, 0x7b, 0x95, 0x99, 0x53, 0x2a, 0xa0, 0x9b,
4895
-	0xe0, 0x0e, 0xe8, 0x38, 0x4f, 0x89, 0xd4, 0xae, 0xbd, 0xa2, 0xf6, 0x89, 0x8a, 0xac, 0x1e, 0xc2,
4896
-	0x18, 0x65, 0x6a, 0xda, 0xb9, 0x58, 0x0b, 0xc1, 0x3f, 0x15, 0x68, 0xd9, 0xc9, 0x9a, 0x9b, 0xe4,
4897
-	0x77, 0xa1, 0xa6, 0x53, 0xaf, 0xab, 0xee, 0xf5, 0x42, 0xa5, 0x19, 0x16, 0x86, 0xca, 0x83, 0xfa,
4898
-	0xa0, 0x60, 0x6a, 0xcc, 0xeb, 0xe1, 0x5f, 0x8a, 0xd2, 0x60, 0x41, 0x45, 0x9c, 0xaa, 0x50, 0x55,
4899
-	0xb1, 0x16, 0xe4, 0xf4, 0x9f, 0x2e, 0x7b, 0xe7, 0x9b, 0xfe, 0x53, 0x35, 0x3b, 0x0d, 0xf5, 0x37,
4900
-	0x4a, 0x43, 0xe3, 0xdc, 0x69, 0x08, 0xfe, 0x70, 0xc0, 0x9d, 0x56, 0xb9, 0x15, 0x5d, 0xe7, 0x8d,
4901
-	0xa3, 0x3b, 0x13, 0x99, 0xca, 0xeb, 0x45, 0xe6, 0x12, 0xd4, 0xb8, 0x60, 0x24, 0x1e, 0xeb, 0xbd,
4902
-	0x14, 0x1b, 0x49, 0xf6, 0x93, 0x31, 0x1f, 0xa9, 0x0c, 0xb5, 0xb0, 0x3c, 0x06, 0x01, 0xb4, 0xd4,
4903
-	0x0a, 0xba, 0x47, 0xb8, 0x5c, 0x7a, 0x64, 0x6e, 0x87, 0xb1, 0x88, 0x95, 0x1f, 0x2d, 0xac, 0xce,
4904
-	0xc1, 0x15, 0x40, 0xf7, 0x12, 0x2e, 0x1e, 0xa9, 0xd5, 0x99, 0x2f, 0xdb, 0x4f, 0xf7, 0xe1, 0xed,
4905
-	0x19, 0xb4, 0xe9, 0x52, 0x5f, 0x9e, 0xda, 0x50, 0x3f, 0x9e, 0xef, 0x1a, 0x6a, 0x43, 0x0f, 0xb5,
4906
-	0xe2, 0xec, 0xa2, 0xba, 0xf5, 0x77, 0x15, 0xea, 0x3b, 0xfa, 0xc7, 0x07, 0x7a, 0x00, 0xee, 0x74,
4907
-	0x01, 0x46, 0xc1, 0x3c, 0xcd, 0xe9, 0x4d, 0xda, 0xff, 0xe8, 0xa5, 0x18, 0x63, 0xdf, 0xd7, 0xb0,
4908
-	0xaa, 0x7e, 0x0a, 0xa0, 0x05, 0x6d, 0xd0, 0xfe, 0x8d, 0xe0, 0xbf, 0x7c, 0xb5, 0xbe, 0xe6, 0x48,
4909
-	0x26, 0x35, 0x43, 0x16, 0x31, 0xd9, 0xcb, 0x8c, 0xbf, 0xb9, 0x64, 0xf8, 0xa0, 0x3d, 0xa8, 0x99,
4910
-	0xe7, 0xbc, 0x08, 0x6a, 0x4f, 0x0a, 0xbf, 0x7d, 0x36, 0x40, 0x93, 0x5d, 0x73, 0xd0, 0xde, 0x74,
4911
-	0x53, 0x5b, 0x64, 0x9a, 0x5d, 0x06, 0xfe, 0x92, 0xff, 0x77, 0x9c, 0x6b, 0x0e, 0xfa, 0x1e, 0x9a,
4912
-	0x56, 0xa2, 0xd1, 0x82, 0x84, 0xce, 0x57, 0x8d, 0xff, 0xc9, 0x12, 0x94, 0x36, 0xb6, 0xdb, 0x7a,
4913
-	0xfa, 0x62, 0xc3, 0xf9, 0xf3, 0xc5, 0x86, 0xf3, 0xd7, 0x8b, 0x0d, 0xa7, 0x5f, 0x53, 0x75, 0xff,
4914
-	0xe9, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x98, 0x98, 0x82, 0x80, 0x0e, 0x00, 0x00,
4831
+func init() { proto.RegisterFile("control.proto", fileDescriptor_control_86d7f5d7b8f10de2) }
4832
+
4833
+var fileDescriptor_control_86d7f5d7b8f10de2 = []byte{
4834
+	// 1359 bytes of a gzipped FileDescriptorProto
4835
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0x4b, 0x6f, 0x1b, 0xb7,
4836
+	0x16, 0xce, 0x48, 0xd6, 0xeb, 0x48, 0x0e, 0x1c, 0x26, 0x37, 0x18, 0xcc, 0xc5, 0xb5, 0x75, 0x27,
4837
+	0x2d, 0x20, 0x04, 0xc9, 0xc8, 0x71, 0x9b, 0x22, 0x35, 0xda, 0x22, 0x91, 0x95, 0x22, 0x0e, 0x62,
4838
+	0x34, 0xa0, 0x93, 0x06, 0xe8, 0xa2, 0xc0, 0x48, 0xa2, 0x95, 0x81, 0x47, 0xc3, 0x29, 0xc9, 0x71,
4839
+	0xa3, 0xfe, 0x80, 0xae, 0xfb, 0x2f, 0xba, 0xea, 0xaa, 0x8b, 0xfe, 0x82, 0x02, 0x59, 0x76, 0x9d,
4840
+	0x85, 0x5b, 0x64, 0xdf, 0xae, 0xba, 0xe9, 0xae, 0xe0, 0x63, 0x64, 0xca, 0x92, 0xfc, 0xca, 0x6a,
4841
+	0x78, 0x38, 0xe7, 0xfb, 0x78, 0x5e, 0x24, 0x0f, 0x61, 0xb9, 0x4f, 0x13, 0xc1, 0x68, 0x1c, 0xa4,
4842
+	0x8c, 0x0a, 0x8a, 0x56, 0x46, 0xb4, 0x37, 0x0e, 0x7a, 0x59, 0x14, 0x0f, 0xf6, 0x23, 0x11, 0x1c,
4843
+	0xdc, 0xf1, 0x6e, 0x0f, 0x23, 0xf1, 0x32, 0xeb, 0x05, 0x7d, 0x3a, 0x6a, 0x0f, 0xe9, 0x90, 0xb6,
4844
+	0x95, 0x62, 0x2f, 0xdb, 0x53, 0x92, 0x12, 0xd4, 0x48, 0x13, 0x78, 0x6b, 0x43, 0x4a, 0x87, 0x31,
4845
+	0x39, 0xd2, 0x12, 0xd1, 0x88, 0x70, 0x11, 0x8e, 0x52, 0xa3, 0x70, 0xcb, 0xe2, 0x93, 0x8b, 0xb5,
4846
+	0xf3, 0xc5, 0xda, 0x9c, 0xc6, 0x07, 0x84, 0xb5, 0xd3, 0x5e, 0x9b, 0xa6, 0xdc, 0x68, 0xb7, 0x17,
4847
+	0x6a, 0x87, 0x69, 0xd4, 0x16, 0xe3, 0x94, 0xf0, 0xf6, 0xb7, 0x94, 0xed, 0x13, 0xa6, 0x01, 0xfe,
4848
+	0xf7, 0x0e, 0x34, 0x9e, 0xb2, 0x2c, 0x21, 0x98, 0x7c, 0x93, 0x11, 0x2e, 0xd0, 0x75, 0x28, 0xef,
4849
+	0x45, 0xb1, 0x20, 0xcc, 0x75, 0x9a, 0xc5, 0x56, 0x0d, 0x1b, 0x09, 0xad, 0x40, 0x31, 0x8c, 0x63,
4850
+	0xb7, 0xd0, 0x74, 0x5a, 0x55, 0x2c, 0x87, 0xa8, 0x05, 0x8d, 0x7d, 0x42, 0xd2, 0x6e, 0xc6, 0x42,
4851
+	0x11, 0xd1, 0xc4, 0x2d, 0x36, 0x9d, 0x56, 0xb1, 0xb3, 0xf4, 0xfa, 0x70, 0xcd, 0xc1, 0x53, 0x7f,
4852
+	0x90, 0x0f, 0x35, 0x29, 0x77, 0xc6, 0x82, 0x70, 0x77, 0xc9, 0x52, 0x3b, 0x9a, 0xf6, 0x6f, 0xc2,
4853
+	0x4a, 0x37, 0xe2, 0xfb, 0xcf, 0x79, 0x38, 0x3c, 0xcd, 0x16, 0xff, 0x31, 0x5c, 0xb1, 0x74, 0x79,
4854
+	0x4a, 0x13, 0x4e, 0xd0, 0x5d, 0x28, 0x33, 0xd2, 0xa7, 0x6c, 0xa0, 0x94, 0xeb, 0x1b, 0xff, 0x0b,
4855
+	0x8e, 0xe7, 0x26, 0x30, 0x00, 0xa9, 0x84, 0x8d, 0xb2, 0xff, 0x4f, 0x01, 0xea, 0xd6, 0x3c, 0xba,
4856
+	0x0c, 0x85, 0xed, 0xae, 0xeb, 0x34, 0x9d, 0x56, 0x0d, 0x17, 0xb6, 0xbb, 0xc8, 0x85, 0xca, 0x4e,
4857
+	0x26, 0xc2, 0x5e, 0x4c, 0x8c, 0xef, 0xb9, 0x88, 0xae, 0x41, 0x69, 0x3b, 0x79, 0xce, 0x89, 0x72,
4858
+	0xbc, 0x8a, 0xb5, 0x80, 0x10, 0x2c, 0xed, 0x46, 0xdf, 0x11, 0xed, 0x26, 0x56, 0x63, 0xe9, 0xc7,
4859
+	0xd3, 0x90, 0x91, 0x44, 0xb8, 0x25, 0xc5, 0x6b, 0x24, 0xd4, 0x81, 0xda, 0x16, 0x23, 0xa1, 0x20,
4860
+	0x83, 0x07, 0xc2, 0x2d, 0x37, 0x9d, 0x56, 0x7d, 0xc3, 0x0b, 0x74, 0x41, 0x04, 0x79, 0x41, 0x04,
4861
+	0xcf, 0xf2, 0x82, 0xe8, 0x54, 0x5f, 0x1f, 0xae, 0x5d, 0xfa, 0xe1, 0x77, 0x19, 0xb7, 0x09, 0x0c,
4862
+	0xdd, 0x07, 0x78, 0x12, 0x72, 0xf1, 0x9c, 0x2b, 0x92, 0xca, 0xa9, 0x24, 0x4b, 0x8a, 0xc0, 0xc2,
4863
+	0xa0, 0x55, 0x00, 0x15, 0x80, 0x2d, 0x9a, 0x25, 0xc2, 0xad, 0x2a, 0xbb, 0xad, 0x19, 0xd4, 0x84,
4864
+	0x7a, 0x97, 0xf0, 0x3e, 0x8b, 0x52, 0x95, 0xe6, 0x9a, 0x72, 0xc1, 0x9e, 0x92, 0x0c, 0x3a, 0x7a,
4865
+	0xcf, 0xc6, 0x29, 0x71, 0x41, 0x29, 0x58, 0x33, 0xd2, 0xff, 0xdd, 0x97, 0x21, 0x23, 0x03, 0xb7,
4866
+	0xae, 0x42, 0x65, 0x24, 0xff, 0xef, 0x25, 0x68, 0xec, 0xca, 0x2a, 0xce, 0x13, 0xbe, 0x02, 0x45,
4867
+	0x4c, 0xf6, 0x4c, 0xf4, 0xe5, 0x10, 0x05, 0x00, 0x5d, 0xb2, 0x17, 0x25, 0x91, 0x5a, 0xbb, 0xa0,
4868
+	0xdc, 0xbb, 0x1c, 0xa4, 0xbd, 0xe0, 0x68, 0x16, 0x5b, 0x1a, 0xc8, 0x83, 0xea, 0xc3, 0x57, 0x29,
4869
+	0x65, 0xb2, 0x68, 0x8a, 0x8a, 0x66, 0x22, 0xa3, 0x17, 0xb0, 0x9c, 0x8f, 0x1f, 0x08, 0xc1, 0x64,
4870
+	0x29, 0xca, 0x42, 0xb9, 0x33, 0x5b, 0x28, 0xb6, 0x51, 0xc1, 0x14, 0xe6, 0x61, 0x22, 0xd8, 0x18,
4871
+	0x4f, 0xf3, 0xc8, 0x1a, 0xd9, 0x25, 0x9c, 0x4b, 0x0b, 0x75, 0x82, 0x73, 0x51, 0x9a, 0xf3, 0x39,
4872
+	0xa3, 0x89, 0x20, 0xc9, 0x40, 0x25, 0xb8, 0x86, 0x27, 0xb2, 0x34, 0x27, 0x1f, 0x6b, 0x73, 0x2a,
4873
+	0x67, 0x32, 0x67, 0x0a, 0x63, 0xcc, 0x99, 0x9a, 0x43, 0x9b, 0x50, 0xda, 0x0a, 0xfb, 0x2f, 0x89,
4874
+	0xca, 0x65, 0x7d, 0x63, 0x75, 0x96, 0x50, 0xfd, 0xfe, 0x42, 0x25, 0x8f, 0xab, 0xad, 0x78, 0x09,
4875
+	0x6b, 0x08, 0xfa, 0x1a, 0x1a, 0x0f, 0x13, 0x11, 0x89, 0x98, 0x8c, 0x48, 0x22, 0xb8, 0x5b, 0x93,
4876
+	0x1b, 0xaf, 0xb3, 0xf9, 0xe6, 0x70, 0xed, 0xa3, 0x85, 0x47, 0x4b, 0x26, 0xa2, 0xb8, 0x4d, 0x2c,
4877
+	0x54, 0x60, 0x51, 0xe0, 0x29, 0x3e, 0xef, 0x3e, 0xa0, 0xd9, 0x78, 0xca, 0xbc, 0xef, 0x93, 0x71,
4878
+	0x9e, 0xf7, 0x7d, 0x32, 0x96, 0x9b, 0xeb, 0x20, 0x8c, 0x33, 0xbd, 0xe9, 0x6a, 0x58, 0x0b, 0x9b,
4879
+	0x85, 0x7b, 0x8e, 0x64, 0x98, 0x0d, 0xc1, 0x79, 0x18, 0xfc, 0x9f, 0x8a, 0xd0, 0xb0, 0x23, 0x80,
4880
+	0xd6, 0xe1, 0xaa, 0x36, 0x0a, 0x93, 0xbd, 0x2e, 0x49, 0x19, 0xe9, 0xcb, 0xcd, 0x65, 0xc8, 0xe6,
4881
+	0xfd, 0x42, 0x1b, 0x70, 0x6d, 0x7b, 0x64, 0xa6, 0xb9, 0x05, 0x29, 0xa8, 0x73, 0x6a, 0xee, 0x3f,
4882
+	0x44, 0xe1, 0x3f, 0x9a, 0x4a, 0x99, 0x6d, 0x81, 0x8a, 0x2a, 0xef, 0x1f, 0x9f, 0x9c, 0xa6, 0x60,
4883
+	0x2e, 0x56, 0xe7, 0x7f, 0x3e, 0x2f, 0xfa, 0x14, 0x2a, 0xfa, 0x47, 0x5e, 0xe9, 0x37, 0x4e, 0x5e,
4884
+	0x42, 0x93, 0xe5, 0x18, 0x09, 0xd7, 0x7e, 0x70, 0xb7, 0x74, 0x0e, 0xb8, 0xc1, 0x78, 0x8f, 0xc0,
4885
+	0x5b, 0x6c, 0xf2, 0xb9, 0xf2, 0xf5, 0xa3, 0x03, 0x57, 0x66, 0x16, 0x92, 0x07, 0xad, 0x3a, 0x6e,
4886
+	0x34, 0x85, 0x1a, 0xa3, 0x2e, 0x94, 0xf4, 0x56, 0x2a, 0x28, 0x83, 0x83, 0x33, 0x18, 0x1c, 0x58,
4887
+	0xfb, 0x48, 0x83, 0xbd, 0x7b, 0x00, 0x17, 0xac, 0xac, 0x5f, 0x1c, 0x58, 0x36, 0x9b, 0xd5, 0xdc,
4888
+	0x4a, 0x21, 0xac, 0xe4, 0xf5, 0x9e, 0xcf, 0x99, 0xfb, 0xe9, 0xee, 0xc2, 0x7d, 0xae, 0xd5, 0x82,
4889
+	0xe3, 0x38, 0x6d, 0xe3, 0x0c, 0x9d, 0xb7, 0x95, 0xd7, 0xd5, 0x31, 0xd5, 0x73, 0x59, 0xfe, 0x7f,
4890
+	0x58, 0xde, 0x15, 0xa1, 0xc8, 0xf8, 0xc2, 0xa3, 0xd8, 0xff, 0xd9, 0x81, 0xcb, 0xb9, 0x8e, 0xf1,
4891
+	0xee, 0x43, 0xa8, 0x1e, 0x10, 0x26, 0xc8, 0x2b, 0xc2, 0x8d, 0x57, 0xee, 0xac, 0x57, 0x5f, 0x2a,
4892
+	0x0d, 0x3c, 0xd1, 0x44, 0x9b, 0x50, 0xe5, 0x8a, 0x87, 0xe4, 0x89, 0x5a, 0x5d, 0x84, 0x32, 0xeb,
4893
+	0x4d, 0xf4, 0x51, 0x1b, 0x96, 0x62, 0x3a, 0xe4, 0x66, 0xcf, 0xfc, 0x77, 0x11, 0xee, 0x09, 0x1d,
4894
+	0x62, 0xa5, 0xe8, 0x1f, 0x16, 0xa0, 0xac, 0xe7, 0xd0, 0x63, 0x28, 0x0f, 0xa2, 0x21, 0xe1, 0x42,
4895
+	0x7b, 0xd5, 0xd9, 0x90, 0x07, 0xdf, 0x9b, 0xc3, 0xb5, 0x9b, 0xd6, 0xc9, 0x46, 0x53, 0x92, 0xc8,
4896
+	0x16, 0x2f, 0x8c, 0x12, 0xc2, 0x78, 0x7b, 0x48, 0x6f, 0x6b, 0x48, 0xd0, 0x55, 0x1f, 0x6c, 0x18,
4897
+	0x24, 0x57, 0x94, 0xa4, 0x99, 0xd0, 0x1e, 0x5c, 0x90, 0x4b, 0x33, 0xc8, 0x4a, 0x4e, 0xc2, 0x11,
4898
+	0x31, 0xf7, 0x95, 0x1a, 0xcb, 0x2b, 0xb3, 0x2f, 0x4b, 0x75, 0xa0, 0x1a, 0x89, 0x2a, 0x36, 0x12,
4899
+	0xda, 0x84, 0x0a, 0x17, 0x21, 0x93, 0xc7, 0x46, 0xe9, 0x8c, 0x77, 0x7d, 0x0e, 0x40, 0x9f, 0x41,
4900
+	0xad, 0x4f, 0x47, 0x69, 0x4c, 0x24, 0xba, 0x7c, 0x46, 0xf4, 0x11, 0x44, 0x56, 0x0f, 0x61, 0x8c,
4901
+	0x32, 0xd5, 0x65, 0xd4, 0xb0, 0x16, 0xfc, 0xbf, 0x0a, 0xd0, 0xb0, 0x93, 0x35, 0xd3, 0x41, 0x3d,
4902
+	0x86, 0xb2, 0x4e, 0xbd, 0xae, 0xba, 0x8b, 0x85, 0x4a, 0x33, 0xcc, 0x0d, 0x95, 0x0b, 0x95, 0x7e,
4903
+	0xc6, 0x54, 0x7b, 0xa5, 0x9b, 0xae, 0x5c, 0x94, 0x06, 0x0b, 0x2a, 0xc2, 0x58, 0x85, 0xaa, 0x88,
4904
+	0xb5, 0x20, 0xbb, 0xae, 0x49, 0x93, 0x7d, 0xbe, 0xae, 0x6b, 0x02, 0xb3, 0xd3, 0x50, 0x79, 0xa7,
4905
+	0x34, 0x54, 0xcf, 0x9d, 0x06, 0xff, 0x57, 0x07, 0x6a, 0x93, 0x2a, 0xb7, 0xa2, 0xeb, 0xbc, 0x73,
4906
+	0x74, 0xa7, 0x22, 0x53, 0xb8, 0x58, 0x64, 0xae, 0x43, 0x99, 0x0b, 0x46, 0xc2, 0x91, 0x7e, 0x0f,
4907
+	0x60, 0x23, 0xc9, 0xf3, 0x64, 0xc4, 0x87, 0x2a, 0x43, 0x0d, 0x2c, 0x87, 0xbe, 0x0f, 0x0d, 0xd5,
4908
+	0xfa, 0xef, 0x10, 0x2e, 0x9b, 0x4d, 0x99, 0xdb, 0x41, 0x28, 0x42, 0xe5, 0x47, 0x03, 0xab, 0xb1,
4909
+	0x7f, 0x0b, 0xd0, 0x93, 0x88, 0x8b, 0x17, 0xea, 0xc9, 0xc2, 0x4f, 0x7b, 0x17, 0xec, 0xc2, 0xd5,
4910
+	0x29, 0x6d, 0x73, 0x4a, 0x7d, 0x72, 0xec, 0x65, 0xf0, 0xde, 0xec, 0xa9, 0xa1, 0x5e, 0x46, 0x81,
4911
+	0x06, 0x4e, 0x3f, 0x10, 0x36, 0xfe, 0x2c, 0x42, 0x65, 0x4b, 0x3f, 0xfa, 0xd0, 0x33, 0xa8, 0x4d,
4912
+	0x1e, 0x1e, 0xc8, 0x9f, 0xa5, 0x39, 0xfe, 0x82, 0xf1, 0x6e, 0x9c, 0xa8, 0x63, 0xec, 0x7b, 0x04,
4913
+	0x25, 0xf5, 0x04, 0x43, 0x73, 0x8e, 0x41, 0xfb, 0x6d, 0xe6, 0x9d, 0xfc, 0xa4, 0x59, 0x77, 0x24,
4914
+	0x93, 0xba, 0x43, 0xe6, 0x31, 0xd9, 0x4d, 0xa4, 0xb7, 0x76, 0xca, 0xe5, 0x83, 0x76, 0xa0, 0x6c,
4915
+	0xb6, 0xf3, 0x3c, 0x55, 0xfb, 0xa6, 0xf0, 0x9a, 0x8b, 0x15, 0x34, 0xd9, 0xba, 0x83, 0x76, 0x26,
4916
+	0x1d, 0xf2, 0x3c, 0xd3, 0xec, 0x32, 0xf0, 0x4e, 0xf9, 0xdf, 0x72, 0xd6, 0x1d, 0xf4, 0x15, 0xd4,
4917
+	0xad, 0x44, 0xa3, 0x39, 0x09, 0x9d, 0xad, 0x1a, 0xef, 0xfd, 0x53, 0xb4, 0xb4, 0xb1, 0x9d, 0xc6,
4918
+	0xeb, 0xb7, 0xab, 0xce, 0x6f, 0x6f, 0x57, 0x9d, 0x3f, 0xde, 0xae, 0x3a, 0xbd, 0xb2, 0xaa, 0xfb,
4919
+	0x0f, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xd3, 0x7a, 0xbe, 0x54, 0xf8, 0x0f, 0x00, 0x00,
4915 4920
 }
... ...
@@ -66,9 +66,31 @@ message SolveRequest {
66 66
 }
67 67
 
68 68
 message CacheOptions {
69
-	string ExportRef = 1;
70
-	repeated string ImportRefs = 2;
71
-	map<string, string> ExportAttrs = 3;
69
+	// ExportRefDeprecated is deprecated in favor or the new Exports since BuildKit v0.4.0.
70
+	// When ExportRefDeprecated is set, the solver appends
71
+	// {.Type = "registry", .Attrs = ExportAttrs.add("ref", ExportRef)}
72
+	// to Exports for compatibility. (planned to be removed)
73
+	string ExportRefDeprecated = 1;
74
+	// ImportRefsDeprecated is deprecated in favor or the new Imports since BuildKit v0.4.0.
75
+	// When ImportRefsDeprecated is set, the solver appends
76
+	// {.Type = "registry", .Attrs = {"ref": importRef}}
77
+	// for each of the ImportRefs entry to Imports for compatibility. (planned to be removed)
78
+	repeated string ImportRefsDeprecated = 2;
79
+	// ExportAttrsDeprecated is deprecated since BuildKit v0.4.0.
80
+	// See the description of ExportRefDeprecated.
81
+	map<string, string> ExportAttrsDeprecated = 3;
82
+	// Exports was introduced in BuildKit v0.4.0.
83
+	repeated CacheOptionsEntry Exports = 4;
84
+	// Imports was introduced in BuildKit v0.4.0.
85
+	repeated CacheOptionsEntry Imports = 5;
86
+}
87
+
88
+message CacheOptionsEntry {
89
+	// Type is like "registry" or "local"
90
+	string Type = 1;
91
+	// Attrs are like mode=(min,max), ref=example.com:5000/foo/bar .
92
+	// See cache importer/exporter implementations' documentation.
93
+	map<string, string> Attrs = 2;
72 94
 }
73 95
 
74 96
 message SolveResponse {
... ...
@@ -124,4 +146,4 @@ message ListWorkersRequest {
124 124
 
125 125
 message ListWorkersResponse {
126 126
 	repeated moby.buildkit.v1.types.WorkerRecord record = 1;
127
-}
128 127
\ No newline at end of file
128
+}
... ...
@@ -1,16 +1,6 @@
1 1
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
2 2
 // source: worker.proto
3 3
 
4
-/*
5
-	Package moby_buildkit_v1_types is a generated protocol buffer package.
6
-
7
-	It is generated from these files:
8
-		worker.proto
9
-
10
-	It has these top-level messages:
11
-		WorkerRecord
12
-		GCPolicy
13
-*/
14 4
 package moby_buildkit_v1_types
15 5
 
16 6
 import proto "github.com/gogo/protobuf/proto"
... ...
@@ -33,16 +23,47 @@ var _ = math.Inf
33 33
 const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
34 34
 
35 35
 type WorkerRecord struct {
36
-	ID        string            `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
37
-	Labels    map[string]string `protobuf:"bytes,2,rep,name=Labels" json:"Labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
38
-	Platforms []pb.Platform     `protobuf:"bytes,3,rep,name=platforms" json:"platforms"`
39
-	GCPolicy  []*GCPolicy       `protobuf:"bytes,4,rep,name=GCPolicy" json:"GCPolicy,omitempty"`
36
+	ID                   string            `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
37
+	Labels               map[string]string `protobuf:"bytes,2,rep,name=Labels,proto3" json:"Labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
38
+	Platforms            []pb.Platform     `protobuf:"bytes,3,rep,name=platforms,proto3" json:"platforms"`
39
+	GCPolicy             []*GCPolicy       `protobuf:"bytes,4,rep,name=GCPolicy,proto3" json:"GCPolicy,omitempty"`
40
+	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
41
+	XXX_unrecognized     []byte            `json:"-"`
42
+	XXX_sizecache        int32             `json:"-"`
40 43
 }
41 44
 
42
-func (m *WorkerRecord) Reset()                    { *m = WorkerRecord{} }
43
-func (m *WorkerRecord) String() string            { return proto.CompactTextString(m) }
44
-func (*WorkerRecord) ProtoMessage()               {}
45
-func (*WorkerRecord) Descriptor() ([]byte, []int) { return fileDescriptorWorker, []int{0} }
45
+func (m *WorkerRecord) Reset()         { *m = WorkerRecord{} }
46
+func (m *WorkerRecord) String() string { return proto.CompactTextString(m) }
47
+func (*WorkerRecord) ProtoMessage()    {}
48
+func (*WorkerRecord) Descriptor() ([]byte, []int) {
49
+	return fileDescriptor_worker_1d0a62be5114ecbf, []int{0}
50
+}
51
+func (m *WorkerRecord) XXX_Unmarshal(b []byte) error {
52
+	return m.Unmarshal(b)
53
+}
54
+func (m *WorkerRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
55
+	if deterministic {
56
+		return xxx_messageInfo_WorkerRecord.Marshal(b, m, deterministic)
57
+	} else {
58
+		b = b[:cap(b)]
59
+		n, err := m.MarshalTo(b)
60
+		if err != nil {
61
+			return nil, err
62
+		}
63
+		return b[:n], nil
64
+	}
65
+}
66
+func (dst *WorkerRecord) XXX_Merge(src proto.Message) {
67
+	xxx_messageInfo_WorkerRecord.Merge(dst, src)
68
+}
69
+func (m *WorkerRecord) XXX_Size() int {
70
+	return m.Size()
71
+}
72
+func (m *WorkerRecord) XXX_DiscardUnknown() {
73
+	xxx_messageInfo_WorkerRecord.DiscardUnknown(m)
74
+}
75
+
76
+var xxx_messageInfo_WorkerRecord proto.InternalMessageInfo
46 77
 
47 78
 func (m *WorkerRecord) GetID() string {
48 79
 	if m != nil {
... ...
@@ -73,16 +94,47 @@ func (m *WorkerRecord) GetGCPolicy() []*GCPolicy {
73 73
 }
74 74
 
75 75
 type GCPolicy struct {
76
-	All          bool     `protobuf:"varint,1,opt,name=all,proto3" json:"all,omitempty"`
77
-	KeepDuration int64    `protobuf:"varint,2,opt,name=keepDuration,proto3" json:"keepDuration,omitempty"`
78
-	KeepBytes    int64    `protobuf:"varint,3,opt,name=keepBytes,proto3" json:"keepBytes,omitempty"`
79
-	Filters      []string `protobuf:"bytes,4,rep,name=filters" json:"filters,omitempty"`
76
+	All                  bool     `protobuf:"varint,1,opt,name=all,proto3" json:"all,omitempty"`
77
+	KeepDuration         int64    `protobuf:"varint,2,opt,name=keepDuration,proto3" json:"keepDuration,omitempty"`
78
+	KeepBytes            int64    `protobuf:"varint,3,opt,name=keepBytes,proto3" json:"keepBytes,omitempty"`
79
+	Filters              []string `protobuf:"bytes,4,rep,name=filters,proto3" json:"filters,omitempty"`
80
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
81
+	XXX_unrecognized     []byte   `json:"-"`
82
+	XXX_sizecache        int32    `json:"-"`
83
+}
84
+
85
+func (m *GCPolicy) Reset()         { *m = GCPolicy{} }
86
+func (m *GCPolicy) String() string { return proto.CompactTextString(m) }
87
+func (*GCPolicy) ProtoMessage()    {}
88
+func (*GCPolicy) Descriptor() ([]byte, []int) {
89
+	return fileDescriptor_worker_1d0a62be5114ecbf, []int{1}
90
+}
91
+func (m *GCPolicy) XXX_Unmarshal(b []byte) error {
92
+	return m.Unmarshal(b)
93
+}
94
+func (m *GCPolicy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
95
+	if deterministic {
96
+		return xxx_messageInfo_GCPolicy.Marshal(b, m, deterministic)
97
+	} else {
98
+		b = b[:cap(b)]
99
+		n, err := m.MarshalTo(b)
100
+		if err != nil {
101
+			return nil, err
102
+		}
103
+		return b[:n], nil
104
+	}
105
+}
106
+func (dst *GCPolicy) XXX_Merge(src proto.Message) {
107
+	xxx_messageInfo_GCPolicy.Merge(dst, src)
108
+}
109
+func (m *GCPolicy) XXX_Size() int {
110
+	return m.Size()
111
+}
112
+func (m *GCPolicy) XXX_DiscardUnknown() {
113
+	xxx_messageInfo_GCPolicy.DiscardUnknown(m)
80 114
 }
81 115
 
82
-func (m *GCPolicy) Reset()                    { *m = GCPolicy{} }
83
-func (m *GCPolicy) String() string            { return proto.CompactTextString(m) }
84
-func (*GCPolicy) ProtoMessage()               {}
85
-func (*GCPolicy) Descriptor() ([]byte, []int) { return fileDescriptorWorker, []int{1} }
116
+var xxx_messageInfo_GCPolicy proto.InternalMessageInfo
86 117
 
87 118
 func (m *GCPolicy) GetAll() bool {
88 119
 	if m != nil {
... ...
@@ -114,6 +166,7 @@ func (m *GCPolicy) GetFilters() []string {
114 114
 
115 115
 func init() {
116 116
 	proto.RegisterType((*WorkerRecord)(nil), "moby.buildkit.v1.types.WorkerRecord")
117
+	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.types.WorkerRecord.LabelsEntry")
117 118
 	proto.RegisterType((*GCPolicy)(nil), "moby.buildkit.v1.types.GCPolicy")
118 119
 }
119 120
 func (m *WorkerRecord) Marshal() (dAtA []byte, err error) {
... ...
@@ -178,6 +231,9 @@ func (m *WorkerRecord) MarshalTo(dAtA []byte) (int, error) {
178 178
 			i += n
179 179
 		}
180 180
 	}
181
+	if m.XXX_unrecognized != nil {
182
+		i += copy(dAtA[i:], m.XXX_unrecognized)
183
+	}
181 184
 	return i, nil
182 185
 }
183 186
 
... ...
@@ -231,6 +287,9 @@ func (m *GCPolicy) MarshalTo(dAtA []byte) (int, error) {
231 231
 			i += copy(dAtA[i:], s)
232 232
 		}
233 233
 	}
234
+	if m.XXX_unrecognized != nil {
235
+		i += copy(dAtA[i:], m.XXX_unrecognized)
236
+	}
234 237
 	return i, nil
235 238
 }
236 239
 
... ...
@@ -244,6 +303,9 @@ func encodeVarintWorker(dAtA []byte, offset int, v uint64) int {
244 244
 	return offset + 1
245 245
 }
246 246
 func (m *WorkerRecord) Size() (n int) {
247
+	if m == nil {
248
+		return 0
249
+	}
247 250
 	var l int
248 251
 	_ = l
249 252
 	l = len(m.ID)
... ...
@@ -270,10 +332,16 @@ func (m *WorkerRecord) Size() (n int) {
270 270
 			n += 1 + l + sovWorker(uint64(l))
271 271
 		}
272 272
 	}
273
+	if m.XXX_unrecognized != nil {
274
+		n += len(m.XXX_unrecognized)
275
+	}
273 276
 	return n
274 277
 }
275 278
 
276 279
 func (m *GCPolicy) Size() (n int) {
280
+	if m == nil {
281
+		return 0
282
+	}
277 283
 	var l int
278 284
 	_ = l
279 285
 	if m.All {
... ...
@@ -291,6 +359,9 @@ func (m *GCPolicy) Size() (n int) {
291 291
 			n += 1 + l + sovWorker(uint64(l))
292 292
 		}
293 293
 	}
294
+	if m.XXX_unrecognized != nil {
295
+		n += len(m.XXX_unrecognized)
296
+	}
294 297
 	return n
295 298
 }
296 299
 
... ...
@@ -557,6 +628,7 @@ func (m *WorkerRecord) Unmarshal(dAtA []byte) error {
557 557
 			if (iNdEx + skippy) > l {
558 558
 				return io.ErrUnexpectedEOF
559 559
 			}
560
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
560 561
 			iNdEx += skippy
561 562
 		}
562 563
 	}
... ...
@@ -694,6 +766,7 @@ func (m *GCPolicy) Unmarshal(dAtA []byte) error {
694 694
 			if (iNdEx + skippy) > l {
695 695
 				return io.ErrUnexpectedEOF
696 696
 			}
697
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
697 698
 			iNdEx += skippy
698 699
 		}
699 700
 	}
... ...
@@ -808,9 +881,9 @@ var (
808 808
 	ErrIntOverflowWorker   = fmt.Errorf("proto: integer overflow")
809 809
 )
810 810
 
811
-func init() { proto.RegisterFile("worker.proto", fileDescriptorWorker) }
811
+func init() { proto.RegisterFile("worker.proto", fileDescriptor_worker_1d0a62be5114ecbf) }
812 812
 
813
-var fileDescriptorWorker = []byte{
813
+var fileDescriptor_worker_1d0a62be5114ecbf = []byte{
814 814
 	// 355 bytes of a gzipped FileDescriptorProto
815 815
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0xc1, 0x4e, 0xea, 0x40,
816 816
 	0x14, 0x86, 0x6f, 0x5b, 0x2e, 0x97, 0x0e, 0xcd, 0x8d, 0x99, 0x18, 0xd3, 0x10, 0x83, 0x84, 0x15,
... ...
@@ -43,8 +43,8 @@ func getDefaultManager() *cacheManager {
43 43
 // header, "/dir" is for contents. For the root node "" (empty string) is the
44 44
 // key for root, "/" for the root header
45 45
 
46
-func Checksum(ctx context.Context, ref cache.ImmutableRef, path string) (digest.Digest, error) {
47
-	return getDefaultManager().Checksum(ctx, ref, path)
46
+func Checksum(ctx context.Context, ref cache.ImmutableRef, path string, followLinks bool) (digest.Digest, error) {
47
+	return getDefaultManager().Checksum(ctx, ref, path, followLinks)
48 48
 }
49 49
 
50 50
 func GetCacheContext(ctx context.Context, md *metadata.StorageItem) (CacheContext, error) {
... ...
@@ -56,7 +56,8 @@ func SetCacheContext(ctx context.Context, md *metadata.StorageItem, cc CacheCont
56 56
 }
57 57
 
58 58
 type CacheContext interface {
59
-	Checksum(ctx context.Context, ref cache.Mountable, p string) (digest.Digest, error)
59
+	Checksum(ctx context.Context, ref cache.Mountable, p string, followLinks bool) (digest.Digest, error)
60
+	ChecksumWildcard(ctx context.Context, ref cache.Mountable, p string, followLinks bool) (digest.Digest, error)
60 61
 	HandleChange(kind fsutil.ChangeKind, p string, fi os.FileInfo, err error) error
61 62
 }
62 63
 
... ...
@@ -64,18 +65,23 @@ type Hashed interface {
64 64
 	Digest() digest.Digest
65 65
 }
66 66
 
67
+type Wildcard struct {
68
+	Path   string
69
+	Record *CacheRecord
70
+}
71
+
67 72
 type cacheManager struct {
68 73
 	locker *locker.Locker
69 74
 	lru    *simplelru.LRU
70 75
 	lruMu  sync.Mutex
71 76
 }
72 77
 
73
-func (cm *cacheManager) Checksum(ctx context.Context, ref cache.ImmutableRef, p string) (digest.Digest, error) {
78
+func (cm *cacheManager) Checksum(ctx context.Context, ref cache.ImmutableRef, p string, followLinks bool) (digest.Digest, error) {
74 79
 	cc, err := cm.GetCacheContext(ctx, ensureOriginMetadata(ref.Metadata()))
75 80
 	if err != nil {
76 81
 		return "", nil
77 82
 	}
78
-	return cc.Checksum(ctx, ref, p)
83
+	return cc.Checksum(ctx, ref, p, followLinks)
79 84
 }
80 85
 
81 86
 func (cm *cacheManager) GetCacheContext(ctx context.Context, md *metadata.StorageItem) (CacheContext, error) {
... ...
@@ -317,10 +323,49 @@ func (cc *cacheContext) HandleChange(kind fsutil.ChangeKind, p string, fi os.Fil
317 317
 	return nil
318 318
 }
319 319
 
320
-func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable, p string) (digest.Digest, error) {
320
+func (cc *cacheContext) ChecksumWildcard(ctx context.Context, mountable cache.Mountable, p string, followLinks bool) (digest.Digest, error) {
321 321
 	m := &mount{mountable: mountable}
322 322
 	defer m.clean()
323 323
 
324
+	wildcards, err := cc.wildcards(ctx, m, p)
325
+	if err != nil {
326
+		return "", nil
327
+	}
328
+
329
+	if followLinks {
330
+		for i, w := range wildcards {
331
+			if w.Record.Type == CacheRecordTypeSymlink {
332
+				dgst, err := cc.checksumFollow(ctx, m, w.Path, followLinks)
333
+				if err != nil {
334
+					return "", err
335
+				}
336
+				wildcards[i].Record = &CacheRecord{Digest: dgst}
337
+			}
338
+		}
339
+	}
340
+
341
+	if len(wildcards) > 1 {
342
+		digester := digest.Canonical.Digester()
343
+		for i, w := range wildcards {
344
+			if i != 0 {
345
+				digester.Hash().Write([]byte{0})
346
+			}
347
+			digester.Hash().Write([]byte(w.Record.Digest))
348
+		}
349
+		return digester.Digest(), nil
350
+	} else {
351
+		return wildcards[0].Record.Digest, nil
352
+	}
353
+}
354
+
355
+func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable, p string, followLinks bool) (digest.Digest, error) {
356
+	m := &mount{mountable: mountable}
357
+	defer m.clean()
358
+
359
+	return cc.checksumFollow(ctx, m, p, followLinks)
360
+}
361
+
362
+func (cc *cacheContext) checksumFollow(ctx context.Context, m *mount, p string, follow bool) (digest.Digest, error) {
324 363
 	const maxSymlinkLimit = 255
325 364
 	i := 0
326 365
 	for {
... ...
@@ -331,7 +376,7 @@ func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable,
331 331
 		if err != nil {
332 332
 			return "", err
333 333
 		}
334
-		if cr.Type == CacheRecordTypeSymlink {
334
+		if cr.Type == CacheRecordTypeSymlink && follow {
335 335
 			link := cr.Linkname
336 336
 			if !path.IsAbs(cr.Linkname) {
337 337
 				link = path.Join(path.Dir(p), link)
... ...
@@ -344,6 +389,82 @@ func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable,
344 344
 	}
345 345
 }
346 346
 
347
+func (cc *cacheContext) wildcards(ctx context.Context, m *mount, p string) ([]*Wildcard, error) {
348
+	cc.mu.Lock()
349
+	defer cc.mu.Unlock()
350
+
351
+	if cc.txn != nil {
352
+		cc.commitActiveTransaction()
353
+	}
354
+
355
+	root := cc.tree.Root()
356
+	scan, err := cc.needsScan(root, "")
357
+	if err != nil {
358
+		return nil, err
359
+	}
360
+	if scan {
361
+		if err := cc.scanPath(ctx, m, ""); err != nil {
362
+			return nil, err
363
+		}
364
+	}
365
+
366
+	defer func() {
367
+		if cc.dirty {
368
+			go cc.save()
369
+			cc.dirty = false
370
+		}
371
+	}()
372
+
373
+	p = path.Join("/", filepath.ToSlash(p))
374
+	if p == "/" {
375
+		p = ""
376
+	}
377
+
378
+	wildcards := make([]*Wildcard, 0, 2)
379
+
380
+	txn := cc.tree.Txn()
381
+	root = txn.Root()
382
+	var updated bool
383
+
384
+	iter := root.Seek([]byte{})
385
+	for {
386
+		k, _, ok := iter.Next()
387
+		if !ok {
388
+			break
389
+		}
390
+		if len(k) > 0 && k[len(k)-1] == byte(0) {
391
+			continue
392
+		}
393
+		fn := convertKeyToPath(k)
394
+		b, err := path.Match(p, string(fn))
395
+		if err != nil {
396
+			return nil, err
397
+		}
398
+		if !b {
399
+			continue
400
+		}
401
+
402
+		cr, upt, err := cc.checksum(ctx, root, txn, m, k, false)
403
+		if err != nil {
404
+			return nil, err
405
+		}
406
+		if upt {
407
+			updated = true
408
+		}
409
+
410
+		wildcards = append(wildcards, &Wildcard{Path: string(fn), Record: cr})
411
+
412
+		if cr.Type == CacheRecordTypeDir {
413
+			iter = root.Seek(append(k, 0, 0xff))
414
+		}
415
+	}
416
+
417
+	cc.tree = txn.Commit()
418
+	cc.dirty = updated
419
+
420
+	return wildcards, nil
421
+}
422
+
347 423
 func (cc *cacheContext) checksumNoFollow(ctx context.Context, m *mount, p string) (*CacheRecord, error) {
348 424
 	p = path.Join("/", filepath.ToSlash(p))
349 425
 	if p == "/" {
... ...
@@ -412,7 +533,7 @@ func (cc *cacheContext) lazyChecksum(ctx context.Context, m *mount, p string) (*
412 412
 	k := convertPathToKey([]byte(p))
413 413
 	txn := cc.tree.Txn()
414 414
 	root = txn.Root()
415
-	cr, updated, err := cc.checksum(ctx, root, txn, m, k)
415
+	cr, updated, err := cc.checksum(ctx, root, txn, m, k, true)
416 416
 	if err != nil {
417 417
 		return nil, err
418 418
 	}
... ...
@@ -421,8 +542,8 @@ func (cc *cacheContext) lazyChecksum(ctx context.Context, m *mount, p string) (*
421 421
 	return cr, err
422 422
 }
423 423
 
424
-func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *iradix.Txn, m *mount, k []byte) (*CacheRecord, bool, error) {
425
-	k, cr, err := getFollowLinks(root, k)
424
+func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *iradix.Txn, m *mount, k []byte, follow bool) (*CacheRecord, bool, error) {
425
+	k, cr, err := getFollowLinks(root, k, follow)
426 426
 	if err != nil {
427 427
 		return nil, false, err
428 428
 	}
... ...
@@ -447,7 +568,7 @@ func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *ir
447 447
 			}
448 448
 			h.Write(bytes.TrimPrefix(subk, k))
449 449
 
450
-			subcr, _, err := cc.checksum(ctx, root, txn, m, subk)
450
+			subcr, _, err := cc.checksum(ctx, root, txn, m, subk, true)
451 451
 			if err != nil {
452 452
 				return nil, false, err
453 453
 			}
... ...
@@ -599,42 +720,49 @@ func (cc *cacheContext) scanPath(ctx context.Context, m *mount, p string) (retEr
599 599
 	return nil
600 600
 }
601 601
 
602
-func getFollowLinks(root *iradix.Node, k []byte) ([]byte, *CacheRecord, error) {
602
+func getFollowLinks(root *iradix.Node, k []byte, follow bool) ([]byte, *CacheRecord, error) {
603 603
 	var linksWalked int
604
-	return getFollowLinksWalk(root, k, &linksWalked)
604
+	return getFollowLinksWalk(root, k, follow, &linksWalked)
605 605
 }
606 606
 
607
-func getFollowLinksWalk(root *iradix.Node, k []byte, linksWalked *int) ([]byte, *CacheRecord, error) {
607
+func getFollowLinksWalk(root *iradix.Node, k []byte, follow bool, linksWalked *int) ([]byte, *CacheRecord, error) {
608 608
 	v, ok := root.Get(k)
609 609
 	if ok {
610 610
 		return k, v.(*CacheRecord), nil
611 611
 	}
612
-	if len(k) == 0 {
612
+	if !follow || len(k) == 0 {
613 613
 		return nil, nil, nil
614 614
 	}
615 615
 
616 616
 	dir, file := splitKey(k)
617 617
 
618
-	_, parent, err := getFollowLinksWalk(root, dir, linksWalked)
618
+	k, parent, err := getFollowLinksWalk(root, dir, follow, linksWalked)
619 619
 	if err != nil {
620 620
 		return nil, nil, err
621 621
 	}
622
-	if parent != nil && parent.Type == CacheRecordTypeSymlink {
623
-		*linksWalked++
624
-		if *linksWalked > 255 {
625
-			return nil, nil, errors.Errorf("too many links")
626
-		}
627
-		dirPath := path.Clean(string(convertKeyToPath(dir)))
628
-		if dirPath == "." || dirPath == "/" {
629
-			dirPath = ""
622
+	if parent != nil {
623
+		if parent.Type == CacheRecordTypeSymlink {
624
+			*linksWalked++
625
+			if *linksWalked > 255 {
626
+				return nil, nil, errors.Errorf("too many links")
627
+			}
628
+			dirPath := path.Clean(string(convertKeyToPath(dir)))
629
+			if dirPath == "." || dirPath == "/" {
630
+				dirPath = ""
631
+			}
632
+			link := path.Clean(parent.Linkname)
633
+			if !path.IsAbs(link) {
634
+				link = path.Join("/", path.Join(path.Dir(dirPath), link))
635
+			}
636
+			return getFollowLinksWalk(root, append(convertPathToKey([]byte(link)), file...), follow, linksWalked)
630 637
 		}
631
-		link := path.Clean(parent.Linkname)
632
-		if !path.IsAbs(link) {
633
-			link = path.Join("/", path.Join(path.Dir(dirPath), link))
638
+
639
+		k = append(k, file...)
640
+		v, ok = root.Get(k)
641
+		if ok {
642
+			return k, v.(*CacheRecord), nil
634 643
 		}
635
-		return getFollowLinksWalk(root, append(convertPathToKey([]byte(link)), file...), linksWalked)
636 644
 	}
637
-
638 645
 	return nil, nil, nil
639 646
 }
640 647
 
... ...
@@ -1,17 +1,6 @@
1 1
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
2 2
 // source: checksum.proto
3 3
 
4
-/*
5
-	Package contenthash is a generated protocol buffer package.
6
-
7
-	It is generated from these files:
8
-		checksum.proto
9
-
10
-	It has these top-level messages:
11
-		CacheRecord
12
-		CacheRecordWithPath
13
-		CacheRecords
14
-*/
15 4
 package contenthash
16 5
 
17 6
 import proto "github.com/gogo/protobuf/proto"
... ...
@@ -59,7 +48,9 @@ var CacheRecordType_value = map[string]int32{
59 59
 func (x CacheRecordType) String() string {
60 60
 	return proto.EnumName(CacheRecordType_name, int32(x))
61 61
 }
62
-func (CacheRecordType) EnumDescriptor() ([]byte, []int) { return fileDescriptorChecksum, []int{0} }
62
+func (CacheRecordType) EnumDescriptor() ([]byte, []int) {
63
+	return fileDescriptor_checksum_efc6501bf3727db3, []int{0}
64
+}
63 65
 
64 66
 type CacheRecord struct {
65 67
 	Digest   github_com_opencontainers_go_digest.Digest `protobuf:"bytes,1,opt,name=digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"digest"`
... ...
@@ -67,10 +58,38 @@ type CacheRecord struct {
67 67
 	Linkname string                                     `protobuf:"bytes,3,opt,name=linkname,proto3" json:"linkname,omitempty"`
68 68
 }
69 69
 
70
-func (m *CacheRecord) Reset()                    { *m = CacheRecord{} }
71
-func (m *CacheRecord) String() string            { return proto.CompactTextString(m) }
72
-func (*CacheRecord) ProtoMessage()               {}
73
-func (*CacheRecord) Descriptor() ([]byte, []int) { return fileDescriptorChecksum, []int{0} }
70
+func (m *CacheRecord) Reset()         { *m = CacheRecord{} }
71
+func (m *CacheRecord) String() string { return proto.CompactTextString(m) }
72
+func (*CacheRecord) ProtoMessage()    {}
73
+func (*CacheRecord) Descriptor() ([]byte, []int) {
74
+	return fileDescriptor_checksum_efc6501bf3727db3, []int{0}
75
+}
76
+func (m *CacheRecord) XXX_Unmarshal(b []byte) error {
77
+	return m.Unmarshal(b)
78
+}
79
+func (m *CacheRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
80
+	if deterministic {
81
+		return xxx_messageInfo_CacheRecord.Marshal(b, m, deterministic)
82
+	} else {
83
+		b = b[:cap(b)]
84
+		n, err := m.MarshalTo(b)
85
+		if err != nil {
86
+			return nil, err
87
+		}
88
+		return b[:n], nil
89
+	}
90
+}
91
+func (dst *CacheRecord) XXX_Merge(src proto.Message) {
92
+	xxx_messageInfo_CacheRecord.Merge(dst, src)
93
+}
94
+func (m *CacheRecord) XXX_Size() int {
95
+	return m.Size()
96
+}
97
+func (m *CacheRecord) XXX_DiscardUnknown() {
98
+	xxx_messageInfo_CacheRecord.DiscardUnknown(m)
99
+}
100
+
101
+var xxx_messageInfo_CacheRecord proto.InternalMessageInfo
74 102
 
75 103
 func (m *CacheRecord) GetType() CacheRecordType {
76 104
 	if m != nil {
... ...
@@ -88,13 +107,41 @@ func (m *CacheRecord) GetLinkname() string {
88 88
 
89 89
 type CacheRecordWithPath struct {
90 90
 	Path   string       `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
91
-	Record *CacheRecord `protobuf:"bytes,2,opt,name=record" json:"record,omitempty"`
91
+	Record *CacheRecord `protobuf:"bytes,2,opt,name=record,proto3" json:"record,omitempty"`
92
+}
93
+
94
+func (m *CacheRecordWithPath) Reset()         { *m = CacheRecordWithPath{} }
95
+func (m *CacheRecordWithPath) String() string { return proto.CompactTextString(m) }
96
+func (*CacheRecordWithPath) ProtoMessage()    {}
97
+func (*CacheRecordWithPath) Descriptor() ([]byte, []int) {
98
+	return fileDescriptor_checksum_efc6501bf3727db3, []int{1}
99
+}
100
+func (m *CacheRecordWithPath) XXX_Unmarshal(b []byte) error {
101
+	return m.Unmarshal(b)
102
+}
103
+func (m *CacheRecordWithPath) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
104
+	if deterministic {
105
+		return xxx_messageInfo_CacheRecordWithPath.Marshal(b, m, deterministic)
106
+	} else {
107
+		b = b[:cap(b)]
108
+		n, err := m.MarshalTo(b)
109
+		if err != nil {
110
+			return nil, err
111
+		}
112
+		return b[:n], nil
113
+	}
114
+}
115
+func (dst *CacheRecordWithPath) XXX_Merge(src proto.Message) {
116
+	xxx_messageInfo_CacheRecordWithPath.Merge(dst, src)
117
+}
118
+func (m *CacheRecordWithPath) XXX_Size() int {
119
+	return m.Size()
120
+}
121
+func (m *CacheRecordWithPath) XXX_DiscardUnknown() {
122
+	xxx_messageInfo_CacheRecordWithPath.DiscardUnknown(m)
92 123
 }
93 124
 
94
-func (m *CacheRecordWithPath) Reset()                    { *m = CacheRecordWithPath{} }
95
-func (m *CacheRecordWithPath) String() string            { return proto.CompactTextString(m) }
96
-func (*CacheRecordWithPath) ProtoMessage()               {}
97
-func (*CacheRecordWithPath) Descriptor() ([]byte, []int) { return fileDescriptorChecksum, []int{1} }
125
+var xxx_messageInfo_CacheRecordWithPath proto.InternalMessageInfo
98 126
 
99 127
 func (m *CacheRecordWithPath) GetPath() string {
100 128
 	if m != nil {
... ...
@@ -111,13 +158,41 @@ func (m *CacheRecordWithPath) GetRecord() *CacheRecord {
111 111
 }
112 112
 
113 113
 type CacheRecords struct {
114
-	Paths []*CacheRecordWithPath `protobuf:"bytes,1,rep,name=paths" json:"paths,omitempty"`
114
+	Paths []*CacheRecordWithPath `protobuf:"bytes,1,rep,name=paths,proto3" json:"paths,omitempty"`
115
+}
116
+
117
+func (m *CacheRecords) Reset()         { *m = CacheRecords{} }
118
+func (m *CacheRecords) String() string { return proto.CompactTextString(m) }
119
+func (*CacheRecords) ProtoMessage()    {}
120
+func (*CacheRecords) Descriptor() ([]byte, []int) {
121
+	return fileDescriptor_checksum_efc6501bf3727db3, []int{2}
122
+}
123
+func (m *CacheRecords) XXX_Unmarshal(b []byte) error {
124
+	return m.Unmarshal(b)
125
+}
126
+func (m *CacheRecords) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
127
+	if deterministic {
128
+		return xxx_messageInfo_CacheRecords.Marshal(b, m, deterministic)
129
+	} else {
130
+		b = b[:cap(b)]
131
+		n, err := m.MarshalTo(b)
132
+		if err != nil {
133
+			return nil, err
134
+		}
135
+		return b[:n], nil
136
+	}
137
+}
138
+func (dst *CacheRecords) XXX_Merge(src proto.Message) {
139
+	xxx_messageInfo_CacheRecords.Merge(dst, src)
140
+}
141
+func (m *CacheRecords) XXX_Size() int {
142
+	return m.Size()
143
+}
144
+func (m *CacheRecords) XXX_DiscardUnknown() {
145
+	xxx_messageInfo_CacheRecords.DiscardUnknown(m)
115 146
 }
116 147
 
117
-func (m *CacheRecords) Reset()                    { *m = CacheRecords{} }
118
-func (m *CacheRecords) String() string            { return proto.CompactTextString(m) }
119
-func (*CacheRecords) ProtoMessage()               {}
120
-func (*CacheRecords) Descriptor() ([]byte, []int) { return fileDescriptorChecksum, []int{2} }
148
+var xxx_messageInfo_CacheRecords proto.InternalMessageInfo
121 149
 
122 150
 func (m *CacheRecords) GetPaths() []*CacheRecordWithPath {
123 151
 	if m != nil {
... ...
@@ -241,6 +316,9 @@ func encodeVarintChecksum(dAtA []byte, offset int, v uint64) int {
241 241
 	return offset + 1
242 242
 }
243 243
 func (m *CacheRecord) Size() (n int) {
244
+	if m == nil {
245
+		return 0
246
+	}
244 247
 	var l int
245 248
 	_ = l
246 249
 	l = len(m.Digest)
... ...
@@ -258,6 +336,9 @@ func (m *CacheRecord) Size() (n int) {
258 258
 }
259 259
 
260 260
 func (m *CacheRecordWithPath) Size() (n int) {
261
+	if m == nil {
262
+		return 0
263
+	}
261 264
 	var l int
262 265
 	_ = l
263 266
 	l = len(m.Path)
... ...
@@ -272,6 +353,9 @@ func (m *CacheRecordWithPath) Size() (n int) {
272 272
 }
273 273
 
274 274
 func (m *CacheRecords) Size() (n int) {
275
+	if m == nil {
276
+		return 0
277
+	}
275 278
 	var l int
276 279
 	_ = l
277 280
 	if len(m.Paths) > 0 {
... ...
@@ -721,35 +805,35 @@ var (
721 721
 	ErrIntOverflowChecksum   = fmt.Errorf("proto: integer overflow")
722 722
 )
723 723
 
724
-func init() { proto.RegisterFile("checksum.proto", fileDescriptorChecksum) }
725
-
726
-var fileDescriptorChecksum = []byte{
727
-	// 418 bytes of a gzipped FileDescriptorProto
728
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xc1, 0x6a, 0xd4, 0x40,
729
-	0x18, 0xc7, 0x77, 0xba, 0xeb, 0xaa, 0xdf, 0x4a, 0x0d, 0x53, 0x68, 0xc3, 0x50, 0xb2, 0xe3, 0x5e,
730
-	0x5c, 0x8a, 0xcd, 0x96, 0x08, 0xde, 0xad, 0xd9, 0xa5, 0xd1, 0x2a, 0x32, 0x15, 0x44, 0x3c, 0x48,
731
-	0x36, 0x3b, 0x66, 0x42, 0x9b, 0x4c, 0x48, 0x66, 0x0f, 0xfb, 0x06, 0x92, 0x93, 0x2f, 0x90, 0x93,
732
-	0x82, 0xef, 0xe0, 0x5d, 0xe8, 0xd1, 0xb3, 0x87, 0x22, 0xeb, 0x8b, 0x48, 0x26, 0x55, 0x42, 0xca,
733
-	0x9e, 0xe6, 0xfb, 0x66, 0x7e, 0xdf, 0xff, 0xff, 0x9f, 0x61, 0x60, 0x3b, 0x10, 0x3c, 0x38, 0xcf,
734
-	0x97, 0xb1, 0x9d, 0x66, 0x52, 0x49, 0x3c, 0x08, 0x64, 0xa2, 0x78, 0xa2, 0x84, 0x9f, 0x0b, 0x72,
735
-	0x18, 0x46, 0x4a, 0x2c, 0xe7, 0x76, 0x20, 0xe3, 0x49, 0x28, 0x43, 0x39, 0xd1, 0xcc, 0x7c, 0xf9,
736
-	0x51, 0x77, 0xba, 0xd1, 0x55, 0x3d, 0x3b, 0xfa, 0x86, 0x60, 0xf0, 0xcc, 0x0f, 0x04, 0x67, 0x3c,
737
-	0x90, 0xd9, 0x02, 0x3f, 0x87, 0xfe, 0x22, 0x0a, 0x79, 0xae, 0x4c, 0x44, 0xd1, 0xf8, 0xee, 0xb1,
738
-	0x73, 0x79, 0x35, 0xec, 0xfc, 0xba, 0x1a, 0x1e, 0x34, 0x64, 0x65, 0xca, 0x93, 0xca, 0xd2, 0x8f,
739
-	0x12, 0x9e, 0xe5, 0x93, 0x50, 0x1e, 0xd6, 0x23, 0xb6, 0xab, 0x17, 0x76, 0xad, 0x80, 0x8f, 0xa0,
740
-	0xa7, 0x56, 0x29, 0x37, 0xb7, 0x28, 0x1a, 0x6f, 0x3b, 0xfb, 0x76, 0x23, 0xa6, 0xdd, 0xf0, 0x7c,
741
-	0xb3, 0x4a, 0x39, 0xd3, 0x24, 0x26, 0x70, 0xe7, 0x22, 0x4a, 0xce, 0x13, 0x3f, 0xe6, 0x66, 0xb7,
742
-	0xf2, 0x67, 0xff, 0xfb, 0xd1, 0x7b, 0xd8, 0x69, 0x0c, 0xbd, 0x8d, 0x94, 0x78, 0xed, 0x2b, 0x81,
743
-	0x31, 0xf4, 0x52, 0x5f, 0x89, 0x3a, 0x2e, 0xd3, 0x35, 0x3e, 0x82, 0x7e, 0xa6, 0x29, 0x6d, 0x3d,
744
-	0x70, 0xcc, 0x4d, 0xd6, 0xec, 0x9a, 0x1b, 0xcd, 0xe0, 0x5e, 0x63, 0x3b, 0xc7, 0x4f, 0xe0, 0x56,
745
-	0xa5, 0x94, 0x9b, 0x88, 0x76, 0xc7, 0x03, 0x87, 0x6e, 0x12, 0xf8, 0x17, 0x83, 0xd5, 0xf8, 0xc1,
746
-	0x0f, 0x04, 0xf7, 0x5b, 0x57, 0xc3, 0x0f, 0xa0, 0x37, 0xf3, 0x4e, 0xa7, 0x46, 0x87, 0xec, 0x15,
747
-	0x25, 0xdd, 0x69, 0x1d, 0xcf, 0xa2, 0x0b, 0x8e, 0x87, 0xd0, 0x75, 0x3d, 0x66, 0x20, 0xb2, 0x5b,
748
-	0x94, 0x14, 0xb7, 0x08, 0x37, 0xca, 0xf0, 0x23, 0x00, 0xd7, 0x63, 0x1f, 0x4e, 0xa6, 0x4f, 0xdd,
749
-	0x29, 0x33, 0xb6, 0xc8, 0x7e, 0x51, 0x52, 0xf3, 0x26, 0x77, 0xc2, 0xfd, 0x05, 0xcf, 0xf0, 0x43,
750
-	0xb8, 0x7d, 0xf6, 0xee, 0xe5, 0xa9, 0xf7, 0xea, 0x85, 0xd1, 0x25, 0xa4, 0x28, 0xe9, 0x6e, 0x0b,
751
-	0x3d, 0x5b, 0xc5, 0xd5, 0xbb, 0x92, 0xbd, 0x4f, 0x5f, 0xac, 0xce, 0xf7, 0xaf, 0x56, 0x3b, 0xf3,
752
-	0xb1, 0x71, 0xb9, 0xb6, 0xd0, 0xcf, 0xb5, 0x85, 0x7e, 0xaf, 0x2d, 0xf4, 0xf9, 0x8f, 0xd5, 0x99,
753
-	0xf7, 0xf5, 0x7f, 0x79, 0xfc, 0x37, 0x00, 0x00, 0xff, 0xff, 0x55, 0xf2, 0x2e, 0x06, 0x7d, 0x02,
754
-	0x00, 0x00,
724
+func init() { proto.RegisterFile("checksum.proto", fileDescriptor_checksum_efc6501bf3727db3) }
725
+
726
+var fileDescriptor_checksum_efc6501bf3727db3 = []byte{
727
+	// 426 bytes of a gzipped FileDescriptorProto
728
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xc1, 0x6a, 0x13, 0x41,
729
+	0x18, 0xc7, 0x77, 0x9a, 0x18, 0xf5, 0x8b, 0xd4, 0x30, 0x85, 0x76, 0x19, 0xca, 0x64, 0xcc, 0xc5,
730
+	0x50, 0xec, 0xa6, 0x44, 0xf0, 0x6e, 0xdd, 0x84, 0x46, 0xab, 0xc8, 0x54, 0x10, 0xf1, 0x20, 0x9b,
731
+	0xcd, 0xb8, 0xb3, 0xb4, 0xd9, 0x59, 0x76, 0x27, 0x87, 0xbc, 0x81, 0xec, 0xc9, 0x17, 0xd8, 0x93,
732
+	0x82, 0xef, 0xe0, 0x5d, 0xe8, 0xb1, 0x47, 0xf1, 0x50, 0x24, 0x79, 0x11, 0xd9, 0xd9, 0x2a, 0xcb,
733
+	0x4a, 0x4e, 0xf3, 0x7d, 0x33, 0xbf, 0xef, 0xff, 0xff, 0xcf, 0x30, 0xb0, 0xed, 0x4b, 0xe1, 0x9f,
734
+	0xa7, 0x8b, 0xb9, 0x13, 0x27, 0x4a, 0x2b, 0xdc, 0xf6, 0x55, 0xa4, 0x45, 0xa4, 0xa5, 0x97, 0x4a,
735
+	0x72, 0x18, 0x84, 0x5a, 0x2e, 0xa6, 0x8e, 0xaf, 0xe6, 0x83, 0x40, 0x05, 0x6a, 0x60, 0x98, 0xe9,
736
+	0xe2, 0xa3, 0xe9, 0x4c, 0x63, 0xaa, 0x72, 0xb6, 0xf7, 0x0d, 0x41, 0xfb, 0x99, 0xe7, 0x4b, 0xc1,
737
+	0x85, 0xaf, 0x92, 0x19, 0x7e, 0x0e, 0xad, 0x59, 0x18, 0x88, 0x54, 0xdb, 0x88, 0xa1, 0xfe, 0xdd,
738
+	0xe3, 0xe1, 0xe5, 0x75, 0xd7, 0xfa, 0x75, 0xdd, 0x3d, 0xa8, 0xc8, 0xaa, 0x58, 0x44, 0x85, 0xa5,
739
+	0x17, 0x46, 0x22, 0x49, 0x07, 0x81, 0x3a, 0x2c, 0x47, 0x1c, 0xd7, 0x2c, 0xfc, 0x46, 0x01, 0x1f,
740
+	0x41, 0x53, 0x2f, 0x63, 0x61, 0x6f, 0x31, 0xd4, 0xdf, 0x1e, 0xee, 0x3b, 0x95, 0x98, 0x4e, 0xc5,
741
+	0xf3, 0xcd, 0x32, 0x16, 0xdc, 0x90, 0x98, 0xc0, 0x9d, 0x8b, 0x30, 0x3a, 0x8f, 0xbc, 0xb9, 0xb0,
742
+	0x1b, 0x85, 0x3f, 0xff, 0xd7, 0xf7, 0xde, 0xc3, 0x4e, 0x65, 0xe8, 0x6d, 0xa8, 0xe5, 0x6b, 0x4f,
743
+	0x4b, 0x8c, 0xa1, 0x19, 0x7b, 0x5a, 0x96, 0x71, 0xb9, 0xa9, 0xf1, 0x11, 0xb4, 0x12, 0x43, 0x19,
744
+	0xeb, 0xf6, 0xd0, 0xde, 0x64, 0xcd, 0x6f, 0xb8, 0xde, 0x18, 0xee, 0x55, 0xb6, 0x53, 0xfc, 0x04,
745
+	0x6e, 0x15, 0x4a, 0xa9, 0x8d, 0x58, 0xa3, 0xdf, 0x1e, 0xb2, 0x4d, 0x02, 0x7f, 0x63, 0xf0, 0x12,
746
+	0x3f, 0xf8, 0x81, 0xe0, 0x7e, 0xed, 0x6a, 0xf8, 0x01, 0x34, 0xc7, 0x93, 0xd3, 0x51, 0xc7, 0x22,
747
+	0x7b, 0x59, 0xce, 0x76, 0x6a, 0xc7, 0xe3, 0xf0, 0x42, 0xe0, 0x2e, 0x34, 0xdc, 0x09, 0xef, 0x20,
748
+	0xb2, 0x9b, 0xe5, 0x0c, 0xd7, 0x08, 0x37, 0x4c, 0xf0, 0x23, 0x00, 0x77, 0xc2, 0x3f, 0x9c, 0x8c,
749
+	0x9e, 0xba, 0x23, 0xde, 0xd9, 0x22, 0xfb, 0x59, 0xce, 0xec, 0xff, 0xb9, 0x13, 0xe1, 0xcd, 0x44,
750
+	0x82, 0x1f, 0xc2, 0xed, 0xb3, 0x77, 0x2f, 0x4f, 0x27, 0xaf, 0x5e, 0x74, 0x1a, 0x84, 0x64, 0x39,
751
+	0xdb, 0xad, 0xa1, 0x67, 0xcb, 0x79, 0xf1, 0xae, 0x64, 0xef, 0xd3, 0x17, 0x6a, 0x7d, 0xff, 0x4a,
752
+	0xeb, 0x99, 0x8f, 0xed, 0xcb, 0x15, 0x45, 0x57, 0x2b, 0x8a, 0x7e, 0xaf, 0x28, 0xfa, 0xbc, 0xa6,
753
+	0xd6, 0xd5, 0x9a, 0x5a, 0x3f, 0xd7, 0xd4, 0x9a, 0xb6, 0xcc, 0xbf, 0x79, 0xfc, 0x27, 0x00, 0x00,
754
+	0xff, 0xff, 0xfd, 0xd7, 0xd8, 0x37, 0x85, 0x02, 0x00, 0x00,
755 755
 }
... ...
@@ -19,7 +19,7 @@ import (
19 19
 	"github.com/pkg/errors"
20 20
 )
21 21
 
22
-type ResolveCacheExporterFunc func(ctx context.Context, typ, target string) (Exporter, error)
22
+type ResolveCacheExporterFunc func(ctx context.Context, attrs map[string]string) (Exporter, error)
23 23
 
24 24
 func oneOffProgress(ctx context.Context, id string) func(err error) error {
25 25
 	pw, _, _ := progress.FromContext(ctx)
... ...
@@ -39,9 +39,17 @@ func oneOffProgress(ctx context.Context, id string) func(err error) error {
39 39
 
40 40
 type Exporter interface {
41 41
 	solver.CacheExporterTarget
42
-	Finalize(ctx context.Context) error
42
+	// Finalize finalizes and return metadata that are returned to the client
43
+	// e.g. ExporterResponseManifestDesc
44
+	Finalize(ctx context.Context) (map[string]string, error)
43 45
 }
44 46
 
47
+const (
48
+	// ExportResponseManifestDesc is a key for the map returned from Exporter.Finalize.
49
+	// The map value is a JSON string of an OCI desciptor of a manifest.
50
+	ExporterResponseManifestDesc = "cache.manifest"
51
+)
52
+
45 53
 type contentCacheExporter struct {
46 54
 	solver.CacheExporterTarget
47 55
 	chains   *v1.CacheChains
... ...
@@ -53,14 +61,15 @@ func NewExporter(ingester content.Ingester) Exporter {
53 53
 	return &contentCacheExporter{CacheExporterTarget: cc, chains: cc, ingester: ingester}
54 54
 }
55 55
 
56
-func (ce *contentCacheExporter) Finalize(ctx context.Context) error {
56
+func (ce *contentCacheExporter) Finalize(ctx context.Context) (map[string]string, error) {
57 57
 	return export(ctx, ce.ingester, ce.chains)
58 58
 }
59 59
 
60
-func export(ctx context.Context, ingester content.Ingester, cc *v1.CacheChains) error {
60
+func export(ctx context.Context, ingester content.Ingester, cc *v1.CacheChains) (map[string]string, error) {
61
+	res := make(map[string]string)
61 62
 	config, descs, err := cc.Marshal()
62 63
 	if err != nil {
63
-		return err
64
+		return nil, err
64 65
 	}
65 66
 
66 67
 	// own type because oci type can't be pushed and docker type doesn't have annotations
... ...
@@ -80,11 +89,11 @@ func export(ctx context.Context, ingester content.Ingester, cc *v1.CacheChains)
80 80
 	for _, l := range config.Layers {
81 81
 		dgstPair, ok := descs[l.Blob]
82 82
 		if !ok {
83
-			return errors.Errorf("missing blob %s", l.Blob)
83
+			return nil, errors.Errorf("missing blob %s", l.Blob)
84 84
 		}
85 85
 		layerDone := oneOffProgress(ctx, fmt.Sprintf("writing layer %s", l.Blob))
86 86
 		if err := contentutil.Copy(ctx, ingester, dgstPair.Provider, dgstPair.Descriptor); err != nil {
87
-			return layerDone(errors.Wrap(err, "error writing layer blob"))
87
+			return nil, layerDone(errors.Wrap(err, "error writing layer blob"))
88 88
 		}
89 89
 		layerDone(nil)
90 90
 		mfst.Manifests = append(mfst.Manifests, dgstPair.Descriptor)
... ...
@@ -92,7 +101,7 @@ func export(ctx context.Context, ingester content.Ingester, cc *v1.CacheChains)
92 92
 
93 93
 	dt, err := json.Marshal(config)
94 94
 	if err != nil {
95
-		return err
95
+		return nil, err
96 96
 	}
97 97
 	dgst := digest.FromBytes(dt)
98 98
 	desc := ocispec.Descriptor{
... ...
@@ -102,7 +111,7 @@ func export(ctx context.Context, ingester content.Ingester, cc *v1.CacheChains)
102 102
 	}
103 103
 	configDone := oneOffProgress(ctx, fmt.Sprintf("writing config %s", dgst))
104 104
 	if err := content.WriteBlob(ctx, ingester, dgst.String(), bytes.NewReader(dt), desc); err != nil {
105
-		return configDone(errors.Wrap(err, "error writing config blob"))
105
+		return nil, configDone(errors.Wrap(err, "error writing config blob"))
106 106
 	}
107 107
 	configDone(nil)
108 108
 
... ...
@@ -110,7 +119,7 @@ func export(ctx context.Context, ingester content.Ingester, cc *v1.CacheChains)
110 110
 
111 111
 	dt, err = json.Marshal(mfst)
112 112
 	if err != nil {
113
-		return errors.Wrap(err, "failed to marshal manifest")
113
+		return nil, errors.Wrap(err, "failed to marshal manifest")
114 114
 	}
115 115
 	dgst = digest.FromBytes(dt)
116 116
 
... ...
@@ -121,8 +130,13 @@ func export(ctx context.Context, ingester content.Ingester, cc *v1.CacheChains)
121 121
 	}
122 122
 	mfstDone := oneOffProgress(ctx, fmt.Sprintf("writing manifest %s", dgst))
123 123
 	if err := content.WriteBlob(ctx, ingester, dgst.String(), bytes.NewReader(dt), desc); err != nil {
124
-		return mfstDone(errors.Wrap(err, "error writing manifest blob"))
124
+		return nil, mfstDone(errors.Wrap(err, "error writing manifest blob"))
125
+	}
126
+	descJSON, err := json.Marshal(desc)
127
+	if err != nil {
128
+		return nil, err
125 129
 	}
130
+	res[ExporterResponseManifestDesc] = string(descJSON)
126 131
 	mfstDone(nil)
127
-	return nil
132
+	return res, nil
128 133
 }
... ...
@@ -4,18 +4,24 @@ import (
4 4
 	"context"
5 5
 	"encoding/json"
6 6
 	"io"
7
+	"sync"
8
+	"time"
7 9
 
8 10
 	"github.com/containerd/containerd/content"
11
+	"github.com/containerd/containerd/images"
9 12
 	v1 "github.com/moby/buildkit/cache/remotecache/v1"
10 13
 	"github.com/moby/buildkit/solver"
14
+	"github.com/moby/buildkit/util/imageutil"
11 15
 	"github.com/moby/buildkit/worker"
16
+	digest "github.com/opencontainers/go-digest"
12 17
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
13 18
 	"github.com/pkg/errors"
19
+	"github.com/sirupsen/logrus"
20
+	"golang.org/x/sync/errgroup"
14 21
 )
15 22
 
16 23
 // ResolveCacheImporterFunc returns importer and descriptor.
17
-// Currently typ needs to be an empty string.
18
-type ResolveCacheImporterFunc func(ctx context.Context, typ, ref string) (Importer, ocispec.Descriptor, error)
24
+type ResolveCacheImporterFunc func(ctx context.Context, attrs map[string]string) (Importer, ocispec.Descriptor, error)
19 25
 
20 26
 type Importer interface {
21 27
 	Resolve(ctx context.Context, desc ocispec.Descriptor, id string, w worker.Worker) (solver.CacheManager, error)
... ...
@@ -56,7 +62,7 @@ func (ci *contentCacheImporter) Resolve(ctx context.Context, desc ocispec.Descri
56 56
 	}
57 57
 
58 58
 	if configDesc.Digest == "" {
59
-		return nil, errors.Errorf("invalid build cache from %+v", desc)
59
+		return ci.importInlineCache(ctx, dt, id, w)
60 60
 	}
61 61
 
62 62
 	dt, err = readBlob(ctx, ci.provider, configDesc)
... ...
@@ -96,3 +102,169 @@ func readBlob(ctx context.Context, provider content.Provider, desc ocispec.Descr
96 96
 	}
97 97
 	return dt, err
98 98
 }
99
+
100
+func (ci *contentCacheImporter) importInlineCache(ctx context.Context, dt []byte, id string, w worker.Worker) (solver.CacheManager, error) {
101
+	m := map[digest.Digest][]byte{}
102
+
103
+	if err := ci.allDistributionManifests(ctx, dt, m); err != nil {
104
+		return nil, err
105
+	}
106
+
107
+	var mu sync.Mutex
108
+	cc := v1.NewCacheChains()
109
+
110
+	eg, ctx := errgroup.WithContext(ctx)
111
+	for dgst, dt := range m {
112
+		func(dgst digest.Digest, dt []byte) {
113
+			eg.Go(func() error {
114
+				var m ocispec.Manifest
115
+
116
+				if err := json.Unmarshal(dt, &m); err != nil {
117
+					return err
118
+				}
119
+
120
+				if m.Config.Digest == "" || len(m.Layers) == 0 {
121
+					return nil
122
+				}
123
+
124
+				p, err := content.ReadBlob(ctx, ci.provider, m.Config)
125
+				if err != nil {
126
+					return err
127
+				}
128
+
129
+				var img image
130
+
131
+				if err := json.Unmarshal(p, &img); err != nil {
132
+					return err
133
+				}
134
+
135
+				if len(img.Rootfs.DiffIDs) != len(m.Layers) {
136
+					logrus.Warnf("invalid image with mismatching manifest and config")
137
+					return nil
138
+				}
139
+
140
+				if img.Cache == nil {
141
+					return nil
142
+				}
143
+
144
+				var config v1.CacheConfig
145
+				if err := json.Unmarshal(img.Cache, &config.Records); err != nil {
146
+					return err
147
+				}
148
+
149
+				createdDates, createdMsg, err := parseCreatedLayerInfo(img)
150
+				if err != nil {
151
+					return err
152
+				}
153
+
154
+				layers := v1.DescriptorProvider{}
155
+				for i, m := range m.Layers {
156
+					if m.Annotations == nil {
157
+						m.Annotations = map[string]string{}
158
+					}
159
+					if createdAt := createdDates[i]; createdAt != "" {
160
+						m.Annotations["buildkit/createdat"] = createdAt
161
+					}
162
+					if createdBy := createdMsg[i]; createdBy != "" {
163
+						m.Annotations["buildkit/description"] = createdBy
164
+					}
165
+					m.Annotations["containerd.io/uncompressed"] = img.Rootfs.DiffIDs[i].String()
166
+					layers[m.Digest] = v1.DescriptorProviderPair{
167
+						Descriptor: m,
168
+						Provider:   ci.provider,
169
+					}
170
+					config.Layers = append(config.Layers, v1.CacheLayer{
171
+						Blob:        m.Digest,
172
+						ParentIndex: i - 1,
173
+					})
174
+				}
175
+
176
+				dt, err = json.Marshal(config)
177
+				if err != nil {
178
+					return err
179
+				}
180
+
181
+				mu.Lock()
182
+				if err := v1.ParseConfig(config, layers, cc); err != nil {
183
+					return err
184
+				}
185
+				mu.Unlock()
186
+				return nil
187
+			})
188
+		}(dgst, dt)
189
+	}
190
+
191
+	if err := eg.Wait(); err != nil {
192
+		return nil, err
193
+	}
194
+
195
+	keysStorage, resultStorage, err := v1.NewCacheKeyStorage(cc, w)
196
+	if err != nil {
197
+		return nil, err
198
+	}
199
+	return solver.NewCacheManager(id, keysStorage, resultStorage), nil
200
+}
201
+
202
+func (ci *contentCacheImporter) allDistributionManifests(ctx context.Context, dt []byte, m map[digest.Digest][]byte) error {
203
+	mt, err := imageutil.DetectManifestBlobMediaType(dt)
204
+	if err != nil {
205
+		return err
206
+	}
207
+
208
+	switch mt {
209
+	case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
210
+		m[digest.FromBytes(dt)] = dt
211
+	case images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
212
+		var index ocispec.Index
213
+		if err := json.Unmarshal(dt, &index); err != nil {
214
+			return err
215
+		}
216
+
217
+		for _, d := range index.Manifests {
218
+			if _, ok := m[d.Digest]; ok {
219
+				continue
220
+			}
221
+			p, err := content.ReadBlob(ctx, ci.provider, d)
222
+			if err != nil {
223
+				return err
224
+			}
225
+			if err := ci.allDistributionManifests(ctx, p, m); err != nil {
226
+				return err
227
+			}
228
+		}
229
+	}
230
+
231
+	return nil
232
+}
233
+
234
+type image struct {
235
+	Rootfs struct {
236
+		DiffIDs []digest.Digest `json:"diff_ids"`
237
+	} `json:"rootfs"`
238
+	Cache   []byte `json:"moby.buildkit.cache.v0"`
239
+	History []struct {
240
+		Created    *time.Time `json:"created,omitempty"`
241
+		CreatedBy  string     `json:"created_by,omitempty"`
242
+		EmptyLayer bool       `json:"empty_layer,omitempty"`
243
+	} `json:"history,omitempty"`
244
+}
245
+
246
+func parseCreatedLayerInfo(img image) ([]string, []string, error) {
247
+	dates := make([]string, 0, len(img.Rootfs.DiffIDs))
248
+	createdBy := make([]string, 0, len(img.Rootfs.DiffIDs))
249
+	for _, h := range img.History {
250
+		if !h.EmptyLayer {
251
+			str := ""
252
+			if h.Created != nil {
253
+				dt, err := h.Created.MarshalText()
254
+				if err != nil {
255
+					return nil, nil, err
256
+				}
257
+				str = string(dt)
258
+			}
259
+			dates = append(dates, str)
260
+			createdBy = append(createdBy, h.CreatedBy)
261
+		}
262
+	}
263
+	return dates, createdBy, nil
264
+}
99 265
new file mode 100644
... ...
@@ -0,0 +1,99 @@
0
+package registry
1
+
2
+import (
3
+	"context"
4
+	"encoding/json"
5
+
6
+	"github.com/moby/buildkit/cache/remotecache"
7
+	v1 "github.com/moby/buildkit/cache/remotecache/v1"
8
+	"github.com/moby/buildkit/solver"
9
+	digest "github.com/opencontainers/go-digest"
10
+	"github.com/sirupsen/logrus"
11
+)
12
+
13
+func ResolveCacheExporterFunc() remotecache.ResolveCacheExporterFunc {
14
+	return func(ctx context.Context, _ map[string]string) (remotecache.Exporter, error) {
15
+		return NewExporter(), nil
16
+	}
17
+}
18
+
19
+func NewExporter() remotecache.Exporter {
20
+	cc := v1.NewCacheChains()
21
+	return &exporter{CacheExporterTarget: cc, chains: cc}
22
+}
23
+
24
+type exporter struct {
25
+	solver.CacheExporterTarget
26
+	chains *v1.CacheChains
27
+}
28
+
29
+func (ce *exporter) Finalize(ctx context.Context) (map[string]string, error) {
30
+	return nil, nil
31
+}
32
+
33
+func (ce *exporter) ExportForLayers(layers []digest.Digest) ([]byte, error) {
34
+	config, descs, err := ce.chains.Marshal()
35
+	if err != nil {
36
+		return nil, err
37
+	}
38
+
39
+	descs2 := map[digest.Digest]v1.DescriptorProviderPair{}
40
+	for _, k := range layers {
41
+		if v, ok := descs[k]; ok {
42
+			descs2[k] = v
43
+			continue
44
+		}
45
+		// fallback for uncompressed digests
46
+		for _, v := range descs {
47
+			if uc := v.Descriptor.Annotations["containerd.io/uncompressed"]; uc == string(k) {
48
+				descs2[v.Descriptor.Digest] = v
49
+			}
50
+		}
51
+	}
52
+
53
+	cc := v1.NewCacheChains()
54
+	if err := v1.ParseConfig(*config, descs2, cc); err != nil {
55
+		return nil, err
56
+	}
57
+
58
+	cfg, _, err := cc.Marshal()
59
+	if err != nil {
60
+		return nil, err
61
+	}
62
+
63
+	if len(cfg.Layers) == 0 {
64
+		logrus.Warn("failed to match any cache with layers")
65
+		return nil, nil
66
+	}
67
+
68
+	cache := map[digest.Digest]int{}
69
+
70
+	// reorder layers based on the order in the image
71
+	for i, r := range cfg.Records {
72
+		for j, rr := range r.Results {
73
+			n := getSortedLayerIndex(rr.LayerIndex, cfg.Layers, cache)
74
+			rr.LayerIndex = n
75
+			r.Results[j] = rr
76
+			cfg.Records[i] = r
77
+		}
78
+	}
79
+
80
+	dt, err := json.Marshal(cfg.Records)
81
+	if err != nil {
82
+		return nil, err
83
+	}
84
+
85
+	return dt, nil
86
+}
87
+
88
+func getSortedLayerIndex(idx int, layers []v1.CacheLayer, cache map[digest.Digest]int) int {
89
+	if idx == -1 {
90
+		return -1
91
+	}
92
+	l := layers[idx]
93
+	if i, ok := cache[l.Blob]; ok {
94
+		return i
95
+	}
96
+	cache[l.Blob] = getSortedLayerIndex(l.ParentIndex, layers, cache) + 1
97
+	return cache[l.Blob]
98
+}
... ...
@@ -6,6 +6,7 @@ import (
6 6
 
7 7
 	"github.com/containerd/containerd/remotes"
8 8
 	"github.com/containerd/containerd/remotes/docker"
9
+	"github.com/docker/distribution/reference"
9 10
 	"github.com/moby/buildkit/cache/remotecache"
10 11
 	"github.com/moby/buildkit/session"
11 12
 	"github.com/moby/buildkit/session/auth"
... ...
@@ -15,10 +16,26 @@ import (
15 15
 	"github.com/pkg/errors"
16 16
 )
17 17
 
18
+func canonicalizeRef(rawRef string) (string, error) {
19
+	if rawRef == "" {
20
+		return "", errors.New("missing ref")
21
+	}
22
+	parsed, err := reference.ParseNormalizedNamed(rawRef)
23
+	if err != nil {
24
+		return "", err
25
+	}
26
+	return reference.TagNameOnly(parsed).String(), nil
27
+}
28
+
29
+const (
30
+	attrRef = "ref"
31
+)
32
+
18 33
 func ResolveCacheExporterFunc(sm *session.Manager, resolverOpt resolver.ResolveOptionsFunc) remotecache.ResolveCacheExporterFunc {
19
-	return func(ctx context.Context, typ, ref string) (remotecache.Exporter, error) {
20
-		if typ != "" {
21
-			return nil, errors.Errorf("unsupported cache exporter type: %s", typ)
34
+	return func(ctx context.Context, attrs map[string]string) (remotecache.Exporter, error) {
35
+		ref, err := canonicalizeRef(attrs[attrRef])
36
+		if err != nil {
37
+			return nil, err
22 38
 		}
23 39
 		remote := newRemoteResolver(ctx, resolverOpt, sm, ref)
24 40
 		pusher, err := remote.Pusher(ctx, ref)
... ...
@@ -30,9 +47,10 @@ func ResolveCacheExporterFunc(sm *session.Manager, resolverOpt resolver.ResolveO
30 30
 }
31 31
 
32 32
 func ResolveCacheImporterFunc(sm *session.Manager, resolverOpt resolver.ResolveOptionsFunc) remotecache.ResolveCacheImporterFunc {
33
-	return func(ctx context.Context, typ, ref string) (remotecache.Importer, specs.Descriptor, error) {
34
-		if typ != "" {
35
-			return nil, specs.Descriptor{}, errors.Errorf("unsupported cache importer type: %s", typ)
33
+	return func(ctx context.Context, attrs map[string]string) (remotecache.Importer, specs.Descriptor, error) {
34
+		ref, err := canonicalizeRef(attrs[attrRef])
35
+		if err != nil {
36
+			return nil, specs.Descriptor{}, err
36 37
 		}
37 38
 		remote := newRemoteResolver(ctx, resolverOpt, sm, ref)
38 39
 		xref, desc, err := remote.Resolve(ctx, ref)
... ...
@@ -2,6 +2,7 @@ package cacheimport
2 2
 
3 3
 import (
4 4
 	"context"
5
+	"time"
5 6
 
6 7
 	"github.com/moby/buildkit/identity"
7 8
 	"github.com/moby/buildkit/solver"
... ...
@@ -26,6 +27,7 @@ func NewCacheKeyStorage(cc *CacheChains, w worker.Worker) (solver.CacheKeyStorag
26 26
 	results := &cacheResultStorage{
27 27
 		w:        w,
28 28
 		byID:     storage.byID,
29
+		byItem:   storage.byItem,
29 30
 		byResult: storage.byResult,
30 31
 	}
31 32
 
... ...
@@ -154,8 +156,22 @@ func (cs *cacheKeyStorage) WalkLinks(id string, link solver.CacheInfoLink, fn fu
154 154
 	return nil
155 155
 }
156 156
 
157
-// TODO:
158 157
 func (cs *cacheKeyStorage) WalkBacklinks(id string, fn func(id string, link solver.CacheInfoLink) error) error {
158
+	for k, it := range cs.byID {
159
+		for nl, ids := range it.links {
160
+			for _, id2 := range ids {
161
+				if id == id2 {
162
+					if err := fn(k, solver.CacheInfoLink{
163
+						Input:    solver.Index(nl.input),
164
+						Selector: digest.Digest(nl.selector),
165
+						Digest:   nl.dgst,
166
+					}); err != nil {
167
+						return err
168
+					}
169
+				}
170
+			}
171
+		}
172
+	}
159 173
 	return nil
160 174
 }
161 175
 
... ...
@@ -189,19 +205,54 @@ type cacheResultStorage struct {
189 189
 	w        worker.Worker
190 190
 	byID     map[string]*itemWithOutgoingLinks
191 191
 	byResult map[string]map[string]struct{}
192
+	byItem   map[*item]string
192 193
 }
193 194
 
194
-func (cs *cacheResultStorage) Save(res solver.Result) (solver.CacheResult, error) {
195
+func (cs *cacheResultStorage) Save(res solver.Result, createdAt time.Time) (solver.CacheResult, error) {
195 196
 	return solver.CacheResult{}, errors.Errorf("importer is immutable")
196 197
 }
197 198
 
198
-func (cs *cacheResultStorage) Load(ctx context.Context, res solver.CacheResult) (solver.Result, error) {
199
-	remote, err := cs.LoadRemote(ctx, res)
200
-	if err != nil {
199
+func (cs *cacheResultStorage) LoadWithParents(ctx context.Context, res solver.CacheResult) (map[string]solver.Result, error) {
200
+	v := cs.byResultID(res.ID)
201
+	if v == nil || v.result == nil {
202
+		return nil, errors.WithStack(solver.ErrNotFound)
203
+	}
204
+
205
+	m := map[string]solver.Result{}
206
+
207
+	if err := v.walkAllResults(func(i *item) error {
208
+		if i.result == nil {
209
+			return nil
210
+		}
211
+		id, ok := cs.byItem[i]
212
+		if !ok {
213
+			return nil
214
+		}
215
+		if isSubRemote(*i.result, *v.result) {
216
+			ref, err := cs.w.FromRemote(ctx, i.result)
217
+			if err != nil {
218
+				return err
219
+			}
220
+			m[id] = worker.NewWorkerRefResult(ref, cs.w)
221
+		}
222
+		return nil
223
+	}); err != nil {
224
+		for _, v := range m {
225
+			v.Release(context.TODO())
226
+		}
201 227
 		return nil, err
202 228
 	}
203 229
 
204
-	ref, err := cs.w.FromRemote(ctx, remote)
230
+	return m, nil
231
+}
232
+
233
+func (cs *cacheResultStorage) Load(ctx context.Context, res solver.CacheResult) (solver.Result, error) {
234
+	item := cs.byResultID(res.ID)
235
+	if item == nil || item.result == nil {
236
+		return nil, errors.WithStack(solver.ErrNotFound)
237
+	}
238
+
239
+	ref, err := cs.w.FromRemote(ctx, item.result)
205 240
 	if err != nil {
206 241
 		return nil, err
207 242
 	}
... ...
@@ -209,8 +260,8 @@ func (cs *cacheResultStorage) Load(ctx context.Context, res solver.CacheResult)
209 209
 }
210 210
 
211 211
 func (cs *cacheResultStorage) LoadRemote(ctx context.Context, res solver.CacheResult) (*solver.Remote, error) {
212
-	if r := cs.byResultID(res.ID); r != nil {
213
-		return r, nil
212
+	if r := cs.byResultID(res.ID); r != nil && r.result != nil {
213
+		return r.result, nil
214 214
 	}
215 215
 	return nil, errors.WithStack(solver.ErrNotFound)
216 216
 }
... ...
@@ -219,7 +270,7 @@ func (cs *cacheResultStorage) Exists(id string) bool {
219 219
 	return cs.byResultID(id) != nil
220 220
 }
221 221
 
222
-func (cs *cacheResultStorage) byResultID(resultID string) *solver.Remote {
222
+func (cs *cacheResultStorage) byResultID(resultID string) *itemWithOutgoingLinks {
223 223
 	m, ok := cs.byResult[resultID]
224 224
 	if !ok || len(m) == 0 {
225 225
 		return nil
... ...
@@ -228,9 +279,7 @@ func (cs *cacheResultStorage) byResultID(resultID string) *solver.Remote {
228 228
 	for id := range m {
229 229
 		it, ok := cs.byID[id]
230 230
 		if ok {
231
-			if r := it.result; r != nil {
232
-				return r
233
-			}
231
+			return it
234 232
 		}
235 233
 	}
236 234
 
... ...
@@ -1,6 +1,7 @@
1 1
 package cacheimport
2 2
 
3 3
 import (
4
+	"strings"
4 5
 	"time"
5 6
 
6 7
 	"github.com/containerd/containerd/content"
... ...
@@ -19,6 +20,9 @@ type CacheChains struct {
19 19
 }
20 20
 
21 21
 func (c *CacheChains) Add(dgst digest.Digest) solver.CacheExporterRecord {
22
+	if strings.HasPrefix(dgst.String(), "random:") {
23
+		return &nopRecord{}
24
+	}
22 25
 	it := &item{c: c, dgst: dgst}
23 26
 	c.items = append(c.items, it)
24 27
 	return it
... ...
@@ -124,4 +128,27 @@ func (c *item) LinkFrom(rec solver.CacheExporterRecord, index int, selector stri
124 124
 	c.links[index][link{src: src, selector: selector}] = struct{}{}
125 125
 }
126 126
 
127
+func (c *item) walkAllResults(fn func(i *item) error) error {
128
+	if err := fn(c); err != nil {
129
+		return err
130
+	}
131
+	for _, links := range c.links {
132
+		for l := range links {
133
+			if err := l.src.walkAllResults(fn); err != nil {
134
+				return err
135
+			}
136
+		}
137
+	}
138
+	return nil
139
+}
140
+
141
+type nopRecord struct {
142
+}
143
+
144
+func (c *nopRecord) AddResult(createdAt time.Time, result *solver.Remote) {
145
+}
146
+
147
+func (c *nopRecord) LinkFrom(rec solver.CacheExporterRecord, index int, selector string) {
148
+}
149
+
127 150
 var _ solver.CacheExporterTarget = &CacheChains{}
... ...
@@ -6,7 +6,7 @@ package cacheimport
6 6
 // https://github.com/opencontainers/image-spec/blob/master/image-index.md .
7 7
 // Manifests array contains descriptors to the cache layers and one instance of
8 8
 // build cache config with media type application/vnd.buildkit.cacheconfig.v0 .
9
-// The cache layer descripts need to have an annotation with uncompressed digest
9
+// The cache layer descriptors need to have an annotation with uncompressed digest
10 10
 // to allow deduplication on extraction and optionally "buildkit/createdat"
11 11
 // annotation to support maintaining original timestamps.
12 12
 //
... ...
@@ -15,6 +15,10 @@ func Parse(configJSON []byte, provider DescriptorProvider, t solver.CacheExporte
15 15
 		return err
16 16
 	}
17 17
 
18
+	return ParseConfig(config, provider, t)
19
+}
20
+
21
+func ParseConfig(config CacheConfig, provider DescriptorProvider, t solver.CacheExporterTarget) error {
18 22
 	cache := map[int]solver.CacheExporterRecord{}
19 23
 
20 24
 	for i := range config.Records {
... ...
@@ -22,7 +26,6 @@ func Parse(configJSON []byte, provider DescriptorProvider, t solver.CacheExporte
22 22
 			return err
23 23
 		}
24 24
 	}
25
-
26 25
 	return nil
27 26
 }
28 27
 
... ...
@@ -57,7 +60,9 @@ func parseRecord(cc CacheConfig, idx int, provider DescriptorProvider, t solver.
57 57
 		if err != nil {
58 58
 			return nil, err
59 59
 		}
60
-		r.AddResult(res.CreatedAt, remote)
60
+		if remote != nil {
61
+			r.AddResult(res.CreatedAt, remote)
62
+		}
61 63
 	}
62 64
 
63 65
 	cache[idx] = r
... ...
@@ -78,7 +83,7 @@ func getRemoteChain(layers []CacheLayer, idx int, provider DescriptorProvider, v
78 78
 
79 79
 	descPair, ok := provider[l.Blob]
80 80
 	if !ok {
81
-		return nil, errors.Errorf("missing blob for %s", l.Blob)
81
+		return nil, nil
82 82
 	}
83 83
 
84 84
 	var r *solver.Remote
... ...
@@ -88,6 +93,9 @@ func getRemoteChain(layers []CacheLayer, idx int, provider DescriptorProvider, v
88 88
 		if err != nil {
89 89
 			return nil, err
90 90
 		}
91
+		if r == nil {
92
+			return nil, nil
93
+		}
91 94
 		r.Descriptors = append(r.Descriptors, descPair.Descriptor)
92 95
 		mp := contentutil.NewMultiProvider(r.Provider)
93 96
 		mp.Add(descPair.Descriptor.Digest, descPair.Provider)
... ...
@@ -304,3 +304,15 @@ func marshalItem(it *item, state *marshalState) error {
304 304
 	state.records = append(state.records, rec)
305 305
 	return nil
306 306
 }
307
+
308
+func isSubRemote(sub, main solver.Remote) bool {
309
+	if len(sub.Descriptors) > len(main.Descriptors) {
310
+		return false
311
+	}
312
+	for i := range sub.Descriptors {
313
+		if sub.Descriptors[i].Digest != main.Descriptors[i].Digest {
314
+			return false
315
+		}
316
+	}
317
+	return true
318
+}
... ...
@@ -16,7 +16,7 @@ func dialer(address string, timeout time.Duration) (net.Conn, error) {
16 16
 	}
17 17
 	switch addrParts[0] {
18 18
 	case "npipe":
19
-		address = strings.Replace(addrParts[1], "/", "\\", 0)
19
+		address = strings.Replace(addrParts[1], "/", "\\", -1)
20 20
 		return winio.DialPipe(address, &timeout)
21 21
 	default:
22 22
 		return net.DialTimeout(addrParts[0], addrParts[1], timeout)
... ...
@@ -41,5 +41,6 @@ type SolveStatus struct {
41 41
 }
42 42
 
43 43
 type SolveResponse struct {
44
+	// ExporterResponse is also used for CacheExporter
44 45
 	ExporterResponse map[string]string
45 46
 }
... ...
@@ -405,12 +405,16 @@ func WithDescription(m map[string]string) ConstraintsOpt {
405 405
 	})
406 406
 }
407 407
 
408
-func WithCustomName(name string, a ...interface{}) ConstraintsOpt {
408
+func WithCustomName(name string) ConstraintsOpt {
409 409
 	return WithDescription(map[string]string{
410
-		"llb.customname": fmt.Sprintf(name, a...),
410
+		"llb.customname": name,
411 411
 	})
412 412
 }
413 413
 
414
+func WithCustomNamef(name string, a ...interface{}) ConstraintsOpt {
415
+	return WithCustomName(fmt.Sprintf(name, a...))
416
+}
417
+
414 418
 // WithExportCache forces results for this vertex to be exported with the cache
415 419
 func WithExportCache() ConstraintsOpt {
416 420
 	return constraintsOptFunc(func(c *Constraints) {
417 421
new file mode 100644
... ...
@@ -0,0 +1,113 @@
0
+package ociindex
1
+
2
+import (
3
+	"encoding/json"
4
+	"io/ioutil"
5
+	"os"
6
+
7
+	"github.com/gofrs/flock"
8
+	"github.com/opencontainers/image-spec/specs-go/v1"
9
+	"github.com/pkg/errors"
10
+)
11
+
12
+const (
13
+	// IndexJSONLockFileSuffix is the suffix of the lock file
14
+	IndexJSONLockFileSuffix = ".lock"
15
+)
16
+
17
+// PutDescToIndex puts desc to index with tag.
18
+// Existing manifests with the same tag will be removed from the index.
19
+func PutDescToIndex(index *v1.Index, desc v1.Descriptor, tag string) error {
20
+	if index == nil {
21
+		index = &v1.Index{}
22
+	}
23
+	if index.SchemaVersion == 0 {
24
+		index.SchemaVersion = 2
25
+	}
26
+	if tag != "" {
27
+		if desc.Annotations == nil {
28
+			desc.Annotations = make(map[string]string)
29
+		}
30
+		desc.Annotations[v1.AnnotationRefName] = tag
31
+		// remove existing manifests with the same tag
32
+		var manifests []v1.Descriptor
33
+		for _, m := range index.Manifests {
34
+			if m.Annotations[v1.AnnotationRefName] != tag {
35
+				manifests = append(manifests, m)
36
+			}
37
+		}
38
+		index.Manifests = manifests
39
+	}
40
+	index.Manifests = append(index.Manifests, desc)
41
+	return nil
42
+}
43
+
44
+func PutDescToIndexJSONFileLocked(indexJSONPath string, desc v1.Descriptor, tag string) error {
45
+	lockPath := indexJSONPath + IndexJSONLockFileSuffix
46
+	lock := flock.New(lockPath)
47
+	locked, err := lock.TryLock()
48
+	if err != nil {
49
+		return errors.Wrapf(err, "could not lock %s", lockPath)
50
+	}
51
+	if !locked {
52
+		return errors.Errorf("could not lock %s", lockPath)
53
+	}
54
+	defer func() {
55
+		lock.Unlock()
56
+		os.RemoveAll(lockPath)
57
+	}()
58
+	f, err := os.OpenFile(indexJSONPath, os.O_RDWR|os.O_CREATE, 0644)
59
+	if err != nil {
60
+		return errors.Wrapf(err, "could not open %s", indexJSONPath)
61
+	}
62
+	defer f.Close()
63
+	var idx v1.Index
64
+	b, err := ioutil.ReadAll(f)
65
+	if err != nil {
66
+		return errors.Wrapf(err, "could not read %s", indexJSONPath)
67
+	}
68
+	if len(b) > 0 {
69
+		if err := json.Unmarshal(b, &idx); err != nil {
70
+			return errors.Wrapf(err, "could not unmarshal %s (%q)", indexJSONPath, string(b))
71
+		}
72
+	}
73
+	if err = PutDescToIndex(&idx, desc, tag); err != nil {
74
+		return err
75
+	}
76
+	b, err = json.Marshal(idx)
77
+	if err != nil {
78
+		return err
79
+	}
80
+	if _, err = f.WriteAt(b, 0); err != nil {
81
+		return err
82
+	}
83
+	if err = f.Truncate(int64(len(b))); err != nil {
84
+		return err
85
+	}
86
+	return nil
87
+}
88
+
89
+func ReadIndexJSONFileLocked(indexJSONPath string) (*v1.Index, error) {
90
+	lockPath := indexJSONPath + IndexJSONLockFileSuffix
91
+	lock := flock.New(lockPath)
92
+	locked, err := lock.TryRLock()
93
+	if err != nil {
94
+		return nil, errors.Wrapf(err, "could not lock %s", lockPath)
95
+	}
96
+	if !locked {
97
+		return nil, errors.Errorf("could not lock %s", lockPath)
98
+	}
99
+	defer func() {
100
+		lock.Unlock()
101
+		os.RemoveAll(lockPath)
102
+	}()
103
+	b, err := ioutil.ReadFile(indexJSONPath)
104
+	if err != nil {
105
+		return nil, errors.Wrapf(err, "could not read %s", indexJSONPath)
106
+	}
107
+	var idx v1.Index
108
+	if err := json.Unmarshal(b, &idx); err != nil {
109
+		return nil, errors.Wrapf(err, "could not unmarshal %s (%q)", indexJSONPath, string(b))
110
+	}
111
+	return &idx, nil
112
+}
... ...
@@ -2,20 +2,26 @@ package client
2 2
 
3 3
 import (
4 4
 	"context"
5
+	"encoding/json"
5 6
 	"io"
6 7
 	"os"
7 8
 	"path/filepath"
8 9
 	"strings"
9 10
 	"time"
10 11
 
12
+	"github.com/containerd/containerd/content"
13
+	contentlocal "github.com/containerd/containerd/content/local"
11 14
 	controlapi "github.com/moby/buildkit/api/services/control"
12 15
 	"github.com/moby/buildkit/client/llb"
16
+	"github.com/moby/buildkit/client/ociindex"
13 17
 	"github.com/moby/buildkit/identity"
14 18
 	"github.com/moby/buildkit/session"
19
+	sessioncontent "github.com/moby/buildkit/session/content"
15 20
 	"github.com/moby/buildkit/session/filesync"
16 21
 	"github.com/moby/buildkit/session/grpchijack"
17 22
 	"github.com/moby/buildkit/solver/pb"
18 23
 	"github.com/moby/buildkit/util/entitlements"
24
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
19 25
 	opentracing "github.com/opentracing/opentracing-go"
20 26
 	"github.com/pkg/errors"
21 27
 	"github.com/sirupsen/logrus"
... ...
@@ -24,21 +30,29 @@ import (
24 24
 )
25 25
 
26 26
 type SolveOpt struct {
27
-	Exporter            string
28
-	ExporterAttrs       map[string]string
29
-	ExporterOutput      io.WriteCloser // for ExporterOCI and ExporterDocker
30
-	ExporterOutputDir   string         // for ExporterLocal
27
+	Exports             []ExportEntry
31 28
 	LocalDirs           map[string]string
32 29
 	SharedKey           string
33 30
 	Frontend            string
34 31
 	FrontendAttrs       map[string]string
35
-	ExportCache         string
36
-	ExportCacheAttrs    map[string]string
37
-	ImportCache         []string
32
+	CacheExports        []CacheOptionsEntry
33
+	CacheImports        []CacheOptionsEntry
38 34
 	Session             []session.Attachable
39 35
 	AllowedEntitlements []entitlements.Entitlement
40 36
 }
41 37
 
38
+type ExportEntry struct {
39
+	Type      string
40
+	Attrs     map[string]string
41
+	Output    io.WriteCloser // for ExporterOCI and ExporterDocker
42
+	OutputDir string         // for ExporterLocal
43
+}
44
+
45
+type CacheOptionsEntry struct {
46
+	Type  string
47
+	Attrs map[string]string
48
+}
49
+
42 50
 // Solve calls Solve on the controller.
43 51
 // def must be nil if (and only if) opt.Frontend is set.
44 52
 func (c *Client) Solve(ctx context.Context, def *llb.Definition, opt SolveOpt, statusChan chan *SolveStatus) (*SolveResponse, error) {
... ...
@@ -93,32 +107,51 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
93 93
 		s.Allow(a)
94 94
 	}
95 95
 
96
-	switch opt.Exporter {
96
+	var ex ExportEntry
97
+	if len(opt.Exports) > 1 {
98
+		return nil, errors.New("currently only single Exports can be specified")
99
+	}
100
+	if len(opt.Exports) == 1 {
101
+		ex = opt.Exports[0]
102
+	}
103
+
104
+	switch ex.Type {
97 105
 	case ExporterLocal:
98
-		if opt.ExporterOutput != nil {
106
+		if ex.Output != nil {
99 107
 			return nil, errors.New("output file writer is not supported by local exporter")
100 108
 		}
101
-		if opt.ExporterOutputDir == "" {
109
+		if ex.OutputDir == "" {
102 110
 			return nil, errors.New("output directory is required for local exporter")
103 111
 		}
104
-		s.Allow(filesync.NewFSSyncTargetDir(opt.ExporterOutputDir))
112
+		s.Allow(filesync.NewFSSyncTargetDir(ex.OutputDir))
105 113
 	case ExporterOCI, ExporterDocker:
106
-		if opt.ExporterOutputDir != "" {
107
-			return nil, errors.Errorf("output directory %s is not supported by %s exporter", opt.ExporterOutputDir, opt.Exporter)
114
+		if ex.OutputDir != "" {
115
+			return nil, errors.Errorf("output directory %s is not supported by %s exporter", ex.OutputDir, ex.Type)
108 116
 		}
109
-		if opt.ExporterOutput == nil {
110
-			return nil, errors.Errorf("output file writer is required for %s exporter", opt.Exporter)
117
+		if ex.Output == nil {
118
+			return nil, errors.Errorf("output file writer is required for %s exporter", ex.Type)
111 119
 		}
112
-		s.Allow(filesync.NewFSSyncTarget(opt.ExporterOutput))
120
+		s.Allow(filesync.NewFSSyncTarget(ex.Output))
113 121
 	default:
114
-		if opt.ExporterOutput != nil {
115
-			return nil, errors.Errorf("output file writer is not supported by %s exporter", opt.Exporter)
122
+		if ex.Output != nil {
123
+			return nil, errors.Errorf("output file writer is not supported by %s exporter", ex.Type)
116 124
 		}
117
-		if opt.ExporterOutputDir != "" {
118
-			return nil, errors.Errorf("output directory %s is not supported by %s exporter", opt.ExporterOutputDir, opt.Exporter)
125
+		if ex.OutputDir != "" {
126
+			return nil, errors.Errorf("output directory %s is not supported by %s exporter", ex.OutputDir, ex.Type)
119 127
 		}
120 128
 	}
121 129
 
130
+	cacheOpt, err := parseCacheOptions(opt)
131
+	if err != nil {
132
+		return nil, err
133
+	}
134
+	if len(cacheOpt.contentStores) > 0 {
135
+		s.Allow(sessioncontent.NewAttachable(cacheOpt.contentStores))
136
+	}
137
+	for k, v := range cacheOpt.frontendAttrs {
138
+		opt.FrontendAttrs[k] = v
139
+	}
140
+
122 141
 	eg.Go(func() error {
123 142
 		return s.Run(statusContext, grpchijack.Dialer(c.controlClient()))
124 143
 	})
... ...
@@ -144,17 +177,13 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
144 144
 		resp, err := c.controlClient().Solve(ctx, &controlapi.SolveRequest{
145 145
 			Ref:           ref,
146 146
 			Definition:    pbd,
147
-			Exporter:      opt.Exporter,
148
-			ExporterAttrs: opt.ExporterAttrs,
147
+			Exporter:      ex.Type,
148
+			ExporterAttrs: ex.Attrs,
149 149
 			Session:       s.ID(),
150 150
 			Frontend:      opt.Frontend,
151 151
 			FrontendAttrs: opt.FrontendAttrs,
152
-			Cache: controlapi.CacheOptions{
153
-				ExportRef:   opt.ExportCache,
154
-				ImportRefs:  opt.ImportCache,
155
-				ExportAttrs: opt.ExportCacheAttrs,
156
-			},
157
-			Entitlements: opt.AllowedEntitlements,
152
+			Cache:         cacheOpt.options,
153
+			Entitlements:  opt.AllowedEntitlements,
158 154
 		})
159 155
 		if err != nil {
160 156
 			return errors.Wrap(err, "failed to solve")
... ...
@@ -243,6 +272,19 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
243 243
 	if err := eg.Wait(); err != nil {
244 244
 		return nil, err
245 245
 	}
246
+	// Update index.json of exported cache content store
247
+	// FIXME(AkihiroSuda): dedupe const definition of cache/remotecache.ExporterResponseManifestDesc = "cache.manifest"
248
+	if manifestDescJSON := res.ExporterResponse["cache.manifest"]; manifestDescJSON != "" {
249
+		var manifestDesc ocispec.Descriptor
250
+		if err = json.Unmarshal([]byte(manifestDescJSON), &manifestDesc); err != nil {
251
+			return nil, err
252
+		}
253
+		for indexJSONPath, tag := range cacheOpt.indicesToUpdate {
254
+			if err = ociindex.PutDescToIndexJSONFileLocked(indexJSONPath, manifestDesc, tag); err != nil {
255
+				return nil, err
256
+			}
257
+		}
258
+	}
246 259
 	return res, nil
247 260
 }
248 261
 
... ...
@@ -295,3 +337,128 @@ func defaultSessionName() string {
295 295
 	}
296 296
 	return filepath.Base(wd)
297 297
 }
298
+
299
+type cacheOptions struct {
300
+	options         controlapi.CacheOptions
301
+	contentStores   map[string]content.Store // key: ID of content store ("local:" + csDir)
302
+	indicesToUpdate map[string]string        // key: index.JSON file name, value: tag
303
+	frontendAttrs   map[string]string
304
+}
305
+
306
+func parseCacheOptions(opt SolveOpt) (*cacheOptions, error) {
307
+	var (
308
+		cacheExports []*controlapi.CacheOptionsEntry
309
+		cacheImports []*controlapi.CacheOptionsEntry
310
+		// legacy API is used for registry caches, because the daemon might not support the new API
311
+		legacyExportRef  string
312
+		legacyImportRefs []string
313
+	)
314
+	contentStores := make(map[string]content.Store)
315
+	indicesToUpdate := make(map[string]string) // key: index.JSON file name, value: tag
316
+	frontendAttrs := make(map[string]string)
317
+	legacyExportAttrs := make(map[string]string)
318
+	for _, ex := range opt.CacheExports {
319
+		if ex.Type == "local" {
320
+			csDir := ex.Attrs["dest"]
321
+			if csDir == "" {
322
+				return nil, errors.New("local cache exporter requires dest")
323
+			}
324
+			if err := os.MkdirAll(csDir, 0755); err != nil {
325
+				return nil, err
326
+			}
327
+			cs, err := contentlocal.NewStore(csDir)
328
+			if err != nil {
329
+				return nil, err
330
+			}
331
+			contentStores["local:"+csDir] = cs
332
+			// TODO(AkihiroSuda): support custom index JSON path and tag
333
+			indexJSONPath := filepath.Join(csDir, "index.json")
334
+			indicesToUpdate[indexJSONPath] = "latest"
335
+		}
336
+		if ex.Type == "registry" && legacyExportRef == "" {
337
+			legacyExportRef = ex.Attrs["ref"]
338
+			for k, v := range ex.Attrs {
339
+				if k != "ref" {
340
+					legacyExportAttrs[k] = v
341
+				}
342
+			}
343
+		} else {
344
+			cacheExports = append(cacheExports, &controlapi.CacheOptionsEntry{
345
+				Type:  ex.Type,
346
+				Attrs: ex.Attrs,
347
+			})
348
+		}
349
+	}
350
+	for _, im := range opt.CacheImports {
351
+		attrs := im.Attrs
352
+		if im.Type == "local" {
353
+			csDir := im.Attrs["src"]
354
+			if csDir == "" {
355
+				return nil, errors.New("local cache importer requires src")
356
+			}
357
+			if err := os.MkdirAll(csDir, 0755); err != nil {
358
+				return nil, err
359
+			}
360
+			cs, err := contentlocal.NewStore(csDir)
361
+			if err != nil {
362
+				return nil, err
363
+			}
364
+			contentStores["local:"+csDir] = cs
365
+
366
+			// if digest is not specified, load from "latest" tag
367
+			if attrs["digest"] == "" {
368
+				idx, err := ociindex.ReadIndexJSONFileLocked(filepath.Join(csDir, "index.json"))
369
+				if err != nil {
370
+					return nil, err
371
+				}
372
+				for _, m := range idx.Manifests {
373
+					if m.Annotations[ocispec.AnnotationRefName] == "latest" {
374
+						attrs["digest"] = string(m.Digest)
375
+						break
376
+					}
377
+				}
378
+				if attrs["digest"] == "" {
379
+					return nil, errors.New("local cache importer requires either explicit digest or \"latest\" tag on index.json")
380
+				}
381
+			}
382
+		}
383
+		if im.Type == "registry" {
384
+			legacyImportRef := attrs["ref"]
385
+			legacyImportRefs = append(legacyImportRefs, legacyImportRef)
386
+		} else {
387
+			cacheImports = append(cacheImports, &controlapi.CacheOptionsEntry{
388
+				Type:  im.Type,
389
+				Attrs: attrs,
390
+			})
391
+		}
392
+	}
393
+	if opt.Frontend != "" {
394
+		// use legacy API for registry importers, because the frontend might not support the new API
395
+		if len(legacyImportRefs) > 0 {
396
+			frontendAttrs["cache-from"] = strings.Join(legacyImportRefs, ",")
397
+		}
398
+		// use new API for other importers
399
+		if len(cacheImports) > 0 {
400
+			s, err := json.Marshal(cacheImports)
401
+			if err != nil {
402
+				return nil, err
403
+			}
404
+			frontendAttrs["cache-imports"] = string(s)
405
+		}
406
+	}
407
+	res := cacheOptions{
408
+		options: controlapi.CacheOptions{
409
+			// old API (for registry caches, planned to be removed in early 2019)
410
+			ExportRefDeprecated:   legacyExportRef,
411
+			ExportAttrsDeprecated: legacyExportAttrs,
412
+			ImportRefsDeprecated:  legacyImportRefs,
413
+			// new API
414
+			Exports: cacheExports,
415
+			Imports: cacheImports,
416
+		},
417
+		contentStores:   contentStores,
418
+		indicesToUpdate: indicesToUpdate,
419
+		frontendAttrs:   frontendAttrs,
420
+	}
421
+	return &res, nil
422
+}
... ...
@@ -5,7 +5,6 @@ import (
5 5
 	"sync"
6 6
 	"time"
7 7
 
8
-	"github.com/docker/distribution/reference"
9 8
 	controlapi "github.com/moby/buildkit/api/services/control"
10 9
 	apitypes "github.com/moby/buildkit/api/types"
11 10
 	"github.com/moby/buildkit/cache/remotecache"
... ...
@@ -26,15 +25,13 @@ import (
26 26
 	"google.golang.org/grpc"
27 27
 )
28 28
 
29
-type ResolveCacheExporterFunc func(ctx context.Context, typ, target string) (remotecache.Exporter, error)
30
-
31 29
 type Opt struct {
32
-	SessionManager           *session.Manager
33
-	WorkerController         *worker.Controller
34
-	Frontends                map[string]frontend.Frontend
35
-	CacheKeyStorage          solver.CacheKeyStorage
36
-	ResolveCacheExporterFunc remotecache.ResolveCacheExporterFunc
37
-	ResolveCacheImporterFunc remotecache.ResolveCacheImporterFunc
30
+	SessionManager            *session.Manager
31
+	WorkerController          *worker.Controller
32
+	Frontends                 map[string]frontend.Frontend
33
+	CacheKeyStorage           solver.CacheKeyStorage
34
+	ResolveCacheExporterFuncs map[string]remotecache.ResolveCacheExporterFunc
35
+	ResolveCacheImporterFuncs map[string]remotecache.ResolveCacheImporterFunc
38 36
 }
39 37
 
40 38
 type Controller struct { // TODO: ControlService
... ...
@@ -51,7 +48,7 @@ func NewController(opt Opt) (*Controller, error) {
51 51
 
52 52
 	gatewayForwarder := controlgateway.NewGatewayForwarder()
53 53
 
54
-	solver, err := llbsolver.New(opt.WorkerController, opt.Frontends, cache, opt.ResolveCacheImporterFunc, gatewayForwarder)
54
+	solver, err := llbsolver.New(opt.WorkerController, opt.Frontends, cache, opt.ResolveCacheImporterFuncs, gatewayForwarder, opt.SessionManager)
55 55
 	if err != nil {
56 56
 		return nil, errors.Wrap(err, "failed to create solver")
57 57
 	}
... ...
@@ -179,7 +176,39 @@ func (c *Controller) Prune(req *controlapi.PruneRequest, stream controlapi.Contr
179 179
 	return eg2.Wait()
180 180
 }
181 181
 
182
+func translateLegacySolveRequest(req *controlapi.SolveRequest) error {
183
+	// translates ExportRef and ExportAttrs to new Exports (v0.4.0)
184
+	if legacyExportRef := req.Cache.ExportRefDeprecated; legacyExportRef != "" {
185
+		ex := &controlapi.CacheOptionsEntry{
186
+			Type:  "registry",
187
+			Attrs: req.Cache.ExportAttrsDeprecated,
188
+		}
189
+		if ex.Attrs == nil {
190
+			ex.Attrs = make(map[string]string)
191
+		}
192
+		ex.Attrs["ref"] = legacyExportRef
193
+		// FIXME(AkihiroSuda): skip append if already exists
194
+		req.Cache.Exports = append(req.Cache.Exports, ex)
195
+		req.Cache.ExportRefDeprecated = ""
196
+		req.Cache.ExportAttrsDeprecated = nil
197
+	}
198
+	// translates ImportRefs to new Imports (v0.4.0)
199
+	for _, legacyImportRef := range req.Cache.ImportRefsDeprecated {
200
+		im := &controlapi.CacheOptionsEntry{
201
+			Type:  "registry",
202
+			Attrs: map[string]string{"ref": legacyImportRef},
203
+		}
204
+		// FIXME(AkihiroSuda): skip append if already exists
205
+		req.Cache.Imports = append(req.Cache.Imports, im)
206
+	}
207
+	req.Cache.ImportRefsDeprecated = nil
208
+	return nil
209
+}
210
+
182 211
 func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (*controlapi.SolveResponse, error) {
212
+	if err := translateLegacySolveRequest(req); err != nil {
213
+		return nil, err
214
+	}
183 215
 	ctx = session.NewContext(ctx, req.Session)
184 216
 
185 217
 	defer func() {
... ...
@@ -194,7 +223,7 @@ func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (*
194 194
 		return nil, err
195 195
 	}
196 196
 	if req.Exporter != "" {
197
-		exp, err := w.Exporter(req.Exporter)
197
+		exp, err := w.Exporter(req.Exporter, c.opt.SessionManager)
198 198
 		if err != nil {
199 199
 			return nil, err
200 200
 		}
... ...
@@ -204,38 +233,44 @@ func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (*
204 204
 		}
205 205
 	}
206 206
 
207
-	var cacheExporter remotecache.Exporter
208
-	if ref := req.Cache.ExportRef; ref != "" && c.opt.ResolveCacheExporterFunc != nil {
209
-		parsed, err := reference.ParseNormalizedNamed(ref)
210
-		if err != nil {
211
-			return nil, err
212
-		}
213
-		exportCacheRef := reference.TagNameOnly(parsed).String()
214
-		typ := "" // unimplemented yet (typically registry)
215
-		cacheExporter, err = c.opt.ResolveCacheExporterFunc(ctx, typ, exportCacheRef)
216
-		if err != nil {
217
-			return nil, err
218
-		}
207
+	var (
208
+		cacheExporter   remotecache.Exporter
209
+		cacheExportMode solver.CacheExportMode
210
+		cacheImports    []frontend.CacheOptionsEntry
211
+	)
212
+	if len(req.Cache.Exports) > 1 {
213
+		// TODO(AkihiroSuda): this should be fairly easy
214
+		return nil, errors.New("specifying multiple cache exports is not supported currently")
219 215
 	}
220 216
 
221
-	var importCacheRefs []string
222
-	for _, ref := range req.Cache.ImportRefs {
223
-		parsed, err := reference.ParseNormalizedNamed(ref)
217
+	if len(req.Cache.Exports) == 1 {
218
+		e := req.Cache.Exports[0]
219
+		cacheExporterFunc, ok := c.opt.ResolveCacheExporterFuncs[e.Type]
220
+		if !ok {
221
+			return nil, errors.Errorf("unknown cache exporter: %q", e.Type)
222
+		}
223
+		cacheExporter, err = cacheExporterFunc(ctx, e.Attrs)
224 224
 		if err != nil {
225 225
 			return nil, err
226 226
 		}
227
-		importCacheRefs = append(importCacheRefs, reference.TagNameOnly(parsed).String())
227
+		cacheExportMode = parseCacheExportMode(e.Attrs["mode"])
228
+	}
229
+	for _, im := range req.Cache.Imports {
230
+		cacheImports = append(cacheImports, frontend.CacheOptionsEntry{
231
+			Type:  im.Type,
232
+			Attrs: im.Attrs,
233
+		})
228 234
 	}
229 235
 
230 236
 	resp, err := c.solver.Solve(ctx, req.Ref, frontend.SolveRequest{
231
-		Frontend:        req.Frontend,
232
-		Definition:      req.Definition,
233
-		FrontendOpt:     req.FrontendAttrs,
234
-		ImportCacheRefs: importCacheRefs,
237
+		Frontend:     req.Frontend,
238
+		Definition:   req.Definition,
239
+		FrontendOpt:  req.FrontendAttrs,
240
+		CacheImports: cacheImports,
235 241
 	}, llbsolver.ExporterRequest{
236 242
 		Exporter:        expi,
237 243
 		CacheExporter:   cacheExporter,
238
-		CacheExportMode: parseCacheExporterOpt(req.Cache.ExportAttrs),
244
+		CacheExportMode: cacheExportMode,
239 245
 	}, req.Entitlements)
240 246
 	if err != nil {
241 247
 		return nil, err
... ...
@@ -376,21 +411,15 @@ func (c *Controller) gc() {
376 376
 	}
377 377
 }
378 378
 
379
-func parseCacheExporterOpt(opt map[string]string) solver.CacheExportMode {
380
-	for k, v := range opt {
381
-		switch k {
382
-		case "mode":
383
-			switch v {
384
-			case "min":
385
-				return solver.CacheExportModeMin
386
-			case "max":
387
-				return solver.CacheExportModeMax
388
-			default:
389
-				logrus.Debugf("skipping incalid cache export mode: %s", v)
390
-			}
391
-		default:
392
-			logrus.Warnf("skipping invalid cache export opt: %s", v)
393
-		}
379
+func parseCacheExportMode(mode string) solver.CacheExportMode {
380
+	switch mode {
381
+	case "min":
382
+		return solver.CacheExportModeMin
383
+	case "max":
384
+		return solver.CacheExportModeMax
385
+	case "":
386
+	default:
387
+		logrus.Debugf("skipping invalid cache export mode: %s", mode)
394 388
 	}
395 389
 	return solver.CacheExportModeMin
396 390
 }
... ...
@@ -2,16 +2,19 @@ package oci
2 2
 
3 3
 import (
4 4
 	"context"
5
+	"path/filepath"
6
+	"strings"
5 7
 
6 8
 	specs "github.com/opencontainers/runtime-spec/specs-go"
9
+	"github.com/pkg/errors"
7 10
 )
8 11
 
9 12
 // MountOpts sets oci spec specific info for mount points
10
-type MountOpts func([]specs.Mount) []specs.Mount
13
+type MountOpts func([]specs.Mount) ([]specs.Mount, error)
11 14
 
12 15
 //GetMounts returns default required for buildkit
13 16
 // https://github.com/moby/buildkit/issues/429
14
-func GetMounts(ctx context.Context, mountOpts ...MountOpts) []specs.Mount {
17
+func GetMounts(ctx context.Context, mountOpts ...MountOpts) ([]specs.Mount, error) {
15 18
 	mounts := []specs.Mount{
16 19
 		{
17 20
 			Destination: "/proc",
... ...
@@ -49,20 +52,66 @@ func GetMounts(ctx context.Context, mountOpts ...MountOpts) []specs.Mount {
49 49
 			Options:     []string{"nosuid", "noexec", "nodev", "ro"},
50 50
 		},
51 51
 	}
52
+	var err error
52 53
 	for _, o := range mountOpts {
53
-		mounts = o(mounts)
54
+		mounts, err = o(mounts)
55
+		if err != nil {
56
+			return nil, err
57
+		}
54 58
 	}
55
-	return mounts
59
+	return mounts, nil
56 60
 }
57 61
 
58
-func withROBind(src, dest string) func(m []specs.Mount) []specs.Mount {
59
-	return func(m []specs.Mount) []specs.Mount {
62
+func withROBind(src, dest string) func(m []specs.Mount) ([]specs.Mount, error) {
63
+	return func(m []specs.Mount) ([]specs.Mount, error) {
60 64
 		m = append(m, specs.Mount{
61 65
 			Destination: dest,
62 66
 			Type:        "bind",
63 67
 			Source:      src,
64 68
 			Options:     []string{"rbind", "ro"},
65 69
 		})
66
-		return m
70
+		return m, nil
71
+	}
72
+}
73
+
74
+func hasPrefix(p, prefixDir string) bool {
75
+	prefixDir = filepath.Clean(prefixDir)
76
+	if prefixDir == "/" {
77
+		return true
78
+	}
79
+	p = filepath.Clean(p)
80
+	return p == prefixDir || strings.HasPrefix(p, prefixDir+"/")
81
+}
82
+
83
+func removeMountsWithPrefix(mounts []specs.Mount, prefixDir string) []specs.Mount {
84
+	var ret []specs.Mount
85
+	for _, m := range mounts {
86
+		if !hasPrefix(m.Destination, prefixDir) {
87
+			ret = append(ret, m)
88
+		}
89
+	}
90
+	return ret
91
+}
92
+
93
+func withProcessMode(processMode ProcessMode) func([]specs.Mount) ([]specs.Mount, error) {
94
+	return func(m []specs.Mount) ([]specs.Mount, error) {
95
+		switch processMode {
96
+		case ProcessSandbox:
97
+			// keep the default
98
+		case NoProcessSandbox:
99
+			m = removeMountsWithPrefix(m, "/proc")
100
+			procMount := specs.Mount{
101
+				Destination: "/proc",
102
+				Type:        "bind",
103
+				Source:      "/proc",
104
+				// NOTE: "rbind"+"ro" does not make /proc read-only recursively.
105
+				// So we keep maskedPath and readonlyPaths (although not mandatory for rootless mode)
106
+				Options: []string{"rbind"},
107
+			}
108
+			m = append([]specs.Mount{procMount}, m...)
109
+		default:
110
+			return nil, errors.Errorf("unknown process mode: %v", processMode)
111
+		}
112
+		return m, nil
67 113
 	}
68 114
 }
... ...
@@ -22,8 +22,21 @@ import (
22 22
 
23 23
 // Ideally we don't have to import whole containerd just for the default spec
24 24
 
25
+// ProcMode configures PID namespaces
26
+type ProcessMode int
27
+
28
+const (
29
+	// ProcessSandbox unshares pidns and mount procfs.
30
+	ProcessSandbox ProcessMode = iota
31
+	// NoProcessSandbox uses host pidns and bind-mount procfs.
32
+	// Note that NoProcessSandbox allows build containers to kill (and potentially ptrace) an arbitrary process in the BuildKit host namespace.
33
+	// NoProcessSandbox should be enabled only when the BuildKit is running in a container as an unprivileged user.
34
+	NoProcessSandbox
35
+)
36
+
25 37
 // GenerateSpec generates spec using containerd functionality.
26
-func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
38
+// opts are ignored for s.Process, s.Hostname, and s.Mounts .
39
+func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, processMode ProcessMode, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
27 40
 	c := &containers.Container{
28 41
 		ID: id,
29 42
 	}
... ...
@@ -32,6 +45,14 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou
32 32
 		ctx = namespaces.WithNamespace(ctx, "buildkit")
33 33
 	}
34 34
 
35
+	switch processMode {
36
+	case NoProcessSandbox:
37
+		// Mount for /proc is replaced in GetMounts()
38
+		opts = append(opts,
39
+			oci.WithHostNamespace(specs.PIDNamespace))
40
+		// TODO(AkihiroSuda): Configure seccomp to disable ptrace (and prctl?) explicitly
41
+	}
42
+
35 43
 	// Note that containerd.GenerateSpec is namespaced so as to make
36 44
 	// specs.Linux.CgroupsPath namespaced
37 45
 	s, err := oci.GenerateSpec(ctx, nil, c, opts...)
... ...
@@ -48,10 +69,14 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou
48 48
 	s.Process.NoNewPrivileges = false // reset nonewprivileges
49 49
 	s.Hostname = "buildkitsandbox"
50 50
 
51
-	s.Mounts = GetMounts(ctx,
51
+	s.Mounts, err = GetMounts(ctx,
52
+		withProcessMode(processMode),
52 53
 		withROBind(resolvConf, "/etc/resolv.conf"),
53 54
 		withROBind(hostsFile, "/etc/hosts"),
54 55
 	)
56
+	if err != nil {
57
+		return nil, nil, err
58
+	}
55 59
 
56 60
 	s.Mounts = append(s.Mounts, specs.Mount{
57 61
 		Destination: "/sys/fs/cgroup",
... ...
@@ -39,6 +39,8 @@ type Opt struct {
39 39
 	Rootless bool
40 40
 	// DefaultCgroupParent is the cgroup-parent name for executor
41 41
 	DefaultCgroupParent string
42
+	// ProcessMode
43
+	ProcessMode oci.ProcessMode
42 44
 }
43 45
 
44 46
 var defaultCommandCandidates = []string{"buildkit-runc", "runc"}
... ...
@@ -50,6 +52,7 @@ type runcExecutor struct {
50 50
 	cgroupParent     string
51 51
 	rootless         bool
52 52
 	networkProviders map[pb.NetMode]network.Provider
53
+	processMode      oci.ProcessMode
53 54
 }
54 55
 
55 56
 func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Executor, error) {
... ...
@@ -105,6 +108,7 @@ func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Ex
105 105
 		cgroupParent:     opt.DefaultCgroupParent,
106 106
 		rootless:         opt.Rootless,
107 107
 		networkProviders: networkProviders,
108
+		processMode:      opt.ProcessMode,
108 109
 	}
109 110
 	return w, nil
110 111
 }
... ...
@@ -193,7 +197,7 @@ func (w *runcExecutor) Exec(ctx context.Context, meta executor.Meta, root cache.
193 193
 		}
194 194
 		opts = append(opts, containerdoci.WithCgroup(cgroupsPath))
195 195
 	}
196
-	spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, opts...)
196
+	spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, w.processMode, opts...)
197 197
 	if err != nil {
198 198
 		return err
199 199
 	}
... ...
@@ -3,6 +3,7 @@ package exptypes
3 3
 import specs "github.com/opencontainers/image-spec/specs-go/v1"
4 4
 
5 5
 const ExporterImageConfigKey = "containerimage.config"
6
+const ExporterInlineCache = "containerimage.inlinecache"
6 7
 const ExporterPlatformsKey = "refs.platforms"
7 8
 
8 9
 type Platforms struct {
9 10
new file mode 100644
... ...
@@ -0,0 +1,148 @@
0
+package local
1
+
2
+import (
3
+	"context"
4
+	"io/ioutil"
5
+	"os"
6
+	"strings"
7
+	"time"
8
+
9
+	"github.com/moby/buildkit/cache"
10
+	"github.com/moby/buildkit/exporter"
11
+	"github.com/moby/buildkit/session"
12
+	"github.com/moby/buildkit/session/filesync"
13
+	"github.com/moby/buildkit/snapshot"
14
+	"github.com/moby/buildkit/util/progress"
15
+	"github.com/pkg/errors"
16
+	"github.com/tonistiigi/fsutil"
17
+	fstypes "github.com/tonistiigi/fsutil/types"
18
+	"golang.org/x/sync/errgroup"
19
+	"golang.org/x/time/rate"
20
+)
21
+
22
+type Opt struct {
23
+	SessionManager *session.Manager
24
+}
25
+
26
+type localExporter struct {
27
+	opt Opt
28
+	// session manager
29
+}
30
+
31
+func New(opt Opt) (exporter.Exporter, error) {
32
+	le := &localExporter{opt: opt}
33
+	return le, nil
34
+}
35
+
36
+func (e *localExporter) Resolve(ctx context.Context, opt map[string]string) (exporter.ExporterInstance, error) {
37
+	id := session.FromContext(ctx)
38
+	if id == "" {
39
+		return nil, errors.New("could not access local files without session")
40
+	}
41
+
42
+	timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
43
+	defer cancel()
44
+
45
+	caller, err := e.opt.SessionManager.Get(timeoutCtx, id)
46
+	if err != nil {
47
+		return nil, err
48
+	}
49
+
50
+	li := &localExporterInstance{localExporter: e, caller: caller}
51
+	return li, nil
52
+}
53
+
54
+type localExporterInstance struct {
55
+	*localExporter
56
+	caller session.Caller
57
+}
58
+
59
+func (e *localExporterInstance) Name() string {
60
+	return "exporting to client"
61
+}
62
+
63
+func (e *localExporterInstance) Export(ctx context.Context, inp exporter.Source) (map[string]string, error) {
64
+	isMap := len(inp.Refs) > 0
65
+
66
+	export := func(ctx context.Context, k string, ref cache.ImmutableRef) func() error {
67
+		return func() error {
68
+			var src string
69
+			var err error
70
+			if ref == nil {
71
+				src, err = ioutil.TempDir("", "buildkit")
72
+				if err != nil {
73
+					return err
74
+				}
75
+				defer os.RemoveAll(src)
76
+			} else {
77
+				mount, err := ref.Mount(ctx, true)
78
+				if err != nil {
79
+					return err
80
+				}
81
+
82
+				lm := snapshot.LocalMounter(mount)
83
+
84
+				src, err = lm.Mount()
85
+				if err != nil {
86
+					return err
87
+				}
88
+				defer lm.Unmount()
89
+			}
90
+
91
+			fs := fsutil.NewFS(src, nil)
92
+			lbl := "copying files"
93
+			if isMap {
94
+				lbl += " " + k
95
+				fs = fsutil.SubDirFS(fs, fstypes.Stat{
96
+					Mode: uint32(os.ModeDir | 0755),
97
+					Path: strings.Replace(k, "/", "_", -1),
98
+				})
99
+			}
100
+
101
+			progress := newProgressHandler(ctx, lbl)
102
+			if err := filesync.CopyToCaller(ctx, fs, e.caller, progress); err != nil {
103
+				return err
104
+			}
105
+			return nil
106
+		}
107
+	}
108
+
109
+	eg, ctx := errgroup.WithContext(ctx)
110
+
111
+	if isMap {
112
+		for k, ref := range inp.Refs {
113
+			eg.Go(export(ctx, k, ref))
114
+		}
115
+	} else {
116
+		eg.Go(export(ctx, "", inp.Ref))
117
+	}
118
+
119
+	if err := eg.Wait(); err != nil {
120
+		return nil, err
121
+	}
122
+	return nil, nil
123
+}
124
+
125
+func newProgressHandler(ctx context.Context, id string) func(int, bool) {
126
+	limiter := rate.NewLimiter(rate.Every(100*time.Millisecond), 1)
127
+	pw, _, _ := progress.FromContext(ctx)
128
+	now := time.Now()
129
+	st := progress.Status{
130
+		Started: &now,
131
+		Action:  "transferring",
132
+	}
133
+	pw.Write(id, st)
134
+	return func(s int, last bool) {
135
+		if last || limiter.Allow() {
136
+			st.Current = s
137
+			if last {
138
+				now := time.Now()
139
+				st.Completed = &now
140
+			}
141
+			pw.Write(id, st)
142
+			if last {
143
+				pw.Close()
144
+			}
145
+		}
146
+	}
147
+}
... ...
@@ -14,6 +14,7 @@ import (
14 14
 
15 15
 	"github.com/containerd/containerd/platforms"
16 16
 	"github.com/docker/docker/builder/dockerignore"
17
+	controlapi "github.com/moby/buildkit/api/services/control"
17 18
 	"github.com/moby/buildkit/client/llb"
18 19
 	"github.com/moby/buildkit/exporter/containerimage/exptypes"
19 20
 	"github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb"
... ...
@@ -25,22 +26,25 @@ import (
25 25
 )
26 26
 
27 27
 const (
28
-	LocalNameContext      = "context"
29
-	LocalNameDockerfile   = "dockerfile"
30
-	keyTarget             = "target"
31
-	keyFilename           = "filename"
32
-	keyCacheFrom          = "cache-from"
33
-	defaultDockerfileName = "Dockerfile"
34
-	dockerignoreFilename  = ".dockerignore"
35
-	buildArgPrefix        = "build-arg:"
36
-	labelPrefix           = "label:"
37
-	keyNoCache            = "no-cache"
38
-	keyTargetPlatform     = "platform"
39
-	keyMultiPlatform      = "multi-platform"
40
-	keyImageResolveMode   = "image-resolve-mode"
41
-	keyGlobalAddHosts     = "add-hosts"
42
-	keyForceNetwork       = "force-network-mode"
43
-	keyOverrideCopyImage  = "override-copy-image" // remove after CopyOp implemented
28
+	DefaultLocalNameContext    = "context"
29
+	DefaultLocalNameDockerfile = "dockerfile"
30
+	keyTarget                  = "target"
31
+	keyFilename                = "filename"
32
+	keyCacheFrom               = "cache-from"    // for registry only. deprecated in favor of keyCacheImports
33
+	keyCacheImports            = "cache-imports" // JSON representation of []CacheOptionsEntry
34
+	defaultDockerfileName      = "Dockerfile"
35
+	dockerignoreFilename       = ".dockerignore"
36
+	buildArgPrefix             = "build-arg:"
37
+	labelPrefix                = "label:"
38
+	keyNoCache                 = "no-cache"
39
+	keyTargetPlatform          = "platform"
40
+	keyMultiPlatform           = "multi-platform"
41
+	keyImageResolveMode        = "image-resolve-mode"
42
+	keyGlobalAddHosts          = "add-hosts"
43
+	keyForceNetwork            = "force-network-mode"
44
+	keyOverrideCopyImage       = "override-copy-image" // remove after CopyOp implemented
45
+	keyNameContext             = "contextkey"
46
+	keyNameDockerfile          = "dockerfilekey"
44 47
 )
45 48
 
46 49
 var httpPrefix = regexp.MustCompile("^https?://")
... ...
@@ -52,6 +56,16 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
52 52
 
53 53
 	marshalOpts := []llb.ConstraintsOpt{llb.WithCaps(caps)}
54 54
 
55
+	localNameContext := DefaultLocalNameContext
56
+	if v, ok := opts[keyNameContext]; ok {
57
+		localNameContext = v
58
+	}
59
+
60
+	localNameDockerfile := DefaultLocalNameDockerfile
61
+	if v, ok := opts[keyNameDockerfile]; ok {
62
+		localNameDockerfile = v
63
+	}
64
+
55 65
 	defaultBuildPlatform := platforms.DefaultSpec()
56 66
 	if workers := c.BuildOpts().Workers; len(workers) > 0 && len(workers[0].Platforms) > 0 {
57 67
 		defaultBuildPlatform = workers[0].Platforms[0]
... ...
@@ -98,19 +112,19 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
98 98
 
99 99
 	name := "load build definition from " + filename
100 100
 
101
-	src := llb.Local(LocalNameDockerfile,
101
+	src := llb.Local(localNameDockerfile,
102 102
 		llb.FollowPaths([]string{filename}),
103 103
 		llb.SessionID(c.BuildOpts().SessionID),
104
-		llb.SharedKeyHint(defaultDockerfileName),
104
+		llb.SharedKeyHint(localNameDockerfile),
105 105
 		dockerfile2llb.WithInternalName(name),
106 106
 	)
107 107
 	var buildContext *llb.State
108 108
 	isScratchContext := false
109
-	if st, ok := detectGitContext(opts[LocalNameContext]); ok {
109
+	if st, ok := detectGitContext(opts[localNameContext]); ok {
110 110
 		src = *st
111 111
 		buildContext = &src
112
-	} else if httpPrefix.MatchString(opts[LocalNameContext]) {
113
-		httpContext := llb.HTTP(opts[LocalNameContext], llb.Filename("context"), dockerfile2llb.WithInternalName("load remote build context"))
112
+	} else if httpPrefix.MatchString(opts[localNameContext]) {
113
+		httpContext := llb.HTTP(opts[localNameContext], llb.Filename("context"), dockerfile2llb.WithInternalName("load remote build context"))
114 114
 		def, err := httpContext.Marshal(marshalOpts...)
115 115
 		if err != nil {
116 116
 			return nil, errors.Wrapf(err, "failed to marshal httpcontext")
... ...
@@ -187,10 +201,10 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
187 187
 		eg.Go(func() error {
188 188
 			dockerignoreState := buildContext
189 189
 			if dockerignoreState == nil {
190
-				st := llb.Local(LocalNameContext,
190
+				st := llb.Local(localNameContext,
191 191
 					llb.SessionID(c.BuildOpts().SessionID),
192 192
 					llb.FollowPaths([]string{dockerignoreFilename}),
193
-					llb.SharedKeyHint(dockerignoreFilename),
193
+					llb.SharedKeyHint(localNameContext+"-"+dockerignoreFilename),
194 194
 					dockerfile2llb.WithInternalName("load "+dockerignoreFilename),
195 195
 				)
196 196
 				dockerignoreState = &st
... ...
@@ -289,14 +303,35 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
289 289
 					return errors.Wrapf(err, "failed to marshal image config")
290 290
 				}
291 291
 
292
-				var cacheFrom []string
292
+				var cacheImports []client.CacheOptionsEntry
293
+				// new API
294
+				if cacheImportsStr := opts[keyCacheImports]; cacheImportsStr != "" {
295
+					var cacheImportsUM []controlapi.CacheOptionsEntry
296
+					if err := json.Unmarshal([]byte(cacheImportsStr), &cacheImportsUM); err != nil {
297
+						return errors.Wrapf(err, "failed to unmarshal %s (%q)", keyCacheImports, cacheImportsStr)
298
+					}
299
+					for _, um := range cacheImportsUM {
300
+						cacheImports = append(cacheImports, client.CacheOptionsEntry{Type: um.Type, Attrs: um.Attrs})
301
+					}
302
+				}
303
+				// old API
293 304
 				if cacheFromStr := opts[keyCacheFrom]; cacheFromStr != "" {
294
-					cacheFrom = strings.Split(cacheFromStr, ",")
305
+					cacheFrom := strings.Split(cacheFromStr, ",")
306
+					for _, s := range cacheFrom {
307
+						im := client.CacheOptionsEntry{
308
+							Type: "registry",
309
+							Attrs: map[string]string{
310
+								"ref": s,
311
+							},
312
+						}
313
+						// FIXME(AkihiroSuda): skip append if already exists
314
+						cacheImports = append(cacheImports, im)
315
+					}
295 316
 				}
296 317
 
297 318
 				r, err := c.Solve(ctx, client.SolveRequest{
298
-					Definition:      def.ToPB(),
299
-					ImportCacheRefs: cacheFrom,
319
+					Definition:   def.ToPB(),
320
+					CacheImports: cacheImports,
300 321
 				})
301 322
 				if err != nil {
302 323
 					return err
... ...
@@ -31,9 +31,9 @@ import (
31 31
 )
32 32
 
33 33
 const (
34
-	emptyImageName   = "scratch"
35
-	localNameContext = "context"
36
-	historyComment   = "buildkit.dockerfile.v0"
34
+	emptyImageName          = "scratch"
35
+	defaultContextLocalName = "context"
36
+	historyComment          = "buildkit.dockerfile.v0"
37 37
 
38 38
 	DefaultCopyImage = "docker/dockerfile-copy:v0.1.9@sha256:e8f159d3f00786604b93c675ee2783f8dc194bb565e61ca5788f6a6e9d304061"
39 39
 )
... ...
@@ -59,6 +59,7 @@ type ConvertOpt struct {
59 59
 	ForceNetMode      pb.NetMode
60 60
 	OverrideCopyImage string
61 61
 	LLBCaps           *apicaps.CapSet
62
+	ContextLocalName  string
62 63
 }
63 64
 
64 65
 func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, *Image, error) {
... ...
@@ -66,6 +67,10 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
66 66
 		return nil, nil, errors.Errorf("the Dockerfile cannot be empty")
67 67
 	}
68 68
 
69
+	if opt.ContextLocalName == "" {
70
+		opt.ContextLocalName = defaultContextLocalName
71
+	}
72
+
69 73
 	platformOpt := buildPlatformOpt(&opt)
70 74
 
71 75
 	optMetaArgs := getPlatformArgs(platformOpt)
... ...
@@ -357,14 +362,14 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
357 357
 	opts := []llb.LocalOption{
358 358
 		llb.SessionID(opt.SessionID),
359 359
 		llb.ExcludePatterns(opt.Excludes),
360
-		llb.SharedKeyHint(localNameContext),
360
+		llb.SharedKeyHint(opt.ContextLocalName),
361 361
 		WithInternalName("load build context"),
362 362
 	}
363 363
 	if includePatterns := normalizeContextPaths(ctxPaths); includePatterns != nil {
364 364
 		opts = append(opts, llb.FollowPaths(includePatterns))
365 365
 	}
366 366
 
367
-	bc := llb.Local(localNameContext, opts...)
367
+	bc := llb.Local(opt.ContextLocalName, opts...)
368 368
 	if opt.BuildContext != nil {
369 369
 		bc = *opt.BuildContext
370 370
 	}
... ...
@@ -1138,8 +1143,8 @@ func autoDetectPlatform(img Image, target specs.Platform, supported []specs.Plat
1138 1138
 	return target
1139 1139
 }
1140 1140
 
1141
-func WithInternalName(name string, a ...interface{}) llb.ConstraintsOpt {
1142
-	return llb.WithCustomName("[internal] "+name, a...)
1141
+func WithInternalName(name string) llb.ConstraintsOpt {
1142
+	return llb.WithCustomName("[internal] " + name)
1143 1143
 }
1144 1144
 
1145 1145
 func uppercaseCmd(str string) string {
... ...
@@ -23,6 +23,8 @@ type FrontendLLBBridge interface {
23 23
 
24 24
 type SolveRequest = gw.SolveRequest
25 25
 
26
+type CacheOptionsEntry = gw.CacheOptionsEntry
27
+
26 28
 type WorkerInfos interface {
27 29
 	WorkerInfos() []client.WorkerInfo
28 30
 }
... ...
@@ -43,10 +43,15 @@ type StatRequest struct {
43 43
 
44 44
 // SolveRequest is same as frontend.SolveRequest but avoiding dependency
45 45
 type SolveRequest struct {
46
-	Definition      *pb.Definition
47
-	Frontend        string
48
-	FrontendOpt     map[string]string
49
-	ImportCacheRefs []string
46
+	Definition   *pb.Definition
47
+	Frontend     string
48
+	FrontendOpt  map[string]string
49
+	CacheImports []CacheOptionsEntry
50
+}
51
+
52
+type CacheOptionsEntry struct {
53
+	Type  string
54
+	Attrs map[string]string
50 55
 }
51 56
 
52 57
 type WorkerInfo struct {
... ...
@@ -42,10 +42,10 @@ type bridgeClient struct {
42 42
 
43 43
 func (c *bridgeClient) Solve(ctx context.Context, req client.SolveRequest) (*client.Result, error) {
44 44
 	res, err := c.FrontendLLBBridge.Solve(ctx, frontend.SolveRequest{
45
-		Definition:      req.Definition,
46
-		Frontend:        req.Frontend,
47
-		FrontendOpt:     req.FrontendOpt,
48
-		ImportCacheRefs: req.ImportCacheRefs,
45
+		Definition:   req.Definition,
46
+		Frontend:     req.Frontend,
47
+		FrontendOpt:  req.FrontendOpt,
48
+		CacheImports: req.CacheImports,
49 49
 	})
50 50
 	if err != nil {
51 51
 		return nil, err
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"io"
8 8
 	"net"
9 9
 	"os"
10
+	"strconv"
10 11
 	"strings"
11 12
 	"sync"
12 13
 	"time"
... ...
@@ -193,12 +194,20 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
193 193
 
194 194
 	env = append(env, "BUILDKIT_EXPORTEDPRODUCT="+apicaps.ExportedProduct)
195 195
 
196
-	err = llbBridge.Exec(ctx, executor.Meta{
196
+	meta := executor.Meta{
197 197
 		Env:            env,
198 198
 		Args:           args,
199 199
 		Cwd:            cwd,
200 200
 		ReadonlyRootFS: readonly,
201
-	}, rootFS, lbf.Stdin, lbf.Stdout, os.Stderr)
201
+	}
202
+
203
+	if v, ok := img.Config.Labels["moby.buildkit.frontend.network.none"]; ok {
204
+		if ok, _ := strconv.ParseBool(v); ok {
205
+			meta.NetMode = opspb.NetMode_NONE
206
+		}
207
+	}
208
+
209
+	err = llbBridge.Exec(ctx, meta, rootFS, lbf.Stdin, lbf.Stdout, os.Stderr)
202 210
 
203 211
 	if err != nil {
204 212
 		// An existing error (set via Return rpc) takes
... ...
@@ -397,13 +406,37 @@ func (lbf *llbBridgeForwarder) ResolveImageConfig(ctx context.Context, req *pb.R
397 397
 	}, nil
398 398
 }
399 399
 
400
+func translateLegacySolveRequest(req *pb.SolveRequest) error {
401
+	// translates ImportCacheRefs to new CacheImports (v0.4.0)
402
+	for _, legacyImportRef := range req.ImportCacheRefsDeprecated {
403
+		im := &pb.CacheOptionsEntry{
404
+			Type:  "registry",
405
+			Attrs: map[string]string{"ref": legacyImportRef},
406
+		}
407
+		// FIXME(AkihiroSuda): skip append if already exists
408
+		req.CacheImports = append(req.CacheImports, im)
409
+	}
410
+	req.ImportCacheRefsDeprecated = nil
411
+	return nil
412
+}
413
+
400 414
 func (lbf *llbBridgeForwarder) Solve(ctx context.Context, req *pb.SolveRequest) (*pb.SolveResponse, error) {
415
+	if err := translateLegacySolveRequest(req); err != nil {
416
+		return nil, err
417
+	}
418
+	var cacheImports []frontend.CacheOptionsEntry
419
+	for _, e := range req.CacheImports {
420
+		cacheImports = append(cacheImports, frontend.CacheOptionsEntry{
421
+			Type:  e.Type,
422
+			Attrs: e.Attrs,
423
+		})
424
+	}
401 425
 	ctx = tracing.ContextWithSpanFromContext(ctx, lbf.callCtx)
402 426
 	res, err := lbf.llbBridge.Solve(ctx, frontend.SolveRequest{
403
-		Definition:      req.Definition,
404
-		Frontend:        req.Frontend,
405
-		FrontendOpt:     req.FrontendOpt,
406
-		ImportCacheRefs: req.ImportCacheRefs,
427
+		Definition:   req.Definition,
428
+		Frontend:     req.Frontend,
429
+		FrontendOpt:  req.FrontendOpt,
430
+		CacheImports: cacheImports,
407 431
 	})
408 432
 	if err != nil {
409 433
 		return nil, err
... ...
@@ -259,13 +259,33 @@ func (c *grpcClient) Solve(ctx context.Context, creq client.SolveRequest) (*clie
259 259
 			}
260 260
 		}
261 261
 	}
262
+	var (
263
+		// old API
264
+		legacyRegistryCacheImports []string
265
+		// new API (CapImportCaches)
266
+		cacheImports []*pb.CacheOptionsEntry
267
+	)
268
+	supportCapImportCaches := c.caps.Supports(pb.CapImportCaches) == nil
269
+	for _, im := range creq.CacheImports {
270
+		if !supportCapImportCaches && im.Type == "registry" {
271
+			legacyRegistryCacheImports = append(legacyRegistryCacheImports, im.Attrs["ref"])
272
+		} else {
273
+			cacheImports = append(cacheImports, &pb.CacheOptionsEntry{
274
+				Type:  im.Type,
275
+				Attrs: im.Attrs,
276
+			})
277
+		}
278
+	}
262 279
 
263 280
 	req := &pb.SolveRequest{
264 281
 		Definition:        creq.Definition,
265 282
 		Frontend:          creq.Frontend,
266 283
 		FrontendOpt:       creq.FrontendOpt,
267
-		ImportCacheRefs:   creq.ImportCacheRefs,
268 284
 		AllowResultReturn: true,
285
+		// old API
286
+		ImportCacheRefsDeprecated: legacyRegistryCacheImports,
287
+		// new API
288
+		CacheImports: cacheImports,
269 289
 	}
270 290
 
271 291
 	// backwards compatibility with inline return
... ...
@@ -18,6 +18,7 @@ const (
18 18
 	CapReturnMap               apicaps.CapID = "returnmap"
19 19
 	CapReadDir                 apicaps.CapID = "readdir"
20 20
 	CapStatFile                apicaps.CapID = "statfile"
21
+	CapImportCaches            apicaps.CapID = "importcaches"
21 22
 )
22 23
 
23 24
 func init() {
... ...
@@ -84,4 +85,11 @@ func init() {
84 84
 		Enabled: true,
85 85
 		Status:  apicaps.CapStatusExperimental,
86 86
 	})
87
+
88
+	Caps.Init(apicaps.Cap{
89
+		ID:      CapImportCaches,
90
+		Name:    "import caches",
91
+		Enabled: true,
92
+		Status:  apicaps.CapStatusExperimental,
93
+	})
87 94
 }
... ...
@@ -1,47 +1,24 @@
1 1
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
2 2
 // source: gateway.proto
3 3
 
4
-/*
5
-	Package moby_buildkit_v1_frontend is a generated protocol buffer package.
6
-
7
-	It is generated from these files:
8
-		gateway.proto
9
-
10
-	It has these top-level messages:
11
-		Result
12
-		RefMap
13
-		ReturnRequest
14
-		ReturnResponse
15
-		ResolveImageConfigRequest
16
-		ResolveImageConfigResponse
17
-		SolveRequest
18
-		SolveResponse
19
-		ReadFileRequest
20
-		FileRange
21
-		ReadFileResponse
22
-		ReadDirRequest
23
-		ReadDirResponse
24
-		StatFileRequest
25
-		StatFileResponse
26
-		PingRequest
27
-		PongResponse
28
-*/
29 4
 package moby_buildkit_v1_frontend
30 5
 
31 6
 import proto "github.com/gogo/protobuf/proto"
32 7
 import fmt "fmt"
33 8
 import math "math"
9
+import rpc "github.com/gogo/googleapis/google/rpc"
34 10
 import _ "github.com/gogo/protobuf/gogoproto"
35
-import google_rpc "github.com/gogo/googleapis/google/rpc"
11
+import types1 "github.com/moby/buildkit/api/types"
36 12
 import pb "github.com/moby/buildkit/solver/pb"
37
-import moby_buildkit_v1_types "github.com/moby/buildkit/api/types"
38
-import moby_buildkit_v1_apicaps "github.com/moby/buildkit/util/apicaps/pb"
39
-import fsutil_types "github.com/tonistiigi/fsutil/types"
13
+import pb1 "github.com/moby/buildkit/util/apicaps/pb"
14
+import types "github.com/tonistiigi/fsutil/types"
40 15
 
41 16
 import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest"
42 17
 
43
-import context "golang.org/x/net/context"
44
-import grpc "google.golang.org/grpc"
18
+import (
19
+	context "golang.org/x/net/context"
20
+	grpc "google.golang.org/grpc"
21
+)
45 22
 
46 23
 import io "io"
47 24
 
... ...
@@ -60,14 +37,45 @@ type Result struct {
60 60
 	// Types that are valid to be assigned to Result:
61 61
 	//	*Result_Ref
62 62
 	//	*Result_Refs
63
-	Result   isResult_Result   `protobuf_oneof:"result"`
64
-	Metadata map[string][]byte `protobuf:"bytes,10,rep,name=metadata" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
63
+	Result               isResult_Result   `protobuf_oneof:"result"`
64
+	Metadata             map[string][]byte `protobuf:"bytes,10,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
65
+	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
66
+	XXX_unrecognized     []byte            `json:"-"`
67
+	XXX_sizecache        int32             `json:"-"`
68
+}
69
+
70
+func (m *Result) Reset()         { *m = Result{} }
71
+func (m *Result) String() string { return proto.CompactTextString(m) }
72
+func (*Result) ProtoMessage()    {}
73
+func (*Result) Descriptor() ([]byte, []int) {
74
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{0}
75
+}
76
+func (m *Result) XXX_Unmarshal(b []byte) error {
77
+	return m.Unmarshal(b)
78
+}
79
+func (m *Result) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
80
+	if deterministic {
81
+		return xxx_messageInfo_Result.Marshal(b, m, deterministic)
82
+	} else {
83
+		b = b[:cap(b)]
84
+		n, err := m.MarshalTo(b)
85
+		if err != nil {
86
+			return nil, err
87
+		}
88
+		return b[:n], nil
89
+	}
90
+}
91
+func (dst *Result) XXX_Merge(src proto.Message) {
92
+	xxx_messageInfo_Result.Merge(dst, src)
93
+}
94
+func (m *Result) XXX_Size() int {
95
+	return m.Size()
96
+}
97
+func (m *Result) XXX_DiscardUnknown() {
98
+	xxx_messageInfo_Result.DiscardUnknown(m)
65 99
 }
66 100
 
67
-func (m *Result) Reset()                    { *m = Result{} }
68
-func (m *Result) String() string            { return proto.CompactTextString(m) }
69
-func (*Result) ProtoMessage()               {}
70
-func (*Result) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{0} }
101
+var xxx_messageInfo_Result proto.InternalMessageInfo
71 102
 
72 103
 type isResult_Result interface {
73 104
 	isResult_Result()
... ...
@@ -79,7 +87,7 @@ type Result_Ref struct {
79 79
 	Ref string `protobuf:"bytes,1,opt,name=ref,proto3,oneof"`
80 80
 }
81 81
 type Result_Refs struct {
82
-	Refs *RefMap `protobuf:"bytes,2,opt,name=refs,oneof"`
82
+	Refs *RefMap `protobuf:"bytes,2,opt,name=refs,proto3,oneof"`
83 83
 }
84 84
 
85 85
 func (*Result_Ref) isResult_Result()  {}
... ...
@@ -168,12 +176,12 @@ func _Result_OneofSizer(msg proto.Message) (n int) {
168 168
 	// result
169 169
 	switch x := m.Result.(type) {
170 170
 	case *Result_Ref:
171
-		n += proto.SizeVarint(1<<3 | proto.WireBytes)
171
+		n += 1 // tag and wire
172 172
 		n += proto.SizeVarint(uint64(len(x.Ref)))
173 173
 		n += len(x.Ref)
174 174
 	case *Result_Refs:
175 175
 		s := proto.Size(x.Refs)
176
-		n += proto.SizeVarint(2<<3 | proto.WireBytes)
176
+		n += 1 // tag and wire
177 177
 		n += proto.SizeVarint(uint64(s))
178 178
 		n += s
179 179
 	case nil:
... ...
@@ -184,13 +192,44 @@ func _Result_OneofSizer(msg proto.Message) (n int) {
184 184
 }
185 185
 
186 186
 type RefMap struct {
187
-	Refs map[string]string `protobuf:"bytes,1,rep,name=refs" json:"refs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
187
+	Refs                 map[string]string `protobuf:"bytes,1,rep,name=refs,proto3" json:"refs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
188
+	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
189
+	XXX_unrecognized     []byte            `json:"-"`
190
+	XXX_sizecache        int32             `json:"-"`
191
+}
192
+
193
+func (m *RefMap) Reset()         { *m = RefMap{} }
194
+func (m *RefMap) String() string { return proto.CompactTextString(m) }
195
+func (*RefMap) ProtoMessage()    {}
196
+func (*RefMap) Descriptor() ([]byte, []int) {
197
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{1}
198
+}
199
+func (m *RefMap) XXX_Unmarshal(b []byte) error {
200
+	return m.Unmarshal(b)
201
+}
202
+func (m *RefMap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
203
+	if deterministic {
204
+		return xxx_messageInfo_RefMap.Marshal(b, m, deterministic)
205
+	} else {
206
+		b = b[:cap(b)]
207
+		n, err := m.MarshalTo(b)
208
+		if err != nil {
209
+			return nil, err
210
+		}
211
+		return b[:n], nil
212
+	}
213
+}
214
+func (dst *RefMap) XXX_Merge(src proto.Message) {
215
+	xxx_messageInfo_RefMap.Merge(dst, src)
216
+}
217
+func (m *RefMap) XXX_Size() int {
218
+	return m.Size()
219
+}
220
+func (m *RefMap) XXX_DiscardUnknown() {
221
+	xxx_messageInfo_RefMap.DiscardUnknown(m)
188 222
 }
189 223
 
190
-func (m *RefMap) Reset()                    { *m = RefMap{} }
191
-func (m *RefMap) String() string            { return proto.CompactTextString(m) }
192
-func (*RefMap) ProtoMessage()               {}
193
-func (*RefMap) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{1} }
224
+var xxx_messageInfo_RefMap proto.InternalMessageInfo
194 225
 
195 226
 func (m *RefMap) GetRefs() map[string]string {
196 227
 	if m != nil {
... ...
@@ -200,14 +239,45 @@ func (m *RefMap) GetRefs() map[string]string {
200 200
 }
201 201
 
202 202
 type ReturnRequest struct {
203
-	Result *Result            `protobuf:"bytes,1,opt,name=result" json:"result,omitempty"`
204
-	Error  *google_rpc.Status `protobuf:"bytes,2,opt,name=error" json:"error,omitempty"`
203
+	Result               *Result     `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"`
204
+	Error                *rpc.Status `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
205
+	XXX_NoUnkeyedLiteral struct{}    `json:"-"`
206
+	XXX_unrecognized     []byte      `json:"-"`
207
+	XXX_sizecache        int32       `json:"-"`
208
+}
209
+
210
+func (m *ReturnRequest) Reset()         { *m = ReturnRequest{} }
211
+func (m *ReturnRequest) String() string { return proto.CompactTextString(m) }
212
+func (*ReturnRequest) ProtoMessage()    {}
213
+func (*ReturnRequest) Descriptor() ([]byte, []int) {
214
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{2}
215
+}
216
+func (m *ReturnRequest) XXX_Unmarshal(b []byte) error {
217
+	return m.Unmarshal(b)
218
+}
219
+func (m *ReturnRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
220
+	if deterministic {
221
+		return xxx_messageInfo_ReturnRequest.Marshal(b, m, deterministic)
222
+	} else {
223
+		b = b[:cap(b)]
224
+		n, err := m.MarshalTo(b)
225
+		if err != nil {
226
+			return nil, err
227
+		}
228
+		return b[:n], nil
229
+	}
230
+}
231
+func (dst *ReturnRequest) XXX_Merge(src proto.Message) {
232
+	xxx_messageInfo_ReturnRequest.Merge(dst, src)
233
+}
234
+func (m *ReturnRequest) XXX_Size() int {
235
+	return m.Size()
236
+}
237
+func (m *ReturnRequest) XXX_DiscardUnknown() {
238
+	xxx_messageInfo_ReturnRequest.DiscardUnknown(m)
205 239
 }
206 240
 
207
-func (m *ReturnRequest) Reset()                    { *m = ReturnRequest{} }
208
-func (m *ReturnRequest) String() string            { return proto.CompactTextString(m) }
209
-func (*ReturnRequest) ProtoMessage()               {}
210
-func (*ReturnRequest) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{2} }
241
+var xxx_messageInfo_ReturnRequest proto.InternalMessageInfo
211 242
 
212 243
 func (m *ReturnRequest) GetResult() *Result {
213 244
 	if m != nil {
... ...
@@ -216,7 +286,7 @@ func (m *ReturnRequest) GetResult() *Result {
216 216
 	return nil
217 217
 }
218 218
 
219
-func (m *ReturnRequest) GetError() *google_rpc.Status {
219
+func (m *ReturnRequest) GetError() *rpc.Status {
220 220
 	if m != nil {
221 221
 		return m.Error
222 222
 	}
... ...
@@ -224,24 +294,86 @@ func (m *ReturnRequest) GetError() *google_rpc.Status {
224 224
 }
225 225
 
226 226
 type ReturnResponse struct {
227
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
228
+	XXX_unrecognized     []byte   `json:"-"`
229
+	XXX_sizecache        int32    `json:"-"`
230
+}
231
+
232
+func (m *ReturnResponse) Reset()         { *m = ReturnResponse{} }
233
+func (m *ReturnResponse) String() string { return proto.CompactTextString(m) }
234
+func (*ReturnResponse) ProtoMessage()    {}
235
+func (*ReturnResponse) Descriptor() ([]byte, []int) {
236
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{3}
237
+}
238
+func (m *ReturnResponse) XXX_Unmarshal(b []byte) error {
239
+	return m.Unmarshal(b)
240
+}
241
+func (m *ReturnResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
242
+	if deterministic {
243
+		return xxx_messageInfo_ReturnResponse.Marshal(b, m, deterministic)
244
+	} else {
245
+		b = b[:cap(b)]
246
+		n, err := m.MarshalTo(b)
247
+		if err != nil {
248
+			return nil, err
249
+		}
250
+		return b[:n], nil
251
+	}
252
+}
253
+func (dst *ReturnResponse) XXX_Merge(src proto.Message) {
254
+	xxx_messageInfo_ReturnResponse.Merge(dst, src)
255
+}
256
+func (m *ReturnResponse) XXX_Size() int {
257
+	return m.Size()
258
+}
259
+func (m *ReturnResponse) XXX_DiscardUnknown() {
260
+	xxx_messageInfo_ReturnResponse.DiscardUnknown(m)
227 261
 }
228 262
 
229
-func (m *ReturnResponse) Reset()                    { *m = ReturnResponse{} }
230
-func (m *ReturnResponse) String() string            { return proto.CompactTextString(m) }
231
-func (*ReturnResponse) ProtoMessage()               {}
232
-func (*ReturnResponse) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{3} }
263
+var xxx_messageInfo_ReturnResponse proto.InternalMessageInfo
233 264
 
234 265
 type ResolveImageConfigRequest struct {
235
-	Ref         string       `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
236
-	Platform    *pb.Platform `protobuf:"bytes,2,opt,name=Platform" json:"Platform,omitempty"`
237
-	ResolveMode string       `protobuf:"bytes,3,opt,name=ResolveMode,proto3" json:"ResolveMode,omitempty"`
238
-	LogName     string       `protobuf:"bytes,4,opt,name=LogName,proto3" json:"LogName,omitempty"`
266
+	Ref                  string       `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
267
+	Platform             *pb.Platform `protobuf:"bytes,2,opt,name=Platform,proto3" json:"Platform,omitempty"`
268
+	ResolveMode          string       `protobuf:"bytes,3,opt,name=ResolveMode,proto3" json:"ResolveMode,omitempty"`
269
+	LogName              string       `protobuf:"bytes,4,opt,name=LogName,proto3" json:"LogName,omitempty"`
270
+	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
271
+	XXX_unrecognized     []byte       `json:"-"`
272
+	XXX_sizecache        int32        `json:"-"`
273
+}
274
+
275
+func (m *ResolveImageConfigRequest) Reset()         { *m = ResolveImageConfigRequest{} }
276
+func (m *ResolveImageConfigRequest) String() string { return proto.CompactTextString(m) }
277
+func (*ResolveImageConfigRequest) ProtoMessage()    {}
278
+func (*ResolveImageConfigRequest) Descriptor() ([]byte, []int) {
279
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{4}
280
+}
281
+func (m *ResolveImageConfigRequest) XXX_Unmarshal(b []byte) error {
282
+	return m.Unmarshal(b)
283
+}
284
+func (m *ResolveImageConfigRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
285
+	if deterministic {
286
+		return xxx_messageInfo_ResolveImageConfigRequest.Marshal(b, m, deterministic)
287
+	} else {
288
+		b = b[:cap(b)]
289
+		n, err := m.MarshalTo(b)
290
+		if err != nil {
291
+			return nil, err
292
+		}
293
+		return b[:n], nil
294
+	}
295
+}
296
+func (dst *ResolveImageConfigRequest) XXX_Merge(src proto.Message) {
297
+	xxx_messageInfo_ResolveImageConfigRequest.Merge(dst, src)
298
+}
299
+func (m *ResolveImageConfigRequest) XXX_Size() int {
300
+	return m.Size()
301
+}
302
+func (m *ResolveImageConfigRequest) XXX_DiscardUnknown() {
303
+	xxx_messageInfo_ResolveImageConfigRequest.DiscardUnknown(m)
239 304
 }
240 305
 
241
-func (m *ResolveImageConfigRequest) Reset()                    { *m = ResolveImageConfigRequest{} }
242
-func (m *ResolveImageConfigRequest) String() string            { return proto.CompactTextString(m) }
243
-func (*ResolveImageConfigRequest) ProtoMessage()               {}
244
-func (*ResolveImageConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{4} }
306
+var xxx_messageInfo_ResolveImageConfigRequest proto.InternalMessageInfo
245 307
 
246 308
 func (m *ResolveImageConfigRequest) GetRef() string {
247 309
 	if m != nil {
... ...
@@ -272,16 +404,45 @@ func (m *ResolveImageConfigRequest) GetLogName() string {
272 272
 }
273 273
 
274 274
 type ResolveImageConfigResponse struct {
275
-	Digest github_com_opencontainers_go_digest.Digest `protobuf:"bytes,1,opt,name=Digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"Digest"`
276
-	Config []byte                                     `protobuf:"bytes,2,opt,name=Config,proto3" json:"Config,omitempty"`
275
+	Digest               github_com_opencontainers_go_digest.Digest `protobuf:"bytes,1,opt,name=Digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"Digest"`
276
+	Config               []byte                                     `protobuf:"bytes,2,opt,name=Config,proto3" json:"Config,omitempty"`
277
+	XXX_NoUnkeyedLiteral struct{}                                   `json:"-"`
278
+	XXX_unrecognized     []byte                                     `json:"-"`
279
+	XXX_sizecache        int32                                      `json:"-"`
277 280
 }
278 281
 
279 282
 func (m *ResolveImageConfigResponse) Reset()         { *m = ResolveImageConfigResponse{} }
280 283
 func (m *ResolveImageConfigResponse) String() string { return proto.CompactTextString(m) }
281 284
 func (*ResolveImageConfigResponse) ProtoMessage()    {}
282 285
 func (*ResolveImageConfigResponse) Descriptor() ([]byte, []int) {
283
-	return fileDescriptorGateway, []int{5}
286
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{5}
287
+}
288
+func (m *ResolveImageConfigResponse) XXX_Unmarshal(b []byte) error {
289
+	return m.Unmarshal(b)
290
+}
291
+func (m *ResolveImageConfigResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
292
+	if deterministic {
293
+		return xxx_messageInfo_ResolveImageConfigResponse.Marshal(b, m, deterministic)
294
+	} else {
295
+		b = b[:cap(b)]
296
+		n, err := m.MarshalTo(b)
297
+		if err != nil {
298
+			return nil, err
299
+		}
300
+		return b[:n], nil
301
+	}
302
+}
303
+func (dst *ResolveImageConfigResponse) XXX_Merge(src proto.Message) {
304
+	xxx_messageInfo_ResolveImageConfigResponse.Merge(dst, src)
305
+}
306
+func (m *ResolveImageConfigResponse) XXX_Size() int {
307
+	return m.Size()
284 308
 }
309
+func (m *ResolveImageConfigResponse) XXX_DiscardUnknown() {
310
+	xxx_messageInfo_ResolveImageConfigResponse.DiscardUnknown(m)
311
+}
312
+
313
+var xxx_messageInfo_ResolveImageConfigResponse proto.InternalMessageInfo
285 314
 
286 315
 func (m *ResolveImageConfigResponse) GetConfig() []byte {
287 316
 	if m != nil {
... ...
@@ -291,20 +452,58 @@ func (m *ResolveImageConfigResponse) GetConfig() []byte {
291 291
 }
292 292
 
293 293
 type SolveRequest struct {
294
-	Definition        *pb.Definition    `protobuf:"bytes,1,opt,name=Definition" json:"Definition,omitempty"`
295
-	Frontend          string            `protobuf:"bytes,2,opt,name=Frontend,proto3" json:"Frontend,omitempty"`
296
-	FrontendOpt       map[string]string `protobuf:"bytes,3,rep,name=FrontendOpt" json:"FrontendOpt,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
297
-	ImportCacheRefs   []string          `protobuf:"bytes,4,rep,name=ImportCacheRefs" json:"ImportCacheRefs,omitempty"`
298
-	AllowResultReturn bool              `protobuf:"varint,5,opt,name=allowResultReturn,proto3" json:"allowResultReturn,omitempty"`
294
+	Definition  *pb.Definition    `protobuf:"bytes,1,opt,name=Definition,proto3" json:"Definition,omitempty"`
295
+	Frontend    string            `protobuf:"bytes,2,opt,name=Frontend,proto3" json:"Frontend,omitempty"`
296
+	FrontendOpt map[string]string `protobuf:"bytes,3,rep,name=FrontendOpt,proto3" json:"FrontendOpt,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
297
+	// ImportCacheRefsDeprecated is deprecated in favor or the new Imports since BuildKit v0.4.0.
298
+	// When ImportCacheRefsDeprecated is set, the solver appends
299
+	// {.Type = "registry", .Attrs = {"ref": importCacheRef}}
300
+	// for each of the ImportCacheRefs entry to CacheImports for compatibility. (planned to be removed)
301
+	ImportCacheRefsDeprecated []string `protobuf:"bytes,4,rep,name=ImportCacheRefsDeprecated,proto3" json:"ImportCacheRefsDeprecated,omitempty"`
302
+	AllowResultReturn         bool     `protobuf:"varint,5,opt,name=allowResultReturn,proto3" json:"allowResultReturn,omitempty"`
299 303
 	// apicaps.CapSolveInlineReturn deprecated
300 304
 	Final        bool   `protobuf:"varint,10,opt,name=Final,proto3" json:"Final,omitempty"`
301 305
 	ExporterAttr []byte `protobuf:"bytes,11,opt,name=ExporterAttr,proto3" json:"ExporterAttr,omitempty"`
306
+	// CacheImports was added in BuildKit v0.4.0.
307
+	// apicaps:CapImportCaches
308
+	CacheImports         []*CacheOptionsEntry `protobuf:"bytes,12,rep,name=CacheImports,proto3" json:"CacheImports,omitempty"`
309
+	XXX_NoUnkeyedLiteral struct{}             `json:"-"`
310
+	XXX_unrecognized     []byte               `json:"-"`
311
+	XXX_sizecache        int32                `json:"-"`
312
+}
313
+
314
+func (m *SolveRequest) Reset()         { *m = SolveRequest{} }
315
+func (m *SolveRequest) String() string { return proto.CompactTextString(m) }
316
+func (*SolveRequest) ProtoMessage()    {}
317
+func (*SolveRequest) Descriptor() ([]byte, []int) {
318
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{6}
319
+}
320
+func (m *SolveRequest) XXX_Unmarshal(b []byte) error {
321
+	return m.Unmarshal(b)
322
+}
323
+func (m *SolveRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
324
+	if deterministic {
325
+		return xxx_messageInfo_SolveRequest.Marshal(b, m, deterministic)
326
+	} else {
327
+		b = b[:cap(b)]
328
+		n, err := m.MarshalTo(b)
329
+		if err != nil {
330
+			return nil, err
331
+		}
332
+		return b[:n], nil
333
+	}
334
+}
335
+func (dst *SolveRequest) XXX_Merge(src proto.Message) {
336
+	xxx_messageInfo_SolveRequest.Merge(dst, src)
337
+}
338
+func (m *SolveRequest) XXX_Size() int {
339
+	return m.Size()
340
+}
341
+func (m *SolveRequest) XXX_DiscardUnknown() {
342
+	xxx_messageInfo_SolveRequest.DiscardUnknown(m)
302 343
 }
303 344
 
304
-func (m *SolveRequest) Reset()                    { *m = SolveRequest{} }
305
-func (m *SolveRequest) String() string            { return proto.CompactTextString(m) }
306
-func (*SolveRequest) ProtoMessage()               {}
307
-func (*SolveRequest) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{6} }
345
+var xxx_messageInfo_SolveRequest proto.InternalMessageInfo
308 346
 
309 347
 func (m *SolveRequest) GetDefinition() *pb.Definition {
310 348
 	if m != nil {
... ...
@@ -327,9 +526,9 @@ func (m *SolveRequest) GetFrontendOpt() map[string]string {
327 327
 	return nil
328 328
 }
329 329
 
330
-func (m *SolveRequest) GetImportCacheRefs() []string {
330
+func (m *SolveRequest) GetImportCacheRefsDeprecated() []string {
331 331
 	if m != nil {
332
-		return m.ImportCacheRefs
332
+		return m.ImportCacheRefsDeprecated
333 333
 	}
334 334
 	return nil
335 335
 }
... ...
@@ -355,17 +554,111 @@ func (m *SolveRequest) GetExporterAttr() []byte {
355 355
 	return nil
356 356
 }
357 357
 
358
+func (m *SolveRequest) GetCacheImports() []*CacheOptionsEntry {
359
+	if m != nil {
360
+		return m.CacheImports
361
+	}
362
+	return nil
363
+}
364
+
365
+// CacheOptionsEntry corresponds to the control.CacheOptionsEntry
366
+type CacheOptionsEntry struct {
367
+	Type                 string            `protobuf:"bytes,1,opt,name=Type,proto3" json:"Type,omitempty"`
368
+	Attrs                map[string]string `protobuf:"bytes,2,rep,name=Attrs,proto3" json:"Attrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
369
+	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
370
+	XXX_unrecognized     []byte            `json:"-"`
371
+	XXX_sizecache        int32             `json:"-"`
372
+}
373
+
374
+func (m *CacheOptionsEntry) Reset()         { *m = CacheOptionsEntry{} }
375
+func (m *CacheOptionsEntry) String() string { return proto.CompactTextString(m) }
376
+func (*CacheOptionsEntry) ProtoMessage()    {}
377
+func (*CacheOptionsEntry) Descriptor() ([]byte, []int) {
378
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{7}
379
+}
380
+func (m *CacheOptionsEntry) XXX_Unmarshal(b []byte) error {
381
+	return m.Unmarshal(b)
382
+}
383
+func (m *CacheOptionsEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
384
+	if deterministic {
385
+		return xxx_messageInfo_CacheOptionsEntry.Marshal(b, m, deterministic)
386
+	} else {
387
+		b = b[:cap(b)]
388
+		n, err := m.MarshalTo(b)
389
+		if err != nil {
390
+			return nil, err
391
+		}
392
+		return b[:n], nil
393
+	}
394
+}
395
+func (dst *CacheOptionsEntry) XXX_Merge(src proto.Message) {
396
+	xxx_messageInfo_CacheOptionsEntry.Merge(dst, src)
397
+}
398
+func (m *CacheOptionsEntry) XXX_Size() int {
399
+	return m.Size()
400
+}
401
+func (m *CacheOptionsEntry) XXX_DiscardUnknown() {
402
+	xxx_messageInfo_CacheOptionsEntry.DiscardUnknown(m)
403
+}
404
+
405
+var xxx_messageInfo_CacheOptionsEntry proto.InternalMessageInfo
406
+
407
+func (m *CacheOptionsEntry) GetType() string {
408
+	if m != nil {
409
+		return m.Type
410
+	}
411
+	return ""
412
+}
413
+
414
+func (m *CacheOptionsEntry) GetAttrs() map[string]string {
415
+	if m != nil {
416
+		return m.Attrs
417
+	}
418
+	return nil
419
+}
420
+
358 421
 type SolveResponse struct {
359 422
 	// deprecated
360 423
 	Ref string `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"`
361 424
 	// these fields are returned when allowMapReturn was set
362
-	Result *Result `protobuf:"bytes,3,opt,name=result" json:"result,omitempty"`
425
+	Result               *Result  `protobuf:"bytes,3,opt,name=result,proto3" json:"result,omitempty"`
426
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
427
+	XXX_unrecognized     []byte   `json:"-"`
428
+	XXX_sizecache        int32    `json:"-"`
429
+}
430
+
431
+func (m *SolveResponse) Reset()         { *m = SolveResponse{} }
432
+func (m *SolveResponse) String() string { return proto.CompactTextString(m) }
433
+func (*SolveResponse) ProtoMessage()    {}
434
+func (*SolveResponse) Descriptor() ([]byte, []int) {
435
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{8}
436
+}
437
+func (m *SolveResponse) XXX_Unmarshal(b []byte) error {
438
+	return m.Unmarshal(b)
439
+}
440
+func (m *SolveResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
441
+	if deterministic {
442
+		return xxx_messageInfo_SolveResponse.Marshal(b, m, deterministic)
443
+	} else {
444
+		b = b[:cap(b)]
445
+		n, err := m.MarshalTo(b)
446
+		if err != nil {
447
+			return nil, err
448
+		}
449
+		return b[:n], nil
450
+	}
451
+}
452
+func (dst *SolveResponse) XXX_Merge(src proto.Message) {
453
+	xxx_messageInfo_SolveResponse.Merge(dst, src)
454
+}
455
+func (m *SolveResponse) XXX_Size() int {
456
+	return m.Size()
457
+}
458
+func (m *SolveResponse) XXX_DiscardUnknown() {
459
+	xxx_messageInfo_SolveResponse.DiscardUnknown(m)
363 460
 }
364 461
 
365
-func (m *SolveResponse) Reset()                    { *m = SolveResponse{} }
366
-func (m *SolveResponse) String() string            { return proto.CompactTextString(m) }
367
-func (*SolveResponse) ProtoMessage()               {}
368
-func (*SolveResponse) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{7} }
462
+var xxx_messageInfo_SolveResponse proto.InternalMessageInfo
369 463
 
370 464
 func (m *SolveResponse) GetRef() string {
371 465
 	if m != nil {
... ...
@@ -382,15 +675,46 @@ func (m *SolveResponse) GetResult() *Result {
382 382
 }
383 383
 
384 384
 type ReadFileRequest struct {
385
-	Ref      string     `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
386
-	FilePath string     `protobuf:"bytes,2,opt,name=FilePath,proto3" json:"FilePath,omitempty"`
387
-	Range    *FileRange `protobuf:"bytes,3,opt,name=Range" json:"Range,omitempty"`
385
+	Ref                  string     `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
386
+	FilePath             string     `protobuf:"bytes,2,opt,name=FilePath,proto3" json:"FilePath,omitempty"`
387
+	Range                *FileRange `protobuf:"bytes,3,opt,name=Range,proto3" json:"Range,omitempty"`
388
+	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
389
+	XXX_unrecognized     []byte     `json:"-"`
390
+	XXX_sizecache        int32      `json:"-"`
391
+}
392
+
393
+func (m *ReadFileRequest) Reset()         { *m = ReadFileRequest{} }
394
+func (m *ReadFileRequest) String() string { return proto.CompactTextString(m) }
395
+func (*ReadFileRequest) ProtoMessage()    {}
396
+func (*ReadFileRequest) Descriptor() ([]byte, []int) {
397
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{9}
398
+}
399
+func (m *ReadFileRequest) XXX_Unmarshal(b []byte) error {
400
+	return m.Unmarshal(b)
401
+}
402
+func (m *ReadFileRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
403
+	if deterministic {
404
+		return xxx_messageInfo_ReadFileRequest.Marshal(b, m, deterministic)
405
+	} else {
406
+		b = b[:cap(b)]
407
+		n, err := m.MarshalTo(b)
408
+		if err != nil {
409
+			return nil, err
410
+		}
411
+		return b[:n], nil
412
+	}
413
+}
414
+func (dst *ReadFileRequest) XXX_Merge(src proto.Message) {
415
+	xxx_messageInfo_ReadFileRequest.Merge(dst, src)
416
+}
417
+func (m *ReadFileRequest) XXX_Size() int {
418
+	return m.Size()
419
+}
420
+func (m *ReadFileRequest) XXX_DiscardUnknown() {
421
+	xxx_messageInfo_ReadFileRequest.DiscardUnknown(m)
388 422
 }
389 423
 
390
-func (m *ReadFileRequest) Reset()                    { *m = ReadFileRequest{} }
391
-func (m *ReadFileRequest) String() string            { return proto.CompactTextString(m) }
392
-func (*ReadFileRequest) ProtoMessage()               {}
393
-func (*ReadFileRequest) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{8} }
424
+var xxx_messageInfo_ReadFileRequest proto.InternalMessageInfo
394 425
 
395 426
 func (m *ReadFileRequest) GetRef() string {
396 427
 	if m != nil {
... ...
@@ -414,14 +738,45 @@ func (m *ReadFileRequest) GetRange() *FileRange {
414 414
 }
415 415
 
416 416
 type FileRange struct {
417
-	Offset int64 `protobuf:"varint,1,opt,name=Offset,proto3" json:"Offset,omitempty"`
418
-	Length int64 `protobuf:"varint,2,opt,name=Length,proto3" json:"Length,omitempty"`
417
+	Offset               int64    `protobuf:"varint,1,opt,name=Offset,proto3" json:"Offset,omitempty"`
418
+	Length               int64    `protobuf:"varint,2,opt,name=Length,proto3" json:"Length,omitempty"`
419
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
420
+	XXX_unrecognized     []byte   `json:"-"`
421
+	XXX_sizecache        int32    `json:"-"`
422
+}
423
+
424
+func (m *FileRange) Reset()         { *m = FileRange{} }
425
+func (m *FileRange) String() string { return proto.CompactTextString(m) }
426
+func (*FileRange) ProtoMessage()    {}
427
+func (*FileRange) Descriptor() ([]byte, []int) {
428
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{10}
429
+}
430
+func (m *FileRange) XXX_Unmarshal(b []byte) error {
431
+	return m.Unmarshal(b)
432
+}
433
+func (m *FileRange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
434
+	if deterministic {
435
+		return xxx_messageInfo_FileRange.Marshal(b, m, deterministic)
436
+	} else {
437
+		b = b[:cap(b)]
438
+		n, err := m.MarshalTo(b)
439
+		if err != nil {
440
+			return nil, err
441
+		}
442
+		return b[:n], nil
443
+	}
444
+}
445
+func (dst *FileRange) XXX_Merge(src proto.Message) {
446
+	xxx_messageInfo_FileRange.Merge(dst, src)
447
+}
448
+func (m *FileRange) XXX_Size() int {
449
+	return m.Size()
450
+}
451
+func (m *FileRange) XXX_DiscardUnknown() {
452
+	xxx_messageInfo_FileRange.DiscardUnknown(m)
419 453
 }
420 454
 
421
-func (m *FileRange) Reset()                    { *m = FileRange{} }
422
-func (m *FileRange) String() string            { return proto.CompactTextString(m) }
423
-func (*FileRange) ProtoMessage()               {}
424
-func (*FileRange) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{9} }
455
+var xxx_messageInfo_FileRange proto.InternalMessageInfo
425 456
 
426 457
 func (m *FileRange) GetOffset() int64 {
427 458
 	if m != nil {
... ...
@@ -438,13 +793,44 @@ func (m *FileRange) GetLength() int64 {
438 438
 }
439 439
 
440 440
 type ReadFileResponse struct {
441
-	Data []byte `protobuf:"bytes,1,opt,name=Data,proto3" json:"Data,omitempty"`
441
+	Data                 []byte   `protobuf:"bytes,1,opt,name=Data,proto3" json:"Data,omitempty"`
442
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
443
+	XXX_unrecognized     []byte   `json:"-"`
444
+	XXX_sizecache        int32    `json:"-"`
445
+}
446
+
447
+func (m *ReadFileResponse) Reset()         { *m = ReadFileResponse{} }
448
+func (m *ReadFileResponse) String() string { return proto.CompactTextString(m) }
449
+func (*ReadFileResponse) ProtoMessage()    {}
450
+func (*ReadFileResponse) Descriptor() ([]byte, []int) {
451
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{11}
452
+}
453
+func (m *ReadFileResponse) XXX_Unmarshal(b []byte) error {
454
+	return m.Unmarshal(b)
455
+}
456
+func (m *ReadFileResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
457
+	if deterministic {
458
+		return xxx_messageInfo_ReadFileResponse.Marshal(b, m, deterministic)
459
+	} else {
460
+		b = b[:cap(b)]
461
+		n, err := m.MarshalTo(b)
462
+		if err != nil {
463
+			return nil, err
464
+		}
465
+		return b[:n], nil
466
+	}
467
+}
468
+func (dst *ReadFileResponse) XXX_Merge(src proto.Message) {
469
+	xxx_messageInfo_ReadFileResponse.Merge(dst, src)
470
+}
471
+func (m *ReadFileResponse) XXX_Size() int {
472
+	return m.Size()
473
+}
474
+func (m *ReadFileResponse) XXX_DiscardUnknown() {
475
+	xxx_messageInfo_ReadFileResponse.DiscardUnknown(m)
442 476
 }
443 477
 
444
-func (m *ReadFileResponse) Reset()                    { *m = ReadFileResponse{} }
445
-func (m *ReadFileResponse) String() string            { return proto.CompactTextString(m) }
446
-func (*ReadFileResponse) ProtoMessage()               {}
447
-func (*ReadFileResponse) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{10} }
478
+var xxx_messageInfo_ReadFileResponse proto.InternalMessageInfo
448 479
 
449 480
 func (m *ReadFileResponse) GetData() []byte {
450 481
 	if m != nil {
... ...
@@ -454,15 +840,46 @@ func (m *ReadFileResponse) GetData() []byte {
454 454
 }
455 455
 
456 456
 type ReadDirRequest struct {
457
-	Ref            string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
458
-	DirPath        string `protobuf:"bytes,2,opt,name=DirPath,proto3" json:"DirPath,omitempty"`
459
-	IncludePattern string `protobuf:"bytes,3,opt,name=IncludePattern,proto3" json:"IncludePattern,omitempty"`
457
+	Ref                  string   `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
458
+	DirPath              string   `protobuf:"bytes,2,opt,name=DirPath,proto3" json:"DirPath,omitempty"`
459
+	IncludePattern       string   `protobuf:"bytes,3,opt,name=IncludePattern,proto3" json:"IncludePattern,omitempty"`
460
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
461
+	XXX_unrecognized     []byte   `json:"-"`
462
+	XXX_sizecache        int32    `json:"-"`
463
+}
464
+
465
+func (m *ReadDirRequest) Reset()         { *m = ReadDirRequest{} }
466
+func (m *ReadDirRequest) String() string { return proto.CompactTextString(m) }
467
+func (*ReadDirRequest) ProtoMessage()    {}
468
+func (*ReadDirRequest) Descriptor() ([]byte, []int) {
469
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{12}
470
+}
471
+func (m *ReadDirRequest) XXX_Unmarshal(b []byte) error {
472
+	return m.Unmarshal(b)
473
+}
474
+func (m *ReadDirRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
475
+	if deterministic {
476
+		return xxx_messageInfo_ReadDirRequest.Marshal(b, m, deterministic)
477
+	} else {
478
+		b = b[:cap(b)]
479
+		n, err := m.MarshalTo(b)
480
+		if err != nil {
481
+			return nil, err
482
+		}
483
+		return b[:n], nil
484
+	}
485
+}
486
+func (dst *ReadDirRequest) XXX_Merge(src proto.Message) {
487
+	xxx_messageInfo_ReadDirRequest.Merge(dst, src)
488
+}
489
+func (m *ReadDirRequest) XXX_Size() int {
490
+	return m.Size()
491
+}
492
+func (m *ReadDirRequest) XXX_DiscardUnknown() {
493
+	xxx_messageInfo_ReadDirRequest.DiscardUnknown(m)
460 494
 }
461 495
 
462
-func (m *ReadDirRequest) Reset()                    { *m = ReadDirRequest{} }
463
-func (m *ReadDirRequest) String() string            { return proto.CompactTextString(m) }
464
-func (*ReadDirRequest) ProtoMessage()               {}
465
-func (*ReadDirRequest) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{11} }
496
+var xxx_messageInfo_ReadDirRequest proto.InternalMessageInfo
466 497
 
467 498
 func (m *ReadDirRequest) GetRef() string {
468 499
 	if m != nil {
... ...
@@ -486,15 +903,46 @@ func (m *ReadDirRequest) GetIncludePattern() string {
486 486
 }
487 487
 
488 488
 type ReadDirResponse struct {
489
-	Entries []*fsutil_types.Stat `protobuf:"bytes,1,rep,name=entries" json:"entries,omitempty"`
489
+	Entries              []*types.Stat `protobuf:"bytes,1,rep,name=entries,proto3" json:"entries,omitempty"`
490
+	XXX_NoUnkeyedLiteral struct{}      `json:"-"`
491
+	XXX_unrecognized     []byte        `json:"-"`
492
+	XXX_sizecache        int32         `json:"-"`
493
+}
494
+
495
+func (m *ReadDirResponse) Reset()         { *m = ReadDirResponse{} }
496
+func (m *ReadDirResponse) String() string { return proto.CompactTextString(m) }
497
+func (*ReadDirResponse) ProtoMessage()    {}
498
+func (*ReadDirResponse) Descriptor() ([]byte, []int) {
499
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{13}
500
+}
501
+func (m *ReadDirResponse) XXX_Unmarshal(b []byte) error {
502
+	return m.Unmarshal(b)
503
+}
504
+func (m *ReadDirResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
505
+	if deterministic {
506
+		return xxx_messageInfo_ReadDirResponse.Marshal(b, m, deterministic)
507
+	} else {
508
+		b = b[:cap(b)]
509
+		n, err := m.MarshalTo(b)
510
+		if err != nil {
511
+			return nil, err
512
+		}
513
+		return b[:n], nil
514
+	}
515
+}
516
+func (dst *ReadDirResponse) XXX_Merge(src proto.Message) {
517
+	xxx_messageInfo_ReadDirResponse.Merge(dst, src)
518
+}
519
+func (m *ReadDirResponse) XXX_Size() int {
520
+	return m.Size()
521
+}
522
+func (m *ReadDirResponse) XXX_DiscardUnknown() {
523
+	xxx_messageInfo_ReadDirResponse.DiscardUnknown(m)
490 524
 }
491 525
 
492
-func (m *ReadDirResponse) Reset()                    { *m = ReadDirResponse{} }
493
-func (m *ReadDirResponse) String() string            { return proto.CompactTextString(m) }
494
-func (*ReadDirResponse) ProtoMessage()               {}
495
-func (*ReadDirResponse) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{12} }
526
+var xxx_messageInfo_ReadDirResponse proto.InternalMessageInfo
496 527
 
497
-func (m *ReadDirResponse) GetEntries() []*fsutil_types.Stat {
528
+func (m *ReadDirResponse) GetEntries() []*types.Stat {
498 529
 	if m != nil {
499 530
 		return m.Entries
500 531
 	}
... ...
@@ -502,14 +950,45 @@ func (m *ReadDirResponse) GetEntries() []*fsutil_types.Stat {
502 502
 }
503 503
 
504 504
 type StatFileRequest struct {
505
-	Ref  string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
506
-	Path string `protobuf:"bytes,2,opt,name=Path,proto3" json:"Path,omitempty"`
505
+	Ref                  string   `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
506
+	Path                 string   `protobuf:"bytes,2,opt,name=Path,proto3" json:"Path,omitempty"`
507
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
508
+	XXX_unrecognized     []byte   `json:"-"`
509
+	XXX_sizecache        int32    `json:"-"`
510
+}
511
+
512
+func (m *StatFileRequest) Reset()         { *m = StatFileRequest{} }
513
+func (m *StatFileRequest) String() string { return proto.CompactTextString(m) }
514
+func (*StatFileRequest) ProtoMessage()    {}
515
+func (*StatFileRequest) Descriptor() ([]byte, []int) {
516
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{14}
517
+}
518
+func (m *StatFileRequest) XXX_Unmarshal(b []byte) error {
519
+	return m.Unmarshal(b)
520
+}
521
+func (m *StatFileRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
522
+	if deterministic {
523
+		return xxx_messageInfo_StatFileRequest.Marshal(b, m, deterministic)
524
+	} else {
525
+		b = b[:cap(b)]
526
+		n, err := m.MarshalTo(b)
527
+		if err != nil {
528
+			return nil, err
529
+		}
530
+		return b[:n], nil
531
+	}
532
+}
533
+func (dst *StatFileRequest) XXX_Merge(src proto.Message) {
534
+	xxx_messageInfo_StatFileRequest.Merge(dst, src)
535
+}
536
+func (m *StatFileRequest) XXX_Size() int {
537
+	return m.Size()
538
+}
539
+func (m *StatFileRequest) XXX_DiscardUnknown() {
540
+	xxx_messageInfo_StatFileRequest.DiscardUnknown(m)
507 541
 }
508 542
 
509
-func (m *StatFileRequest) Reset()                    { *m = StatFileRequest{} }
510
-func (m *StatFileRequest) String() string            { return proto.CompactTextString(m) }
511
-func (*StatFileRequest) ProtoMessage()               {}
512
-func (*StatFileRequest) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{13} }
543
+var xxx_messageInfo_StatFileRequest proto.InternalMessageInfo
513 544
 
514 545
 func (m *StatFileRequest) GetRef() string {
515 546
 	if m != nil {
... ...
@@ -526,15 +1005,46 @@ func (m *StatFileRequest) GetPath() string {
526 526
 }
527 527
 
528 528
 type StatFileResponse struct {
529
-	Stat *fsutil_types.Stat `protobuf:"bytes,1,opt,name=stat" json:"stat,omitempty"`
529
+	Stat                 *types.Stat `protobuf:"bytes,1,opt,name=stat,proto3" json:"stat,omitempty"`
530
+	XXX_NoUnkeyedLiteral struct{}    `json:"-"`
531
+	XXX_unrecognized     []byte      `json:"-"`
532
+	XXX_sizecache        int32       `json:"-"`
533
+}
534
+
535
+func (m *StatFileResponse) Reset()         { *m = StatFileResponse{} }
536
+func (m *StatFileResponse) String() string { return proto.CompactTextString(m) }
537
+func (*StatFileResponse) ProtoMessage()    {}
538
+func (*StatFileResponse) Descriptor() ([]byte, []int) {
539
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{15}
540
+}
541
+func (m *StatFileResponse) XXX_Unmarshal(b []byte) error {
542
+	return m.Unmarshal(b)
543
+}
544
+func (m *StatFileResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
545
+	if deterministic {
546
+		return xxx_messageInfo_StatFileResponse.Marshal(b, m, deterministic)
547
+	} else {
548
+		b = b[:cap(b)]
549
+		n, err := m.MarshalTo(b)
550
+		if err != nil {
551
+			return nil, err
552
+		}
553
+		return b[:n], nil
554
+	}
555
+}
556
+func (dst *StatFileResponse) XXX_Merge(src proto.Message) {
557
+	xxx_messageInfo_StatFileResponse.Merge(dst, src)
558
+}
559
+func (m *StatFileResponse) XXX_Size() int {
560
+	return m.Size()
561
+}
562
+func (m *StatFileResponse) XXX_DiscardUnknown() {
563
+	xxx_messageInfo_StatFileResponse.DiscardUnknown(m)
530 564
 }
531 565
 
532
-func (m *StatFileResponse) Reset()                    { *m = StatFileResponse{} }
533
-func (m *StatFileResponse) String() string            { return proto.CompactTextString(m) }
534
-func (*StatFileResponse) ProtoMessage()               {}
535
-func (*StatFileResponse) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{14} }
566
+var xxx_messageInfo_StatFileResponse proto.InternalMessageInfo
536 567
 
537
-func (m *StatFileResponse) GetStat() *fsutil_types.Stat {
568
+func (m *StatFileResponse) GetStat() *types.Stat {
538 569
 	if m != nil {
539 570
 		return m.Stat
540 571
 	}
... ...
@@ -542,39 +1052,101 @@ func (m *StatFileResponse) GetStat() *fsutil_types.Stat {
542 542
 }
543 543
 
544 544
 type PingRequest struct {
545
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
546
+	XXX_unrecognized     []byte   `json:"-"`
547
+	XXX_sizecache        int32    `json:"-"`
548
+}
549
+
550
+func (m *PingRequest) Reset()         { *m = PingRequest{} }
551
+func (m *PingRequest) String() string { return proto.CompactTextString(m) }
552
+func (*PingRequest) ProtoMessage()    {}
553
+func (*PingRequest) Descriptor() ([]byte, []int) {
554
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{16}
555
+}
556
+func (m *PingRequest) XXX_Unmarshal(b []byte) error {
557
+	return m.Unmarshal(b)
558
+}
559
+func (m *PingRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
560
+	if deterministic {
561
+		return xxx_messageInfo_PingRequest.Marshal(b, m, deterministic)
562
+	} else {
563
+		b = b[:cap(b)]
564
+		n, err := m.MarshalTo(b)
565
+		if err != nil {
566
+			return nil, err
567
+		}
568
+		return b[:n], nil
569
+	}
570
+}
571
+func (dst *PingRequest) XXX_Merge(src proto.Message) {
572
+	xxx_messageInfo_PingRequest.Merge(dst, src)
573
+}
574
+func (m *PingRequest) XXX_Size() int {
575
+	return m.Size()
576
+}
577
+func (m *PingRequest) XXX_DiscardUnknown() {
578
+	xxx_messageInfo_PingRequest.DiscardUnknown(m)
545 579
 }
546 580
 
547
-func (m *PingRequest) Reset()                    { *m = PingRequest{} }
548
-func (m *PingRequest) String() string            { return proto.CompactTextString(m) }
549
-func (*PingRequest) ProtoMessage()               {}
550
-func (*PingRequest) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{15} }
581
+var xxx_messageInfo_PingRequest proto.InternalMessageInfo
551 582
 
552 583
 type PongResponse struct {
553
-	FrontendAPICaps []moby_buildkit_v1_apicaps.APICap      `protobuf:"bytes,1,rep,name=FrontendAPICaps" json:"FrontendAPICaps"`
554
-	LLBCaps         []moby_buildkit_v1_apicaps.APICap      `protobuf:"bytes,2,rep,name=LLBCaps" json:"LLBCaps"`
555
-	Workers         []*moby_buildkit_v1_types.WorkerRecord `protobuf:"bytes,3,rep,name=Workers" json:"Workers,omitempty"`
584
+	FrontendAPICaps      []pb1.APICap           `protobuf:"bytes,1,rep,name=FrontendAPICaps,proto3" json:"FrontendAPICaps"`
585
+	LLBCaps              []pb1.APICap           `protobuf:"bytes,2,rep,name=LLBCaps,proto3" json:"LLBCaps"`
586
+	Workers              []*types1.WorkerRecord `protobuf:"bytes,3,rep,name=Workers,proto3" json:"Workers,omitempty"`
587
+	XXX_NoUnkeyedLiteral struct{}               `json:"-"`
588
+	XXX_unrecognized     []byte                 `json:"-"`
589
+	XXX_sizecache        int32                  `json:"-"`
590
+}
591
+
592
+func (m *PongResponse) Reset()         { *m = PongResponse{} }
593
+func (m *PongResponse) String() string { return proto.CompactTextString(m) }
594
+func (*PongResponse) ProtoMessage()    {}
595
+func (*PongResponse) Descriptor() ([]byte, []int) {
596
+	return fileDescriptor_gateway_eff078cadb286ceb, []int{17}
597
+}
598
+func (m *PongResponse) XXX_Unmarshal(b []byte) error {
599
+	return m.Unmarshal(b)
600
+}
601
+func (m *PongResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
602
+	if deterministic {
603
+		return xxx_messageInfo_PongResponse.Marshal(b, m, deterministic)
604
+	} else {
605
+		b = b[:cap(b)]
606
+		n, err := m.MarshalTo(b)
607
+		if err != nil {
608
+			return nil, err
609
+		}
610
+		return b[:n], nil
611
+	}
612
+}
613
+func (dst *PongResponse) XXX_Merge(src proto.Message) {
614
+	xxx_messageInfo_PongResponse.Merge(dst, src)
615
+}
616
+func (m *PongResponse) XXX_Size() int {
617
+	return m.Size()
618
+}
619
+func (m *PongResponse) XXX_DiscardUnknown() {
620
+	xxx_messageInfo_PongResponse.DiscardUnknown(m)
556 621
 }
557 622
 
558
-func (m *PongResponse) Reset()                    { *m = PongResponse{} }
559
-func (m *PongResponse) String() string            { return proto.CompactTextString(m) }
560
-func (*PongResponse) ProtoMessage()               {}
561
-func (*PongResponse) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{16} }
623
+var xxx_messageInfo_PongResponse proto.InternalMessageInfo
562 624
 
563
-func (m *PongResponse) GetFrontendAPICaps() []moby_buildkit_v1_apicaps.APICap {
625
+func (m *PongResponse) GetFrontendAPICaps() []pb1.APICap {
564 626
 	if m != nil {
565 627
 		return m.FrontendAPICaps
566 628
 	}
567 629
 	return nil
568 630
 }
569 631
 
570
-func (m *PongResponse) GetLLBCaps() []moby_buildkit_v1_apicaps.APICap {
632
+func (m *PongResponse) GetLLBCaps() []pb1.APICap {
571 633
 	if m != nil {
572 634
 		return m.LLBCaps
573 635
 	}
574 636
 	return nil
575 637
 }
576 638
 
577
-func (m *PongResponse) GetWorkers() []*moby_buildkit_v1_types.WorkerRecord {
639
+func (m *PongResponse) GetWorkers() []*types1.WorkerRecord {
578 640
 	if m != nil {
579 641
 		return m.Workers
580 642
 	}
... ...
@@ -583,12 +1155,17 @@ func (m *PongResponse) GetWorkers() []*moby_buildkit_v1_types.WorkerRecord {
583 583
 
584 584
 func init() {
585 585
 	proto.RegisterType((*Result)(nil), "moby.buildkit.v1.frontend.Result")
586
+	proto.RegisterMapType((map[string][]byte)(nil), "moby.buildkit.v1.frontend.Result.MetadataEntry")
586 587
 	proto.RegisterType((*RefMap)(nil), "moby.buildkit.v1.frontend.RefMap")
588
+	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.frontend.RefMap.RefsEntry")
587 589
 	proto.RegisterType((*ReturnRequest)(nil), "moby.buildkit.v1.frontend.ReturnRequest")
588 590
 	proto.RegisterType((*ReturnResponse)(nil), "moby.buildkit.v1.frontend.ReturnResponse")
589 591
 	proto.RegisterType((*ResolveImageConfigRequest)(nil), "moby.buildkit.v1.frontend.ResolveImageConfigRequest")
590 592
 	proto.RegisterType((*ResolveImageConfigResponse)(nil), "moby.buildkit.v1.frontend.ResolveImageConfigResponse")
591 593
 	proto.RegisterType((*SolveRequest)(nil), "moby.buildkit.v1.frontend.SolveRequest")
594
+	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.frontend.SolveRequest.FrontendOptEntry")
595
+	proto.RegisterType((*CacheOptionsEntry)(nil), "moby.buildkit.v1.frontend.CacheOptionsEntry")
596
+	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.v1.frontend.CacheOptionsEntry.AttrsEntry")
592 597
 	proto.RegisterType((*SolveResponse)(nil), "moby.buildkit.v1.frontend.SolveResponse")
593 598
 	proto.RegisterType((*ReadFileRequest)(nil), "moby.buildkit.v1.frontend.ReadFileRequest")
594 599
 	proto.RegisterType((*FileRange)(nil), "moby.buildkit.v1.frontend.FileRange")
... ...
@@ -609,8 +1186,9 @@ var _ grpc.ClientConn
609 609
 // is compatible with the grpc package it is being compiled against.
610 610
 const _ = grpc.SupportPackageIsVersion4
611 611
 
612
-// Client API for LLBBridge service
613
-
612
+// LLBBridgeClient is the client API for LLBBridge service.
613
+//
614
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
614 615
 type LLBBridgeClient interface {
615 616
 	// apicaps:CapResolveImage
616 617
 	ResolveImageConfig(ctx context.Context, in *ResolveImageConfigRequest, opts ...grpc.CallOption) (*ResolveImageConfigResponse, error)
... ...
@@ -636,7 +1214,7 @@ func NewLLBBridgeClient(cc *grpc.ClientConn) LLBBridgeClient {
636 636
 
637 637
 func (c *lLBBridgeClient) ResolveImageConfig(ctx context.Context, in *ResolveImageConfigRequest, opts ...grpc.CallOption) (*ResolveImageConfigResponse, error) {
638 638
 	out := new(ResolveImageConfigResponse)
639
-	err := grpc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/ResolveImageConfig", in, out, c.cc, opts...)
639
+	err := c.cc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/ResolveImageConfig", in, out, opts...)
640 640
 	if err != nil {
641 641
 		return nil, err
642 642
 	}
... ...
@@ -645,7 +1223,7 @@ func (c *lLBBridgeClient) ResolveImageConfig(ctx context.Context, in *ResolveIma
645 645
 
646 646
 func (c *lLBBridgeClient) Solve(ctx context.Context, in *SolveRequest, opts ...grpc.CallOption) (*SolveResponse, error) {
647 647
 	out := new(SolveResponse)
648
-	err := grpc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/Solve", in, out, c.cc, opts...)
648
+	err := c.cc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/Solve", in, out, opts...)
649 649
 	if err != nil {
650 650
 		return nil, err
651 651
 	}
... ...
@@ -654,7 +1232,7 @@ func (c *lLBBridgeClient) Solve(ctx context.Context, in *SolveRequest, opts ...g
654 654
 
655 655
 func (c *lLBBridgeClient) ReadFile(ctx context.Context, in *ReadFileRequest, opts ...grpc.CallOption) (*ReadFileResponse, error) {
656 656
 	out := new(ReadFileResponse)
657
-	err := grpc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/ReadFile", in, out, c.cc, opts...)
657
+	err := c.cc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/ReadFile", in, out, opts...)
658 658
 	if err != nil {
659 659
 		return nil, err
660 660
 	}
... ...
@@ -663,7 +1241,7 @@ func (c *lLBBridgeClient) ReadFile(ctx context.Context, in *ReadFileRequest, opt
663 663
 
664 664
 func (c *lLBBridgeClient) ReadDir(ctx context.Context, in *ReadDirRequest, opts ...grpc.CallOption) (*ReadDirResponse, error) {
665 665
 	out := new(ReadDirResponse)
666
-	err := grpc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/ReadDir", in, out, c.cc, opts...)
666
+	err := c.cc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/ReadDir", in, out, opts...)
667 667
 	if err != nil {
668 668
 		return nil, err
669 669
 	}
... ...
@@ -672,7 +1250,7 @@ func (c *lLBBridgeClient) ReadDir(ctx context.Context, in *ReadDirRequest, opts
672 672
 
673 673
 func (c *lLBBridgeClient) StatFile(ctx context.Context, in *StatFileRequest, opts ...grpc.CallOption) (*StatFileResponse, error) {
674 674
 	out := new(StatFileResponse)
675
-	err := grpc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/StatFile", in, out, c.cc, opts...)
675
+	err := c.cc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/StatFile", in, out, opts...)
676 676
 	if err != nil {
677 677
 		return nil, err
678 678
 	}
... ...
@@ -681,7 +1259,7 @@ func (c *lLBBridgeClient) StatFile(ctx context.Context, in *StatFileRequest, opt
681 681
 
682 682
 func (c *lLBBridgeClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PongResponse, error) {
683 683
 	out := new(PongResponse)
684
-	err := grpc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/Ping", in, out, c.cc, opts...)
684
+	err := c.cc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/Ping", in, out, opts...)
685 685
 	if err != nil {
686 686
 		return nil, err
687 687
 	}
... ...
@@ -690,15 +1268,14 @@ func (c *lLBBridgeClient) Ping(ctx context.Context, in *PingRequest, opts ...grp
690 690
 
691 691
 func (c *lLBBridgeClient) Return(ctx context.Context, in *ReturnRequest, opts ...grpc.CallOption) (*ReturnResponse, error) {
692 692
 	out := new(ReturnResponse)
693
-	err := grpc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/Return", in, out, c.cc, opts...)
693
+	err := c.cc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/Return", in, out, opts...)
694 694
 	if err != nil {
695 695
 		return nil, err
696 696
 	}
697 697
 	return out, nil
698 698
 }
699 699
 
700
-// Server API for LLBBridge service
701
-
700
+// LLBBridgeServer is the server API for LLBBridge service.
702 701
 type LLBBridgeServer interface {
703 702
 	// apicaps:CapResolveImage
704 703
 	ResolveImageConfig(context.Context, *ResolveImageConfigRequest) (*ResolveImageConfigResponse, error)
... ...
@@ -926,6 +1503,9 @@ func (m *Result) MarshalTo(dAtA []byte) (int, error) {
926 926
 			}
927 927
 		}
928 928
 	}
929
+	if m.XXX_unrecognized != nil {
930
+		i += copy(dAtA[i:], m.XXX_unrecognized)
931
+	}
929 932
 	return i, nil
930 933
 }
931 934
 
... ...
@@ -983,6 +1563,9 @@ func (m *RefMap) MarshalTo(dAtA []byte) (int, error) {
983 983
 			i += copy(dAtA[i:], v)
984 984
 		}
985 985
 	}
986
+	if m.XXX_unrecognized != nil {
987
+		i += copy(dAtA[i:], m.XXX_unrecognized)
988
+	}
986 989
 	return i, nil
987 990
 }
988 991
 
... ...
@@ -1021,6 +1604,9 @@ func (m *ReturnRequest) MarshalTo(dAtA []byte) (int, error) {
1021 1021
 		}
1022 1022
 		i += n4
1023 1023
 	}
1024
+	if m.XXX_unrecognized != nil {
1025
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1026
+	}
1024 1027
 	return i, nil
1025 1028
 }
1026 1029
 
... ...
@@ -1039,6 +1625,9 @@ func (m *ReturnResponse) MarshalTo(dAtA []byte) (int, error) {
1039 1039
 	_ = i
1040 1040
 	var l int
1041 1041
 	_ = l
1042
+	if m.XXX_unrecognized != nil {
1043
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1044
+	}
1042 1045
 	return i, nil
1043 1046
 }
1044 1047
 
... ...
@@ -1085,6 +1674,9 @@ func (m *ResolveImageConfigRequest) MarshalTo(dAtA []byte) (int, error) {
1085 1085
 		i = encodeVarintGateway(dAtA, i, uint64(len(m.LogName)))
1086 1086
 		i += copy(dAtA[i:], m.LogName)
1087 1087
 	}
1088
+	if m.XXX_unrecognized != nil {
1089
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1090
+	}
1088 1091
 	return i, nil
1089 1092
 }
1090 1093
 
... ...
@@ -1115,6 +1707,9 @@ func (m *ResolveImageConfigResponse) MarshalTo(dAtA []byte) (int, error) {
1115 1115
 		i = encodeVarintGateway(dAtA, i, uint64(len(m.Config)))
1116 1116
 		i += copy(dAtA[i:], m.Config)
1117 1117
 	}
1118
+	if m.XXX_unrecognized != nil {
1119
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1120
+	}
1118 1121
 	return i, nil
1119 1122
 }
1120 1123
 
... ...
@@ -1166,8 +1761,8 @@ func (m *SolveRequest) MarshalTo(dAtA []byte) (int, error) {
1166 1166
 			i += copy(dAtA[i:], v)
1167 1167
 		}
1168 1168
 	}
1169
-	if len(m.ImportCacheRefs) > 0 {
1170
-		for _, s := range m.ImportCacheRefs {
1169
+	if len(m.ImportCacheRefsDeprecated) > 0 {
1170
+		for _, s := range m.ImportCacheRefsDeprecated {
1171 1171
 			dAtA[i] = 0x22
1172 1172
 			i++
1173 1173
 			l = len(s)
... ...
@@ -1207,6 +1802,65 @@ func (m *SolveRequest) MarshalTo(dAtA []byte) (int, error) {
1207 1207
 		i = encodeVarintGateway(dAtA, i, uint64(len(m.ExporterAttr)))
1208 1208
 		i += copy(dAtA[i:], m.ExporterAttr)
1209 1209
 	}
1210
+	if len(m.CacheImports) > 0 {
1211
+		for _, msg := range m.CacheImports {
1212
+			dAtA[i] = 0x62
1213
+			i++
1214
+			i = encodeVarintGateway(dAtA, i, uint64(msg.Size()))
1215
+			n, err := msg.MarshalTo(dAtA[i:])
1216
+			if err != nil {
1217
+				return 0, err
1218
+			}
1219
+			i += n
1220
+		}
1221
+	}
1222
+	if m.XXX_unrecognized != nil {
1223
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1224
+	}
1225
+	return i, nil
1226
+}
1227
+
1228
+func (m *CacheOptionsEntry) Marshal() (dAtA []byte, err error) {
1229
+	size := m.Size()
1230
+	dAtA = make([]byte, size)
1231
+	n, err := m.MarshalTo(dAtA)
1232
+	if err != nil {
1233
+		return nil, err
1234
+	}
1235
+	return dAtA[:n], nil
1236
+}
1237
+
1238
+func (m *CacheOptionsEntry) MarshalTo(dAtA []byte) (int, error) {
1239
+	var i int
1240
+	_ = i
1241
+	var l int
1242
+	_ = l
1243
+	if len(m.Type) > 0 {
1244
+		dAtA[i] = 0xa
1245
+		i++
1246
+		i = encodeVarintGateway(dAtA, i, uint64(len(m.Type)))
1247
+		i += copy(dAtA[i:], m.Type)
1248
+	}
1249
+	if len(m.Attrs) > 0 {
1250
+		for k, _ := range m.Attrs {
1251
+			dAtA[i] = 0x12
1252
+			i++
1253
+			v := m.Attrs[k]
1254
+			mapSize := 1 + len(k) + sovGateway(uint64(len(k))) + 1 + len(v) + sovGateway(uint64(len(v)))
1255
+			i = encodeVarintGateway(dAtA, i, uint64(mapSize))
1256
+			dAtA[i] = 0xa
1257
+			i++
1258
+			i = encodeVarintGateway(dAtA, i, uint64(len(k)))
1259
+			i += copy(dAtA[i:], k)
1260
+			dAtA[i] = 0x12
1261
+			i++
1262
+			i = encodeVarintGateway(dAtA, i, uint64(len(v)))
1263
+			i += copy(dAtA[i:], v)
1264
+		}
1265
+	}
1266
+	if m.XXX_unrecognized != nil {
1267
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1268
+	}
1210 1269
 	return i, nil
1211 1270
 }
1212 1271
 
... ...
@@ -1241,6 +1895,9 @@ func (m *SolveResponse) MarshalTo(dAtA []byte) (int, error) {
1241 1241
 		}
1242 1242
 		i += n7
1243 1243
 	}
1244
+	if m.XXX_unrecognized != nil {
1245
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1246
+	}
1244 1247
 	return i, nil
1245 1248
 }
1246 1249
 
... ...
@@ -1281,6 +1938,9 @@ func (m *ReadFileRequest) MarshalTo(dAtA []byte) (int, error) {
1281 1281
 		}
1282 1282
 		i += n8
1283 1283
 	}
1284
+	if m.XXX_unrecognized != nil {
1285
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1286
+	}
1284 1287
 	return i, nil
1285 1288
 }
1286 1289
 
... ...
@@ -1309,6 +1969,9 @@ func (m *FileRange) MarshalTo(dAtA []byte) (int, error) {
1309 1309
 		i++
1310 1310
 		i = encodeVarintGateway(dAtA, i, uint64(m.Length))
1311 1311
 	}
1312
+	if m.XXX_unrecognized != nil {
1313
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1314
+	}
1312 1315
 	return i, nil
1313 1316
 }
1314 1317
 
... ...
@@ -1333,6 +1996,9 @@ func (m *ReadFileResponse) MarshalTo(dAtA []byte) (int, error) {
1333 1333
 		i = encodeVarintGateway(dAtA, i, uint64(len(m.Data)))
1334 1334
 		i += copy(dAtA[i:], m.Data)
1335 1335
 	}
1336
+	if m.XXX_unrecognized != nil {
1337
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1338
+	}
1336 1339
 	return i, nil
1337 1340
 }
1338 1341
 
... ...
@@ -1369,6 +2035,9 @@ func (m *ReadDirRequest) MarshalTo(dAtA []byte) (int, error) {
1369 1369
 		i = encodeVarintGateway(dAtA, i, uint64(len(m.IncludePattern)))
1370 1370
 		i += copy(dAtA[i:], m.IncludePattern)
1371 1371
 	}
1372
+	if m.XXX_unrecognized != nil {
1373
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1374
+	}
1372 1375
 	return i, nil
1373 1376
 }
1374 1377
 
... ...
@@ -1399,6 +2068,9 @@ func (m *ReadDirResponse) MarshalTo(dAtA []byte) (int, error) {
1399 1399
 			i += n
1400 1400
 		}
1401 1401
 	}
1402
+	if m.XXX_unrecognized != nil {
1403
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1404
+	}
1402 1405
 	return i, nil
1403 1406
 }
1404 1407
 
... ...
@@ -1429,6 +2101,9 @@ func (m *StatFileRequest) MarshalTo(dAtA []byte) (int, error) {
1429 1429
 		i = encodeVarintGateway(dAtA, i, uint64(len(m.Path)))
1430 1430
 		i += copy(dAtA[i:], m.Path)
1431 1431
 	}
1432
+	if m.XXX_unrecognized != nil {
1433
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1434
+	}
1432 1435
 	return i, nil
1433 1436
 }
1434 1437
 
... ...
@@ -1457,6 +2132,9 @@ func (m *StatFileResponse) MarshalTo(dAtA []byte) (int, error) {
1457 1457
 		}
1458 1458
 		i += n9
1459 1459
 	}
1460
+	if m.XXX_unrecognized != nil {
1461
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1462
+	}
1460 1463
 	return i, nil
1461 1464
 }
1462 1465
 
... ...
@@ -1475,6 +2153,9 @@ func (m *PingRequest) MarshalTo(dAtA []byte) (int, error) {
1475 1475
 	_ = i
1476 1476
 	var l int
1477 1477
 	_ = l
1478
+	if m.XXX_unrecognized != nil {
1479
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1480
+	}
1478 1481
 	return i, nil
1479 1482
 }
1480 1483
 
... ...
@@ -1529,6 +2210,9 @@ func (m *PongResponse) MarshalTo(dAtA []byte) (int, error) {
1529 1529
 			i += n
1530 1530
 		}
1531 1531
 	}
1532
+	if m.XXX_unrecognized != nil {
1533
+		i += copy(dAtA[i:], m.XXX_unrecognized)
1534
+	}
1532 1535
 	return i, nil
1533 1536
 }
1534 1537
 
... ...
@@ -1542,6 +2226,9 @@ func encodeVarintGateway(dAtA []byte, offset int, v uint64) int {
1542 1542
 	return offset + 1
1543 1543
 }
1544 1544
 func (m *Result) Size() (n int) {
1545
+	if m == nil {
1546
+		return 0
1547
+	}
1545 1548
 	var l int
1546 1549
 	_ = l
1547 1550
 	if m.Result != nil {
... ...
@@ -1559,10 +2246,16 @@ func (m *Result) Size() (n int) {
1559 1559
 			n += mapEntrySize + 1 + sovGateway(uint64(mapEntrySize))
1560 1560
 		}
1561 1561
 	}
1562
+	if m.XXX_unrecognized != nil {
1563
+		n += len(m.XXX_unrecognized)
1564
+	}
1562 1565
 	return n
1563 1566
 }
1564 1567
 
1565 1568
 func (m *Result_Ref) Size() (n int) {
1569
+	if m == nil {
1570
+		return 0
1571
+	}
1566 1572
 	var l int
1567 1573
 	_ = l
1568 1574
 	l = len(m.Ref)
... ...
@@ -1570,6 +2263,9 @@ func (m *Result_Ref) Size() (n int) {
1570 1570
 	return n
1571 1571
 }
1572 1572
 func (m *Result_Refs) Size() (n int) {
1573
+	if m == nil {
1574
+		return 0
1575
+	}
1573 1576
 	var l int
1574 1577
 	_ = l
1575 1578
 	if m.Refs != nil {
... ...
@@ -1579,6 +2275,9 @@ func (m *Result_Refs) Size() (n int) {
1579 1579
 	return n
1580 1580
 }
1581 1581
 func (m *RefMap) Size() (n int) {
1582
+	if m == nil {
1583
+		return 0
1584
+	}
1582 1585
 	var l int
1583 1586
 	_ = l
1584 1587
 	if len(m.Refs) > 0 {
... ...
@@ -1589,10 +2288,16 @@ func (m *RefMap) Size() (n int) {
1589 1589
 			n += mapEntrySize + 1 + sovGateway(uint64(mapEntrySize))
1590 1590
 		}
1591 1591
 	}
1592
+	if m.XXX_unrecognized != nil {
1593
+		n += len(m.XXX_unrecognized)
1594
+	}
1592 1595
 	return n
1593 1596
 }
1594 1597
 
1595 1598
 func (m *ReturnRequest) Size() (n int) {
1599
+	if m == nil {
1600
+		return 0
1601
+	}
1596 1602
 	var l int
1597 1603
 	_ = l
1598 1604
 	if m.Result != nil {
... ...
@@ -1603,16 +2308,28 @@ func (m *ReturnRequest) Size() (n int) {
1603 1603
 		l = m.Error.Size()
1604 1604
 		n += 1 + l + sovGateway(uint64(l))
1605 1605
 	}
1606
+	if m.XXX_unrecognized != nil {
1607
+		n += len(m.XXX_unrecognized)
1608
+	}
1606 1609
 	return n
1607 1610
 }
1608 1611
 
1609 1612
 func (m *ReturnResponse) Size() (n int) {
1613
+	if m == nil {
1614
+		return 0
1615
+	}
1610 1616
 	var l int
1611 1617
 	_ = l
1618
+	if m.XXX_unrecognized != nil {
1619
+		n += len(m.XXX_unrecognized)
1620
+	}
1612 1621
 	return n
1613 1622
 }
1614 1623
 
1615 1624
 func (m *ResolveImageConfigRequest) Size() (n int) {
1625
+	if m == nil {
1626
+		return 0
1627
+	}
1616 1628
 	var l int
1617 1629
 	_ = l
1618 1630
 	l = len(m.Ref)
... ...
@@ -1631,10 +2348,16 @@ func (m *ResolveImageConfigRequest) Size() (n int) {
1631 1631
 	if l > 0 {
1632 1632
 		n += 1 + l + sovGateway(uint64(l))
1633 1633
 	}
1634
+	if m.XXX_unrecognized != nil {
1635
+		n += len(m.XXX_unrecognized)
1636
+	}
1634 1637
 	return n
1635 1638
 }
1636 1639
 
1637 1640
 func (m *ResolveImageConfigResponse) Size() (n int) {
1641
+	if m == nil {
1642
+		return 0
1643
+	}
1638 1644
 	var l int
1639 1645
 	_ = l
1640 1646
 	l = len(m.Digest)
... ...
@@ -1645,10 +2368,16 @@ func (m *ResolveImageConfigResponse) Size() (n int) {
1645 1645
 	if l > 0 {
1646 1646
 		n += 1 + l + sovGateway(uint64(l))
1647 1647
 	}
1648
+	if m.XXX_unrecognized != nil {
1649
+		n += len(m.XXX_unrecognized)
1650
+	}
1648 1651
 	return n
1649 1652
 }
1650 1653
 
1651 1654
 func (m *SolveRequest) Size() (n int) {
1655
+	if m == nil {
1656
+		return 0
1657
+	}
1652 1658
 	var l int
1653 1659
 	_ = l
1654 1660
 	if m.Definition != nil {
... ...
@@ -1667,8 +2396,8 @@ func (m *SolveRequest) Size() (n int) {
1667 1667
 			n += mapEntrySize + 1 + sovGateway(uint64(mapEntrySize))
1668 1668
 		}
1669 1669
 	}
1670
-	if len(m.ImportCacheRefs) > 0 {
1671
-		for _, s := range m.ImportCacheRefs {
1670
+	if len(m.ImportCacheRefsDeprecated) > 0 {
1671
+		for _, s := range m.ImportCacheRefsDeprecated {
1672 1672
 			l = len(s)
1673 1673
 			n += 1 + l + sovGateway(uint64(l))
1674 1674
 		}
... ...
@@ -1683,10 +2412,46 @@ func (m *SolveRequest) Size() (n int) {
1683 1683
 	if l > 0 {
1684 1684
 		n += 1 + l + sovGateway(uint64(l))
1685 1685
 	}
1686
+	if len(m.CacheImports) > 0 {
1687
+		for _, e := range m.CacheImports {
1688
+			l = e.Size()
1689
+			n += 1 + l + sovGateway(uint64(l))
1690
+		}
1691
+	}
1692
+	if m.XXX_unrecognized != nil {
1693
+		n += len(m.XXX_unrecognized)
1694
+	}
1695
+	return n
1696
+}
1697
+
1698
+func (m *CacheOptionsEntry) Size() (n int) {
1699
+	if m == nil {
1700
+		return 0
1701
+	}
1702
+	var l int
1703
+	_ = l
1704
+	l = len(m.Type)
1705
+	if l > 0 {
1706
+		n += 1 + l + sovGateway(uint64(l))
1707
+	}
1708
+	if len(m.Attrs) > 0 {
1709
+		for k, v := range m.Attrs {
1710
+			_ = k
1711
+			_ = v
1712
+			mapEntrySize := 1 + len(k) + sovGateway(uint64(len(k))) + 1 + len(v) + sovGateway(uint64(len(v)))
1713
+			n += mapEntrySize + 1 + sovGateway(uint64(mapEntrySize))
1714
+		}
1715
+	}
1716
+	if m.XXX_unrecognized != nil {
1717
+		n += len(m.XXX_unrecognized)
1718
+	}
1686 1719
 	return n
1687 1720
 }
1688 1721
 
1689 1722
 func (m *SolveResponse) Size() (n int) {
1723
+	if m == nil {
1724
+		return 0
1725
+	}
1690 1726
 	var l int
1691 1727
 	_ = l
1692 1728
 	l = len(m.Ref)
... ...
@@ -1697,10 +2462,16 @@ func (m *SolveResponse) Size() (n int) {
1697 1697
 		l = m.Result.Size()
1698 1698
 		n += 1 + l + sovGateway(uint64(l))
1699 1699
 	}
1700
+	if m.XXX_unrecognized != nil {
1701
+		n += len(m.XXX_unrecognized)
1702
+	}
1700 1703
 	return n
1701 1704
 }
1702 1705
 
1703 1706
 func (m *ReadFileRequest) Size() (n int) {
1707
+	if m == nil {
1708
+		return 0
1709
+	}
1704 1710
 	var l int
1705 1711
 	_ = l
1706 1712
 	l = len(m.Ref)
... ...
@@ -1715,10 +2486,16 @@ func (m *ReadFileRequest) Size() (n int) {
1715 1715
 		l = m.Range.Size()
1716 1716
 		n += 1 + l + sovGateway(uint64(l))
1717 1717
 	}
1718
+	if m.XXX_unrecognized != nil {
1719
+		n += len(m.XXX_unrecognized)
1720
+	}
1718 1721
 	return n
1719 1722
 }
1720 1723
 
1721 1724
 func (m *FileRange) Size() (n int) {
1725
+	if m == nil {
1726
+		return 0
1727
+	}
1722 1728
 	var l int
1723 1729
 	_ = l
1724 1730
 	if m.Offset != 0 {
... ...
@@ -1727,20 +2504,32 @@ func (m *FileRange) Size() (n int) {
1727 1727
 	if m.Length != 0 {
1728 1728
 		n += 1 + sovGateway(uint64(m.Length))
1729 1729
 	}
1730
+	if m.XXX_unrecognized != nil {
1731
+		n += len(m.XXX_unrecognized)
1732
+	}
1730 1733
 	return n
1731 1734
 }
1732 1735
 
1733 1736
 func (m *ReadFileResponse) Size() (n int) {
1737
+	if m == nil {
1738
+		return 0
1739
+	}
1734 1740
 	var l int
1735 1741
 	_ = l
1736 1742
 	l = len(m.Data)
1737 1743
 	if l > 0 {
1738 1744
 		n += 1 + l + sovGateway(uint64(l))
1739 1745
 	}
1746
+	if m.XXX_unrecognized != nil {
1747
+		n += len(m.XXX_unrecognized)
1748
+	}
1740 1749
 	return n
1741 1750
 }
1742 1751
 
1743 1752
 func (m *ReadDirRequest) Size() (n int) {
1753
+	if m == nil {
1754
+		return 0
1755
+	}
1744 1756
 	var l int
1745 1757
 	_ = l
1746 1758
 	l = len(m.Ref)
... ...
@@ -1755,10 +2544,16 @@ func (m *ReadDirRequest) Size() (n int) {
1755 1755
 	if l > 0 {
1756 1756
 		n += 1 + l + sovGateway(uint64(l))
1757 1757
 	}
1758
+	if m.XXX_unrecognized != nil {
1759
+		n += len(m.XXX_unrecognized)
1760
+	}
1758 1761
 	return n
1759 1762
 }
1760 1763
 
1761 1764
 func (m *ReadDirResponse) Size() (n int) {
1765
+	if m == nil {
1766
+		return 0
1767
+	}
1762 1768
 	var l int
1763 1769
 	_ = l
1764 1770
 	if len(m.Entries) > 0 {
... ...
@@ -1767,10 +2562,16 @@ func (m *ReadDirResponse) Size() (n int) {
1767 1767
 			n += 1 + l + sovGateway(uint64(l))
1768 1768
 		}
1769 1769
 	}
1770
+	if m.XXX_unrecognized != nil {
1771
+		n += len(m.XXX_unrecognized)
1772
+	}
1770 1773
 	return n
1771 1774
 }
1772 1775
 
1773 1776
 func (m *StatFileRequest) Size() (n int) {
1777
+	if m == nil {
1778
+		return 0
1779
+	}
1774 1780
 	var l int
1775 1781
 	_ = l
1776 1782
 	l = len(m.Ref)
... ...
@@ -1781,26 +2582,44 @@ func (m *StatFileRequest) Size() (n int) {
1781 1781
 	if l > 0 {
1782 1782
 		n += 1 + l + sovGateway(uint64(l))
1783 1783
 	}
1784
+	if m.XXX_unrecognized != nil {
1785
+		n += len(m.XXX_unrecognized)
1786
+	}
1784 1787
 	return n
1785 1788
 }
1786 1789
 
1787 1790
 func (m *StatFileResponse) Size() (n int) {
1791
+	if m == nil {
1792
+		return 0
1793
+	}
1788 1794
 	var l int
1789 1795
 	_ = l
1790 1796
 	if m.Stat != nil {
1791 1797
 		l = m.Stat.Size()
1792 1798
 		n += 1 + l + sovGateway(uint64(l))
1793 1799
 	}
1800
+	if m.XXX_unrecognized != nil {
1801
+		n += len(m.XXX_unrecognized)
1802
+	}
1794 1803
 	return n
1795 1804
 }
1796 1805
 
1797 1806
 func (m *PingRequest) Size() (n int) {
1807
+	if m == nil {
1808
+		return 0
1809
+	}
1798 1810
 	var l int
1799 1811
 	_ = l
1812
+	if m.XXX_unrecognized != nil {
1813
+		n += len(m.XXX_unrecognized)
1814
+	}
1800 1815
 	return n
1801 1816
 }
1802 1817
 
1803 1818
 func (m *PongResponse) Size() (n int) {
1819
+	if m == nil {
1820
+		return 0
1821
+	}
1804 1822
 	var l int
1805 1823
 	_ = l
1806 1824
 	if len(m.FrontendAPICaps) > 0 {
... ...
@@ -1821,6 +2640,9 @@ func (m *PongResponse) Size() (n int) {
1821 1821
 			n += 1 + l + sovGateway(uint64(l))
1822 1822
 		}
1823 1823
 	}
1824
+	if m.XXX_unrecognized != nil {
1825
+		n += len(m.XXX_unrecognized)
1826
+	}
1824 1827
 	return n
1825 1828
 }
1826 1829
 
... ...
@@ -2058,6 +2880,7 @@ func (m *Result) Unmarshal(dAtA []byte) error {
2058 2058
 			if (iNdEx + skippy) > l {
2059 2059
 				return io.ErrUnexpectedEOF
2060 2060
 			}
2061
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
2061 2062
 			iNdEx += skippy
2062 2063
 		}
2063 2064
 	}
... ...
@@ -2226,6 +3049,7 @@ func (m *RefMap) Unmarshal(dAtA []byte) error {
2226 2226
 			if (iNdEx + skippy) > l {
2227 2227
 				return io.ErrUnexpectedEOF
2228 2228
 			}
2229
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
2229 2230
 			iNdEx += skippy
2230 2231
 		}
2231 2232
 	}
... ...
@@ -2324,7 +3148,7 @@ func (m *ReturnRequest) Unmarshal(dAtA []byte) error {
2324 2324
 				return io.ErrUnexpectedEOF
2325 2325
 			}
2326 2326
 			if m.Error == nil {
2327
-				m.Error = &google_rpc.Status{}
2327
+				m.Error = &rpc.Status{}
2328 2328
 			}
2329 2329
 			if err := m.Error.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
2330 2330
 				return err
... ...
@@ -2342,6 +3166,7 @@ func (m *ReturnRequest) Unmarshal(dAtA []byte) error {
2342 2342
 			if (iNdEx + skippy) > l {
2343 2343
 				return io.ErrUnexpectedEOF
2344 2344
 			}
2345
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
2345 2346
 			iNdEx += skippy
2346 2347
 		}
2347 2348
 	}
... ...
@@ -2392,6 +3217,7 @@ func (m *ReturnResponse) Unmarshal(dAtA []byte) error {
2392 2392
 			if (iNdEx + skippy) > l {
2393 2393
 				return io.ErrUnexpectedEOF
2394 2394
 			}
2395
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
2395 2396
 			iNdEx += skippy
2396 2397
 		}
2397 2398
 	}
... ...
@@ -2562,6 +3388,7 @@ func (m *ResolveImageConfigRequest) Unmarshal(dAtA []byte) error {
2562 2562
 			if (iNdEx + skippy) > l {
2563 2563
 				return io.ErrUnexpectedEOF
2564 2564
 			}
2565
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
2565 2566
 			iNdEx += skippy
2566 2567
 		}
2567 2568
 	}
... ...
@@ -2672,6 +3499,7 @@ func (m *ResolveImageConfigResponse) Unmarshal(dAtA []byte) error {
2672 2672
 			if (iNdEx + skippy) > l {
2673 2673
 				return io.ErrUnexpectedEOF
2674 2674
 			}
2675
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
2675 2676
 			iNdEx += skippy
2676 2677
 		}
2677 2678
 	}
... ...
@@ -2892,7 +3720,7 @@ func (m *SolveRequest) Unmarshal(dAtA []byte) error {
2892 2892
 			iNdEx = postIndex
2893 2893
 		case 4:
2894 2894
 			if wireType != 2 {
2895
-				return fmt.Errorf("proto: wrong wireType = %d for field ImportCacheRefs", wireType)
2895
+				return fmt.Errorf("proto: wrong wireType = %d for field ImportCacheRefsDeprecated", wireType)
2896 2896
 			}
2897 2897
 			var stringLen uint64
2898 2898
 			for shift := uint(0); ; shift += 7 {
... ...
@@ -2917,7 +3745,7 @@ func (m *SolveRequest) Unmarshal(dAtA []byte) error {
2917 2917
 			if postIndex > l {
2918 2918
 				return io.ErrUnexpectedEOF
2919 2919
 			}
2920
-			m.ImportCacheRefs = append(m.ImportCacheRefs, string(dAtA[iNdEx:postIndex]))
2920
+			m.ImportCacheRefsDeprecated = append(m.ImportCacheRefsDeprecated, string(dAtA[iNdEx:postIndex]))
2921 2921
 			iNdEx = postIndex
2922 2922
 		case 5:
2923 2923
 			if wireType != 0 {
... ...
@@ -2990,6 +3818,235 @@ func (m *SolveRequest) Unmarshal(dAtA []byte) error {
2990 2990
 				m.ExporterAttr = []byte{}
2991 2991
 			}
2992 2992
 			iNdEx = postIndex
2993
+		case 12:
2994
+			if wireType != 2 {
2995
+				return fmt.Errorf("proto: wrong wireType = %d for field CacheImports", wireType)
2996
+			}
2997
+			var msglen int
2998
+			for shift := uint(0); ; shift += 7 {
2999
+				if shift >= 64 {
3000
+					return ErrIntOverflowGateway
3001
+				}
3002
+				if iNdEx >= l {
3003
+					return io.ErrUnexpectedEOF
3004
+				}
3005
+				b := dAtA[iNdEx]
3006
+				iNdEx++
3007
+				msglen |= (int(b) & 0x7F) << shift
3008
+				if b < 0x80 {
3009
+					break
3010
+				}
3011
+			}
3012
+			if msglen < 0 {
3013
+				return ErrInvalidLengthGateway
3014
+			}
3015
+			postIndex := iNdEx + msglen
3016
+			if postIndex > l {
3017
+				return io.ErrUnexpectedEOF
3018
+			}
3019
+			m.CacheImports = append(m.CacheImports, &CacheOptionsEntry{})
3020
+			if err := m.CacheImports[len(m.CacheImports)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
3021
+				return err
3022
+			}
3023
+			iNdEx = postIndex
3024
+		default:
3025
+			iNdEx = preIndex
3026
+			skippy, err := skipGateway(dAtA[iNdEx:])
3027
+			if err != nil {
3028
+				return err
3029
+			}
3030
+			if skippy < 0 {
3031
+				return ErrInvalidLengthGateway
3032
+			}
3033
+			if (iNdEx + skippy) > l {
3034
+				return io.ErrUnexpectedEOF
3035
+			}
3036
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3037
+			iNdEx += skippy
3038
+		}
3039
+	}
3040
+
3041
+	if iNdEx > l {
3042
+		return io.ErrUnexpectedEOF
3043
+	}
3044
+	return nil
3045
+}
3046
+func (m *CacheOptionsEntry) Unmarshal(dAtA []byte) error {
3047
+	l := len(dAtA)
3048
+	iNdEx := 0
3049
+	for iNdEx < l {
3050
+		preIndex := iNdEx
3051
+		var wire uint64
3052
+		for shift := uint(0); ; shift += 7 {
3053
+			if shift >= 64 {
3054
+				return ErrIntOverflowGateway
3055
+			}
3056
+			if iNdEx >= l {
3057
+				return io.ErrUnexpectedEOF
3058
+			}
3059
+			b := dAtA[iNdEx]
3060
+			iNdEx++
3061
+			wire |= (uint64(b) & 0x7F) << shift
3062
+			if b < 0x80 {
3063
+				break
3064
+			}
3065
+		}
3066
+		fieldNum := int32(wire >> 3)
3067
+		wireType := int(wire & 0x7)
3068
+		if wireType == 4 {
3069
+			return fmt.Errorf("proto: CacheOptionsEntry: wiretype end group for non-group")
3070
+		}
3071
+		if fieldNum <= 0 {
3072
+			return fmt.Errorf("proto: CacheOptionsEntry: illegal tag %d (wire type %d)", fieldNum, wire)
3073
+		}
3074
+		switch fieldNum {
3075
+		case 1:
3076
+			if wireType != 2 {
3077
+				return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
3078
+			}
3079
+			var stringLen uint64
3080
+			for shift := uint(0); ; shift += 7 {
3081
+				if shift >= 64 {
3082
+					return ErrIntOverflowGateway
3083
+				}
3084
+				if iNdEx >= l {
3085
+					return io.ErrUnexpectedEOF
3086
+				}
3087
+				b := dAtA[iNdEx]
3088
+				iNdEx++
3089
+				stringLen |= (uint64(b) & 0x7F) << shift
3090
+				if b < 0x80 {
3091
+					break
3092
+				}
3093
+			}
3094
+			intStringLen := int(stringLen)
3095
+			if intStringLen < 0 {
3096
+				return ErrInvalidLengthGateway
3097
+			}
3098
+			postIndex := iNdEx + intStringLen
3099
+			if postIndex > l {
3100
+				return io.ErrUnexpectedEOF
3101
+			}
3102
+			m.Type = string(dAtA[iNdEx:postIndex])
3103
+			iNdEx = postIndex
3104
+		case 2:
3105
+			if wireType != 2 {
3106
+				return fmt.Errorf("proto: wrong wireType = %d for field Attrs", wireType)
3107
+			}
3108
+			var msglen int
3109
+			for shift := uint(0); ; shift += 7 {
3110
+				if shift >= 64 {
3111
+					return ErrIntOverflowGateway
3112
+				}
3113
+				if iNdEx >= l {
3114
+					return io.ErrUnexpectedEOF
3115
+				}
3116
+				b := dAtA[iNdEx]
3117
+				iNdEx++
3118
+				msglen |= (int(b) & 0x7F) << shift
3119
+				if b < 0x80 {
3120
+					break
3121
+				}
3122
+			}
3123
+			if msglen < 0 {
3124
+				return ErrInvalidLengthGateway
3125
+			}
3126
+			postIndex := iNdEx + msglen
3127
+			if postIndex > l {
3128
+				return io.ErrUnexpectedEOF
3129
+			}
3130
+			if m.Attrs == nil {
3131
+				m.Attrs = make(map[string]string)
3132
+			}
3133
+			var mapkey string
3134
+			var mapvalue string
3135
+			for iNdEx < postIndex {
3136
+				entryPreIndex := iNdEx
3137
+				var wire uint64
3138
+				for shift := uint(0); ; shift += 7 {
3139
+					if shift >= 64 {
3140
+						return ErrIntOverflowGateway
3141
+					}
3142
+					if iNdEx >= l {
3143
+						return io.ErrUnexpectedEOF
3144
+					}
3145
+					b := dAtA[iNdEx]
3146
+					iNdEx++
3147
+					wire |= (uint64(b) & 0x7F) << shift
3148
+					if b < 0x80 {
3149
+						break
3150
+					}
3151
+				}
3152
+				fieldNum := int32(wire >> 3)
3153
+				if fieldNum == 1 {
3154
+					var stringLenmapkey uint64
3155
+					for shift := uint(0); ; shift += 7 {
3156
+						if shift >= 64 {
3157
+							return ErrIntOverflowGateway
3158
+						}
3159
+						if iNdEx >= l {
3160
+							return io.ErrUnexpectedEOF
3161
+						}
3162
+						b := dAtA[iNdEx]
3163
+						iNdEx++
3164
+						stringLenmapkey |= (uint64(b) & 0x7F) << shift
3165
+						if b < 0x80 {
3166
+							break
3167
+						}
3168
+					}
3169
+					intStringLenmapkey := int(stringLenmapkey)
3170
+					if intStringLenmapkey < 0 {
3171
+						return ErrInvalidLengthGateway
3172
+					}
3173
+					postStringIndexmapkey := iNdEx + intStringLenmapkey
3174
+					if postStringIndexmapkey > l {
3175
+						return io.ErrUnexpectedEOF
3176
+					}
3177
+					mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
3178
+					iNdEx = postStringIndexmapkey
3179
+				} else if fieldNum == 2 {
3180
+					var stringLenmapvalue uint64
3181
+					for shift := uint(0); ; shift += 7 {
3182
+						if shift >= 64 {
3183
+							return ErrIntOverflowGateway
3184
+						}
3185
+						if iNdEx >= l {
3186
+							return io.ErrUnexpectedEOF
3187
+						}
3188
+						b := dAtA[iNdEx]
3189
+						iNdEx++
3190
+						stringLenmapvalue |= (uint64(b) & 0x7F) << shift
3191
+						if b < 0x80 {
3192
+							break
3193
+						}
3194
+					}
3195
+					intStringLenmapvalue := int(stringLenmapvalue)
3196
+					if intStringLenmapvalue < 0 {
3197
+						return ErrInvalidLengthGateway
3198
+					}
3199
+					postStringIndexmapvalue := iNdEx + intStringLenmapvalue
3200
+					if postStringIndexmapvalue > l {
3201
+						return io.ErrUnexpectedEOF
3202
+					}
3203
+					mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue])
3204
+					iNdEx = postStringIndexmapvalue
3205
+				} else {
3206
+					iNdEx = entryPreIndex
3207
+					skippy, err := skipGateway(dAtA[iNdEx:])
3208
+					if err != nil {
3209
+						return err
3210
+					}
3211
+					if skippy < 0 {
3212
+						return ErrInvalidLengthGateway
3213
+					}
3214
+					if (iNdEx + skippy) > postIndex {
3215
+						return io.ErrUnexpectedEOF
3216
+					}
3217
+					iNdEx += skippy
3218
+				}
3219
+			}
3220
+			m.Attrs[mapkey] = mapvalue
3221
+			iNdEx = postIndex
2993 3222
 		default:
2994 3223
 			iNdEx = preIndex
2995 3224
 			skippy, err := skipGateway(dAtA[iNdEx:])
... ...
@@ -3002,6 +4059,7 @@ func (m *SolveRequest) Unmarshal(dAtA []byte) error {
3002 3002
 			if (iNdEx + skippy) > l {
3003 3003
 				return io.ErrUnexpectedEOF
3004 3004
 			}
3005
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3005 3006
 			iNdEx += skippy
3006 3007
 		}
3007 3008
 	}
... ...
@@ -3114,6 +4172,7 @@ func (m *SolveResponse) Unmarshal(dAtA []byte) error {
3114 3114
 			if (iNdEx + skippy) > l {
3115 3115
 				return io.ErrUnexpectedEOF
3116 3116
 			}
3117
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3117 3118
 			iNdEx += skippy
3118 3119
 		}
3119 3120
 	}
... ...
@@ -3255,6 +4314,7 @@ func (m *ReadFileRequest) Unmarshal(dAtA []byte) error {
3255 3255
 			if (iNdEx + skippy) > l {
3256 3256
 				return io.ErrUnexpectedEOF
3257 3257
 			}
3258
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3258 3259
 			iNdEx += skippy
3259 3260
 		}
3260 3261
 	}
... ...
@@ -3343,6 +4403,7 @@ func (m *FileRange) Unmarshal(dAtA []byte) error {
3343 3343
 			if (iNdEx + skippy) > l {
3344 3344
 				return io.ErrUnexpectedEOF
3345 3345
 			}
3346
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3346 3347
 			iNdEx += skippy
3347 3348
 		}
3348 3349
 	}
... ...
@@ -3424,6 +4485,7 @@ func (m *ReadFileResponse) Unmarshal(dAtA []byte) error {
3424 3424
 			if (iNdEx + skippy) > l {
3425 3425
 				return io.ErrUnexpectedEOF
3426 3426
 			}
3427
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3427 3428
 			iNdEx += skippy
3428 3429
 		}
3429 3430
 	}
... ...
@@ -3561,6 +4623,7 @@ func (m *ReadDirRequest) Unmarshal(dAtA []byte) error {
3561 3561
 			if (iNdEx + skippy) > l {
3562 3562
 				return io.ErrUnexpectedEOF
3563 3563
 			}
3564
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3564 3565
 			iNdEx += skippy
3565 3566
 		}
3566 3567
 	}
... ...
@@ -3625,7 +4688,7 @@ func (m *ReadDirResponse) Unmarshal(dAtA []byte) error {
3625 3625
 			if postIndex > l {
3626 3626
 				return io.ErrUnexpectedEOF
3627 3627
 			}
3628
-			m.Entries = append(m.Entries, &fsutil_types.Stat{})
3628
+			m.Entries = append(m.Entries, &types.Stat{})
3629 3629
 			if err := m.Entries[len(m.Entries)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
3630 3630
 				return err
3631 3631
 			}
... ...
@@ -3642,6 +4705,7 @@ func (m *ReadDirResponse) Unmarshal(dAtA []byte) error {
3642 3642
 			if (iNdEx + skippy) > l {
3643 3643
 				return io.ErrUnexpectedEOF
3644 3644
 			}
3645
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3645 3646
 			iNdEx += skippy
3646 3647
 		}
3647 3648
 	}
... ...
@@ -3750,6 +4814,7 @@ func (m *StatFileRequest) Unmarshal(dAtA []byte) error {
3750 3750
 			if (iNdEx + skippy) > l {
3751 3751
 				return io.ErrUnexpectedEOF
3752 3752
 			}
3753
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3753 3754
 			iNdEx += skippy
3754 3755
 		}
3755 3756
 	}
... ...
@@ -3815,7 +4880,7 @@ func (m *StatFileResponse) Unmarshal(dAtA []byte) error {
3815 3815
 				return io.ErrUnexpectedEOF
3816 3816
 			}
3817 3817
 			if m.Stat == nil {
3818
-				m.Stat = &fsutil_types.Stat{}
3818
+				m.Stat = &types.Stat{}
3819 3819
 			}
3820 3820
 			if err := m.Stat.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
3821 3821
 				return err
... ...
@@ -3833,6 +4898,7 @@ func (m *StatFileResponse) Unmarshal(dAtA []byte) error {
3833 3833
 			if (iNdEx + skippy) > l {
3834 3834
 				return io.ErrUnexpectedEOF
3835 3835
 			}
3836
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3836 3837
 			iNdEx += skippy
3837 3838
 		}
3838 3839
 	}
... ...
@@ -3883,6 +4949,7 @@ func (m *PingRequest) Unmarshal(dAtA []byte) error {
3883 3883
 			if (iNdEx + skippy) > l {
3884 3884
 				return io.ErrUnexpectedEOF
3885 3885
 			}
3886
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
3886 3887
 			iNdEx += skippy
3887 3888
 		}
3888 3889
 	}
... ...
@@ -3947,7 +5014,7 @@ func (m *PongResponse) Unmarshal(dAtA []byte) error {
3947 3947
 			if postIndex > l {
3948 3948
 				return io.ErrUnexpectedEOF
3949 3949
 			}
3950
-			m.FrontendAPICaps = append(m.FrontendAPICaps, moby_buildkit_v1_apicaps.APICap{})
3950
+			m.FrontendAPICaps = append(m.FrontendAPICaps, pb1.APICap{})
3951 3951
 			if err := m.FrontendAPICaps[len(m.FrontendAPICaps)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
3952 3952
 				return err
3953 3953
 			}
... ...
@@ -3978,7 +5045,7 @@ func (m *PongResponse) Unmarshal(dAtA []byte) error {
3978 3978
 			if postIndex > l {
3979 3979
 				return io.ErrUnexpectedEOF
3980 3980
 			}
3981
-			m.LLBCaps = append(m.LLBCaps, moby_buildkit_v1_apicaps.APICap{})
3981
+			m.LLBCaps = append(m.LLBCaps, pb1.APICap{})
3982 3982
 			if err := m.LLBCaps[len(m.LLBCaps)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
3983 3983
 				return err
3984 3984
 			}
... ...
@@ -4009,7 +5076,7 @@ func (m *PongResponse) Unmarshal(dAtA []byte) error {
4009 4009
 			if postIndex > l {
4010 4010
 				return io.ErrUnexpectedEOF
4011 4011
 			}
4012
-			m.Workers = append(m.Workers, &moby_buildkit_v1_types.WorkerRecord{})
4012
+			m.Workers = append(m.Workers, &types1.WorkerRecord{})
4013 4013
 			if err := m.Workers[len(m.Workers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
4014 4014
 				return err
4015 4015
 			}
... ...
@@ -4026,6 +5093,7 @@ func (m *PongResponse) Unmarshal(dAtA []byte) error {
4026 4026
 			if (iNdEx + skippy) > l {
4027 4027
 				return io.ErrUnexpectedEOF
4028 4028
 			}
4029
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
4029 4030
 			iNdEx += skippy
4030 4031
 		}
4031 4032
 	}
... ...
@@ -4140,80 +5208,85 @@ var (
4140 4140
 	ErrIntOverflowGateway   = fmt.Errorf("proto: integer overflow")
4141 4141
 )
4142 4142
 
4143
-func init() { proto.RegisterFile("gateway.proto", fileDescriptorGateway) }
4144
-
4145
-var fileDescriptorGateway = []byte{
4146
-	// 1144 bytes of a gzipped FileDescriptorProto
4147
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xcf, 0x4f, 0x1b, 0xc7,
4148
-	0x17, 0x67, 0xb1, 0x8d, 0xed, 0x67, 0x03, 0xfe, 0x8e, 0xbe, 0xaa, 0x36, 0x7b, 0x20, 0xee, 0xaa,
4149
-	0xa2, 0x0e, 0x21, 0xbb, 0x2a, 0x69, 0x45, 0x4a, 0xa4, 0xa4, 0x31, 0x04, 0x85, 0xd6, 0x34, 0xd6,
4150
-	0xe4, 0x10, 0x29, 0x6a, 0xa5, 0xae, 0xed, 0xf1, 0x32, 0x62, 0xbd, 0xb3, 0x9d, 0x1d, 0x43, 0x51,
4151
-	0x2f, 0x6d, 0x4f, 0xbd, 0xf7, 0x9f, 0xca, 0xad, 0x3d, 0xf7, 0x10, 0x55, 0xdc, 0xfa, 0x5f, 0x54,
4152
-	0xf3, 0x63, 0xed, 0xc5, 0x80, 0x81, 0xd3, 0xce, 0x9b, 0x79, 0x9f, 0xf7, 0x3e, 0x6f, 0xde, 0x8f,
4153
-	0x59, 0x58, 0x0e, 0x03, 0x41, 0x4e, 0x83, 0x33, 0x2f, 0xe1, 0x4c, 0x30, 0x74, 0x6f, 0xc4, 0x7a,
4154
-	0x67, 0x5e, 0x6f, 0x4c, 0xa3, 0xc1, 0x31, 0x15, 0xde, 0xc9, 0x67, 0xde, 0x90, 0xb3, 0x58, 0x90,
4155
-	0x78, 0xe0, 0x3c, 0x0a, 0xa9, 0x38, 0x1a, 0xf7, 0xbc, 0x3e, 0x1b, 0xf9, 0x21, 0x0b, 0x99, 0xaf,
4156
-	0x10, 0xbd, 0xf1, 0x50, 0x49, 0x4a, 0x50, 0x2b, 0x6d, 0xc9, 0xd9, 0x9a, 0x55, 0x0f, 0x19, 0x0b,
4157
-	0x23, 0x12, 0x24, 0x34, 0x35, 0x4b, 0x9f, 0x27, 0x7d, 0x3f, 0x15, 0x81, 0x18, 0xa7, 0x06, 0xb3,
4158
-	0x99, 0xc3, 0x48, 0x22, 0x7e, 0x46, 0xc4, 0x4f, 0x59, 0x74, 0x42, 0xb8, 0x9f, 0xf4, 0x7c, 0x96,
4159
-	0x64, 0xda, 0xfe, 0xb5, 0xda, 0x41, 0x42, 0x7d, 0x71, 0x96, 0x90, 0xd4, 0x3f, 0x65, 0xfc, 0x98,
4160
-	0x70, 0x03, 0x78, 0x7c, 0x2d, 0x60, 0x2c, 0x68, 0x24, 0x51, 0xfd, 0x20, 0x49, 0xa5, 0x13, 0xf9,
4161
-	0x35, 0xa0, 0x7c, 0xd8, 0x82, 0xc5, 0x34, 0x15, 0x94, 0x86, 0xd4, 0x1f, 0xa6, 0x0a, 0xa3, 0xbd,
4162
-	0xc8, 0x20, 0xb4, 0xba, 0xfb, 0xaf, 0x05, 0x4b, 0x98, 0xa4, 0xe3, 0x48, 0x20, 0x04, 0x05, 0x4e,
4163
-	0x86, 0xb6, 0xd5, 0xb4, 0x5a, 0xd5, 0x57, 0x0b, 0x58, 0x0a, 0x68, 0x1b, 0x8a, 0x9c, 0x0c, 0x53,
4164
-	0x7b, 0xb1, 0x69, 0xb5, 0x6a, 0x5b, 0x1f, 0x7b, 0xd7, 0x5e, 0xb7, 0x87, 0xc9, 0xf0, 0x30, 0x48,
4165
-	0x5e, 0x2d, 0x60, 0x05, 0x40, 0xdf, 0x40, 0x65, 0x44, 0x44, 0x30, 0x08, 0x44, 0x60, 0x43, 0xb3,
4166
-	0xd0, 0xaa, 0x6d, 0xf9, 0x73, 0xc1, 0x92, 0x81, 0x77, 0x68, 0x10, 0x2f, 0x63, 0xc1, 0xcf, 0xf0,
4167
-	0xc4, 0x80, 0xf3, 0x14, 0x96, 0x2f, 0x1c, 0xa1, 0x06, 0x14, 0x8e, 0xc9, 0x99, 0xa6, 0x8a, 0xe5,
4168
-	0x12, 0xfd, 0x1f, 0x4a, 0x27, 0x41, 0x34, 0x26, 0x8a, 0x69, 0x1d, 0x6b, 0x61, 0x67, 0xf1, 0x89,
4169
-	0xd5, 0xae, 0xc0, 0x12, 0x57, 0xe6, 0xdd, 0xdf, 0x54, 0xac, 0x92, 0x26, 0x7a, 0x6e, 0xe2, 0xb2,
4170
-	0x14, 0xb5, 0x87, 0x37, 0xc6, 0x25, 0x3f, 0xa9, 0xa6, 0xa5, 0x80, 0xce, 0x36, 0x54, 0x27, 0x5b,
4171
-	0x37, 0xd1, 0xa9, 0xe6, 0xe8, 0xb8, 0x02, 0x96, 0x31, 0x11, 0x63, 0x1e, 0x63, 0xf2, 0xe3, 0x98,
4172
-	0xa4, 0x02, 0x7d, 0x99, 0xf1, 0x53, 0xf8, 0x9b, 0x2e, 0x59, 0x2a, 0x62, 0x03, 0x40, 0x2d, 0x28,
4173
-	0x11, 0xce, 0x19, 0x37, 0xe9, 0x41, 0x9e, 0x2e, 0x54, 0x8f, 0x27, 0x7d, 0xef, 0x8d, 0x2a, 0x54,
4174
-	0xac, 0x15, 0xdc, 0x06, 0xac, 0x64, 0x5e, 0xd3, 0x84, 0xc5, 0x29, 0x71, 0xff, 0xb0, 0xe0, 0x1e,
4175
-	0x26, 0xaa, 0x4e, 0x0f, 0x46, 0x41, 0x48, 0x76, 0x59, 0x3c, 0xa4, 0x61, 0x46, 0xaa, 0x01, 0x05,
4176
-	0x9c, 0xd5, 0x02, 0x96, 0x4b, 0xd4, 0x82, 0x4a, 0x37, 0x0a, 0xc4, 0x90, 0xf1, 0x91, 0x71, 0x57,
4177
-	0xf7, 0x92, 0x9e, 0x97, 0xed, 0xe1, 0xc9, 0x29, 0x6a, 0x42, 0xcd, 0x18, 0x3e, 0x64, 0x03, 0x62,
4178
-	0x17, 0x94, 0x8d, 0xfc, 0x16, 0xb2, 0xa1, 0xdc, 0x61, 0xe1, 0xb7, 0xc1, 0x88, 0xd8, 0x45, 0x75,
4179
-	0x9a, 0x89, 0xee, 0x2f, 0x16, 0x38, 0x57, 0xb1, 0xd2, 0xa4, 0xd1, 0xd7, 0xb0, 0xb4, 0x47, 0x43,
4180
-	0x92, 0xea, 0xbb, 0xaa, 0xb6, 0xb7, 0xde, 0x7f, 0xb8, 0xbf, 0xf0, 0xf7, 0x87, 0xfb, 0x1b, 0xb9,
4181
-	0xa2, 0x67, 0x09, 0x89, 0xfb, 0x2c, 0x16, 0x01, 0x8d, 0x09, 0x97, 0xbd, 0xfb, 0x68, 0xa0, 0x20,
4182
-	0x9e, 0x46, 0x62, 0x63, 0x01, 0x7d, 0x04, 0x4b, 0xda, 0xba, 0x29, 0x19, 0x23, 0xb9, 0xbf, 0x17,
4183
-	0xa0, 0xfe, 0x46, 0x12, 0xc8, 0xee, 0xc2, 0x03, 0xd8, 0x23, 0x43, 0x1a, 0x53, 0x41, 0x59, 0x6c,
4184
-	0x92, 0xb4, 0x22, 0x63, 0x9f, 0xee, 0xe2, 0x9c, 0x06, 0x72, 0xa0, 0xb2, 0x6f, 0x12, 0x66, 0xd2,
4185
-	0x3f, 0x91, 0xd1, 0x3b, 0xa8, 0x65, 0xeb, 0xd7, 0x89, 0xb0, 0x0b, 0xaa, 0xfc, 0x9e, 0xcc, 0xc9,
4186
-	0x78, 0x9e, 0x89, 0x97, 0x83, 0xea, 0x5a, 0xcc, 0x1b, 0x43, 0x2d, 0x58, 0x3d, 0x18, 0x25, 0x8c,
4187
-	0x8b, 0xdd, 0xa0, 0x7f, 0x44, 0x64, 0x75, 0xda, 0xc5, 0x66, 0xa1, 0x55, 0xc5, 0xb3, 0xdb, 0x68,
4188
-	0x13, 0xfe, 0x17, 0x44, 0x11, 0x3b, 0x35, 0xe5, 0xa4, 0x0a, 0xc3, 0x2e, 0x35, 0xad, 0x56, 0x05,
4189
-	0x5f, 0x3e, 0x90, 0xb5, 0xbc, 0x4f, 0xe3, 0x20, 0xb2, 0x41, 0x69, 0x68, 0x01, 0xb9, 0x50, 0x7f,
4190
-	0xf9, 0x93, 0x34, 0x4b, 0xf8, 0x0b, 0x21, 0xb8, 0x5d, 0x53, 0x97, 0x78, 0x61, 0xcf, 0x79, 0x06,
4191
-	0x8d, 0x59, 0xca, 0x77, 0xea, 0x95, 0xef, 0x60, 0xd9, 0xc4, 0x6f, 0xf2, 0xdf, 0xc8, 0x8d, 0x28,
4192
-	0x3d, 0xa0, 0xa6, 0xdd, 0x53, 0xb8, 0x63, 0xf7, 0xb8, 0x3f, 0xc3, 0x2a, 0x26, 0xc1, 0x60, 0x9f,
4193
-	0x46, 0xe4, 0xfa, 0xb2, 0x97, 0xc9, 0xa4, 0x11, 0xe9, 0x06, 0xe2, 0x68, 0x92, 0x4c, 0x23, 0xa3,
4194
-	0x1d, 0x28, 0xe1, 0x20, 0x0e, 0x89, 0x71, 0xfd, 0xc9, 0x1c, 0xd7, 0xca, 0x89, 0xd4, 0xc5, 0x1a,
4195
-	0xe2, 0x3e, 0x85, 0xea, 0x64, 0x4f, 0x96, 0xe2, 0xeb, 0xe1, 0x30, 0x25, 0xba, 0xac, 0x0b, 0xd8,
4196
-	0x48, 0x72, 0xbf, 0x43, 0xe2, 0xd0, 0xb8, 0x2e, 0x60, 0x23, 0xb9, 0xeb, 0xd0, 0x98, 0x32, 0x37,
4197
-	0x57, 0x83, 0xa0, 0xb8, 0x27, 0x87, 0xad, 0xa5, 0xf2, 0xa0, 0xd6, 0xee, 0x40, 0x76, 0x7d, 0x30,
4198
-	0xd8, 0xa3, 0xfc, 0xfa, 0x00, 0x6d, 0x28, 0xef, 0x51, 0x9e, 0x8b, 0x2f, 0x13, 0xd1, 0x3a, 0xac,
4199
-	0x1c, 0xc4, 0xfd, 0x68, 0x3c, 0x90, 0xd1, 0x0a, 0xc2, 0x63, 0xd3, 0xca, 0x33, 0xbb, 0xee, 0x73,
4200
-	0x7d, 0x8f, 0xca, 0x8b, 0x21, 0xb3, 0x09, 0x65, 0x12, 0x0b, 0x4e, 0x49, 0x36, 0x61, 0x91, 0xa7,
4201
-	0x1f, 0x20, 0x4f, 0x3d, 0x40, 0x6a, 0x38, 0xe1, 0x4c, 0xc5, 0xdd, 0x86, 0x55, 0xb9, 0x31, 0x3f,
4202
-	0x11, 0x08, 0x8a, 0x39, 0x92, 0x6a, 0xed, 0xee, 0x40, 0x63, 0x0a, 0x34, 0xae, 0xd7, 0xa1, 0x28,
4203
-	0x9f, 0x37, 0xd3, 0xa7, 0x57, 0xf9, 0x55, 0xe7, 0xee, 0x32, 0xd4, 0xba, 0x34, 0xce, 0x06, 0x9e,
4204
-	0x7b, 0x6e, 0x41, 0xbd, 0xcb, 0xe2, 0xe9, 0xa8, 0xe9, 0xc2, 0x6a, 0x56, 0xbb, 0x2f, 0xba, 0x07,
4205
-	0xbb, 0x41, 0x92, 0x85, 0xd2, 0xbc, 0x9c, 0x66, 0xf3, 0x12, 0x7b, 0x5a, 0xb1, 0x5d, 0x94, 0x53,
4206
-	0x09, 0xcf, 0xc2, 0xd1, 0x57, 0x50, 0xee, 0x74, 0xda, 0xca, 0xd2, 0xe2, 0x9d, 0x2c, 0x65, 0x30,
4207
-	0xf4, 0x0c, 0xca, 0x6f, 0xd5, 0x0f, 0x42, 0x6a, 0x26, 0xc7, 0x15, 0x25, 0xa7, 0x03, 0xd5, 0x6a,
4208
-	0x98, 0xf4, 0x19, 0x1f, 0xe0, 0x0c, 0xb4, 0xf5, 0x67, 0x09, 0xaa, 0x9d, 0x4e, 0xbb, 0xcd, 0xe9,
4209
-	0x20, 0x24, 0xe8, 0x57, 0x0b, 0xd0, 0xe5, 0x59, 0x8b, 0x3e, 0x9f, 0xdf, 0x41, 0x57, 0x3f, 0x18,
4210
-	0xce, 0x17, 0x77, 0x44, 0x99, 0x5b, 0x7e, 0x07, 0x25, 0xd5, 0xe1, 0xe8, 0xd3, 0x5b, 0xce, 0x40,
4211
-	0xa7, 0x75, 0xb3, 0xa2, 0xb1, 0xdd, 0x87, 0x4a, 0xd6, 0x25, 0x68, 0x63, 0x2e, 0xbd, 0x0b, 0x43,
4212
-	0xc0, 0x79, 0x78, 0x2b, 0x5d, 0xe3, 0xe4, 0x07, 0x28, 0x9b, 0xe2, 0x47, 0x0f, 0x6e, 0xc0, 0x4d,
4213
-	0xdb, 0xd0, 0xd9, 0xb8, 0x8d, 0xea, 0x34, 0x8c, 0xac, 0xc8, 0xe7, 0x86, 0x31, 0xd3, 0x42, 0x73,
4214
-	0xc3, 0xb8, 0xd4, 0x35, 0x6f, 0xa1, 0x28, 0xbb, 0x01, 0xad, 0xcf, 0x01, 0xe5, 0xda, 0xc5, 0x99,
4215
-	0x97, 0xae, 0x0b, 0x6d, 0xf4, 0xbd, 0xfc, 0xe5, 0x52, 0xcf, 0x48, 0x6b, 0x6e, 0xcc, 0xb9, 0x3f,
4216
-	0x22, 0xe7, 0xc1, 0x2d, 0x34, 0xb5, 0xf9, 0x76, 0xfd, 0xfd, 0xf9, 0x9a, 0xf5, 0xd7, 0xf9, 0x9a,
4217
-	0xf5, 0xcf, 0xf9, 0x9a, 0xd5, 0x5b, 0x52, 0xff, 0xb4, 0x8f, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff,
4218
-	0x80, 0x7e, 0xd2, 0xb5, 0x25, 0x0c, 0x00, 0x00,
4143
+func init() { proto.RegisterFile("gateway.proto", fileDescriptor_gateway_eff078cadb286ceb) }
4144
+
4145
+var fileDescriptor_gateway_eff078cadb286ceb = []byte{
4146
+	// 1224 bytes of a gzipped FileDescriptorProto
4147
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xcd, 0x6e, 0xdb, 0xc6,
4148
+	0x13, 0x0f, 0x23, 0xc9, 0xb6, 0xc6, 0x72, 0xa2, 0x2c, 0xfe, 0xf8, 0x83, 0xe1, 0x21, 0x51, 0x89,
4149
+	0xc2, 0x55, 0x12, 0x87, 0x44, 0x9d, 0x16, 0x4e, 0x93, 0x22, 0x69, 0x14, 0x27, 0x88, 0x5b, 0xbb,
4150
+	0x11, 0x36, 0x05, 0x02, 0x04, 0x2d, 0xd0, 0x95, 0xb8, 0x62, 0x16, 0xa1, 0xb8, 0xec, 0x72, 0x15,
4151
+	0xd7, 0xe8, 0xa5, 0xed, 0x2b, 0xf4, 0x45, 0xfa, 0x18, 0xb9, 0xb5, 0xe7, 0x1e, 0x82, 0xc2, 0xb7,
4152
+	0x5e, 0xfa, 0x0c, 0xc5, 0x7e, 0x50, 0xa2, 0x3f, 0x44, 0x5b, 0x27, 0xee, 0x2c, 0xe7, 0x37, 0xf3,
4153
+	0x9b, 0xd9, 0x99, 0xd9, 0x85, 0xb5, 0x98, 0x48, 0xba, 0x4f, 0x0e, 0x82, 0x4c, 0x70, 0xc9, 0xd1,
4154
+	0xd5, 0x31, 0x1f, 0x1c, 0x04, 0x83, 0x09, 0x4b, 0xa2, 0x37, 0x4c, 0x06, 0x6f, 0x3f, 0x0e, 0x46,
4155
+	0x82, 0xa7, 0x92, 0xa6, 0x91, 0x77, 0x3b, 0x66, 0xf2, 0xf5, 0x64, 0x10, 0x0c, 0xf9, 0x38, 0x8c,
4156
+	0x79, 0xcc, 0x43, 0x8d, 0x18, 0x4c, 0x46, 0x5a, 0xd2, 0x82, 0x5e, 0x19, 0x4b, 0xde, 0xe6, 0x71,
4157
+	0xf5, 0x98, 0xf3, 0x38, 0xa1, 0x24, 0x63, 0xb9, 0x5d, 0x86, 0x22, 0x1b, 0x86, 0xb9, 0x24, 0x72,
4158
+	0x92, 0x5b, 0xcc, 0x46, 0x09, 0xa3, 0x88, 0x84, 0x05, 0x91, 0x30, 0xe7, 0xc9, 0x5b, 0x2a, 0xc2,
4159
+	0x6c, 0x10, 0xf2, 0xac, 0xd0, 0x0e, 0xe7, 0x6a, 0x93, 0x8c, 0x85, 0xf2, 0x20, 0xa3, 0x79, 0xb8,
4160
+	0xcf, 0xc5, 0x1b, 0x2a, 0x2c, 0xe0, 0xce, 0x5c, 0xc0, 0x44, 0xb2, 0x44, 0xa1, 0x86, 0x24, 0xcb,
4161
+	0x95, 0x13, 0xf5, 0xb5, 0xa0, 0x72, 0xd8, 0x92, 0xa7, 0x2c, 0x97, 0x8c, 0xc5, 0x2c, 0x1c, 0xe5,
4162
+	0x1a, 0x63, 0xbc, 0xa8, 0x20, 0x8c, 0xba, 0xff, 0x8f, 0x03, 0x4b, 0x98, 0xe6, 0x93, 0x44, 0x22,
4163
+	0x04, 0x35, 0x41, 0x47, 0xae, 0xd3, 0x71, 0xba, 0xcd, 0x67, 0x17, 0xb0, 0x12, 0xd0, 0x16, 0xd4,
4164
+	0x05, 0x1d, 0xe5, 0xee, 0xc5, 0x8e, 0xd3, 0x5d, 0xdd, 0xfc, 0x20, 0x98, 0x9b, 0xee, 0x00, 0xd3,
4165
+	0xd1, 0x1e, 0xc9, 0x9e, 0x5d, 0xc0, 0x1a, 0x80, 0xbe, 0x82, 0x95, 0x31, 0x95, 0x24, 0x22, 0x92,
4166
+	0xb8, 0xd0, 0xa9, 0x75, 0x57, 0x37, 0xc3, 0x4a, 0xb0, 0x62, 0x10, 0xec, 0x59, 0xc4, 0x93, 0x54,
4167
+	0x8a, 0x03, 0x3c, 0x35, 0xe0, 0xdd, 0x87, 0xb5, 0x23, 0xbf, 0x50, 0x1b, 0x6a, 0x6f, 0xe8, 0x81,
4168
+	0xa1, 0x8a, 0xd5, 0x12, 0xfd, 0x0f, 0x1a, 0x6f, 0x49, 0x32, 0xa1, 0x9a, 0x69, 0x0b, 0x1b, 0xe1,
4169
+	0xde, 0xc5, 0xbb, 0x4e, 0x6f, 0x05, 0x96, 0x84, 0x36, 0xef, 0xff, 0xaa, 0x63, 0x55, 0x34, 0xd1,
4170
+	0x43, 0x1b, 0x97, 0xa3, 0xa9, 0xdd, 0x3a, 0x33, 0x2e, 0xf5, 0xc9, 0x0d, 0x2d, 0x0d, 0xf4, 0xb6,
4171
+	0xa0, 0x39, 0xdd, 0x3a, 0x8b, 0x4e, 0xb3, 0x44, 0xc7, 0x97, 0xb0, 0x86, 0xa9, 0x9c, 0x88, 0x14,
4172
+	0xd3, 0x1f, 0x26, 0x34, 0x97, 0xe8, 0xb3, 0x82, 0x9f, 0xc6, 0x9f, 0x95, 0x64, 0xa5, 0x88, 0x2d,
4173
+	0x00, 0x75, 0xa1, 0x41, 0x85, 0xe0, 0xc2, 0x1e, 0x0f, 0x0a, 0x4c, 0xa1, 0x06, 0x22, 0x1b, 0x06,
4174
+	0x2f, 0x74, 0xa1, 0x62, 0xa3, 0xe0, 0xb7, 0xe1, 0x52, 0xe1, 0x35, 0xcf, 0x78, 0x9a, 0x53, 0xff,
4175
+	0x37, 0x07, 0xae, 0x62, 0xaa, 0xeb, 0x74, 0x67, 0x4c, 0x62, 0xfa, 0x98, 0xa7, 0x23, 0x16, 0x17,
4176
+	0xa4, 0xda, 0x50, 0xc3, 0x45, 0x2d, 0x60, 0xb5, 0x44, 0x5d, 0x58, 0xe9, 0x27, 0x44, 0x8e, 0xb8,
4177
+	0x18, 0x5b, 0x77, 0xad, 0x20, 0x1b, 0x04, 0xc5, 0x1e, 0x9e, 0xfe, 0x45, 0x1d, 0x58, 0xb5, 0x86,
4178
+	0xf7, 0x78, 0x44, 0xdd, 0x9a, 0xb6, 0x51, 0xde, 0x42, 0x2e, 0x2c, 0xef, 0xf2, 0xf8, 0x6b, 0x32,
4179
+	0xa6, 0x6e, 0x5d, 0xff, 0x2d, 0x44, 0xff, 0x67, 0x07, 0xbc, 0xd3, 0x58, 0x19, 0xd2, 0xe8, 0x4b,
4180
+	0x58, 0xda, 0x66, 0x31, 0xcd, 0x4d, 0xae, 0x9a, 0xbd, 0xcd, 0x77, 0xef, 0xaf, 0x5f, 0xf8, 0xeb,
4181
+	0xfd, 0xf5, 0x9b, 0xa5, 0xa2, 0xe7, 0x19, 0x4d, 0x87, 0x3c, 0x95, 0x84, 0xa5, 0x54, 0xa8, 0xde,
4182
+	0xbd, 0x1d, 0x69, 0x48, 0x60, 0x90, 0xd8, 0x5a, 0x40, 0xff, 0x87, 0x25, 0x63, 0xdd, 0x96, 0x8c,
4183
+	0x95, 0xfc, 0x7f, 0x6b, 0xd0, 0x7a, 0xa1, 0x08, 0x14, 0xb9, 0x08, 0x00, 0xb6, 0xe9, 0x88, 0xa5,
4184
+	0x4c, 0x32, 0x9e, 0xda, 0x43, 0xba, 0xa4, 0x62, 0x9f, 0xed, 0xe2, 0x92, 0x06, 0xf2, 0x60, 0xe5,
4185
+	0xa9, 0x3d, 0x30, 0x7b, 0xfc, 0x53, 0x19, 0xbd, 0x82, 0xd5, 0x62, 0xfd, 0x3c, 0x93, 0x6e, 0x4d,
4186
+	0x97, 0xdf, 0xdd, 0x8a, 0x13, 0x2f, 0x33, 0x09, 0x4a, 0x50, 0x53, 0x8b, 0x65, 0x63, 0xe8, 0x73,
4187
+	0xb8, 0xba, 0x33, 0xce, 0xb8, 0x90, 0x8f, 0xc9, 0xf0, 0x35, 0x55, 0xd5, 0xb9, 0x4d, 0x33, 0x41,
4188
+	0x87, 0x44, 0xd2, 0xc8, 0xad, 0x77, 0x6a, 0xdd, 0x26, 0x9e, 0xaf, 0x80, 0x36, 0xe0, 0x0a, 0x49,
4189
+	0x12, 0xbe, 0x6f, 0x4b, 0x4c, 0x17, 0x8b, 0xdb, 0xe8, 0x38, 0xdd, 0x15, 0x7c, 0xf2, 0x87, 0xaa,
4190
+	0xef, 0xa7, 0x2c, 0x25, 0x89, 0x0b, 0x5a, 0xc3, 0x08, 0xc8, 0x87, 0xd6, 0x93, 0x1f, 0x95, 0x03,
4191
+	0x2a, 0x1e, 0x49, 0x29, 0xdc, 0x55, 0x9d, 0xd8, 0x23, 0x7b, 0xa8, 0x0f, 0x2d, 0xed, 0xde, 0x30,
4192
+	0xc9, 0xdd, 0x96, 0x4e, 0xc1, 0x46, 0x45, 0x0a, 0xb4, 0xfa, 0xf3, 0x4c, 0xe5, 0xd6, 0xb6, 0xe0,
4193
+	0x11, 0x0b, 0xde, 0x03, 0x68, 0x1f, 0x4f, 0xcc, 0x42, 0x1d, 0xf9, 0xbb, 0x03, 0x57, 0x4e, 0xf8,
4194
+	0x40, 0x08, 0xea, 0xdf, 0x1c, 0x64, 0xd4, 0x9a, 0xd0, 0x6b, 0xb4, 0x07, 0x0d, 0x15, 0x83, 0x1a,
4195
+	0x87, 0x8a, 0xf4, 0xd6, 0x22, 0xa4, 0x03, 0x8d, 0x34, 0xfc, 0x8d, 0x15, 0xef, 0x2e, 0xc0, 0x6c,
4196
+	0x73, 0x21, 0xca, 0xdf, 0xc2, 0x9a, 0x2d, 0x0c, 0xdb, 0x18, 0xed, 0xd2, 0xec, 0x36, 0x93, 0x7b,
4197
+	0x36, 0x56, 0x6a, 0x0b, 0x8e, 0x15, 0xff, 0x27, 0xb8, 0x8c, 0x29, 0x89, 0x9e, 0xb2, 0x84, 0xce,
4198
+	0x9f, 0x07, 0xaa, 0xca, 0x59, 0x42, 0xfb, 0x44, 0xbe, 0x9e, 0x56, 0xb9, 0x95, 0xd1, 0x3d, 0x68,
4199
+	0x60, 0x92, 0xc6, 0xd4, 0xba, 0xfe, 0xb0, 0xc2, 0xb5, 0x76, 0xa2, 0x74, 0xb1, 0x81, 0xf8, 0xf7,
4200
+	0xa1, 0x39, 0xdd, 0x53, 0x3d, 0xfa, 0x7c, 0x34, 0xca, 0xa9, 0xe9, 0xf7, 0x1a, 0xb6, 0x92, 0xda,
4201
+	0xdf, 0xa5, 0x69, 0x6c, 0x5d, 0xd7, 0xb0, 0x95, 0xfc, 0x75, 0x68, 0xcf, 0x98, 0xdb, 0xd4, 0x20,
4202
+	0xa8, 0x6f, 0xab, 0x5b, 0xc8, 0xd1, 0xc5, 0xa8, 0xd7, 0x7e, 0xa4, 0xc6, 0x21, 0x89, 0xb6, 0x99,
4203
+	0x98, 0x1f, 0xa0, 0x0b, 0xcb, 0xdb, 0x4c, 0x94, 0xe2, 0x2b, 0x44, 0xb4, 0x0e, 0x97, 0x76, 0xd2,
4204
+	0x61, 0x32, 0x89, 0x54, 0xb4, 0x92, 0x8a, 0xd4, 0xce, 0xb8, 0x63, 0xbb, 0xfe, 0x43, 0x93, 0x47,
4205
+	0xed, 0xc5, 0x92, 0xd9, 0x80, 0x65, 0x9a, 0x4a, 0xc1, 0x68, 0x71, 0xf5, 0xa0, 0xc0, 0xdc, 0xcc,
4206
+	0x81, 0xbe, 0x99, 0xf5, 0xd4, 0xc6, 0x85, 0x8a, 0xbf, 0x05, 0x97, 0xd5, 0x46, 0xf5, 0x41, 0x20,
4207
+	0xa8, 0x97, 0x48, 0xea, 0xb5, 0x7f, 0x0f, 0xda, 0x33, 0xa0, 0x75, 0xbd, 0x0e, 0x75, 0x75, 0xef,
4208
+	0xdb, 0x01, 0x76, 0x9a, 0x5f, 0xfd, 0xdf, 0x5f, 0x83, 0xd5, 0x3e, 0x4b, 0x8b, 0x9b, 0xc0, 0x3f,
4209
+	0x74, 0xa0, 0xd5, 0xe7, 0xe9, 0x6c, 0x06, 0xf7, 0xe1, 0x72, 0xd1, 0x6e, 0x8f, 0xfa, 0x3b, 0x8f,
4210
+	0x49, 0x56, 0x84, 0xd2, 0x39, 0x79, 0xcc, 0xf6, 0x89, 0x12, 0x18, 0xc5, 0x5e, 0x5d, 0x8d, 0x6b,
4211
+	0x7c, 0x1c, 0x8e, 0xbe, 0x80, 0xe5, 0xdd, 0xdd, 0x9e, 0xb6, 0x74, 0x71, 0x21, 0x4b, 0x05, 0x0c,
4212
+	0x3d, 0x80, 0xe5, 0x97, 0xfa, 0xe5, 0x94, 0xdb, 0x91, 0x7a, 0x4a, 0xc9, 0x99, 0x40, 0x8d, 0x1a,
4213
+	0xa6, 0x43, 0x2e, 0x22, 0x5c, 0x80, 0x36, 0xff, 0x68, 0x40, 0x73, 0x77, 0xb7, 0xd7, 0x13, 0x2c,
4214
+	0x8a, 0x29, 0xfa, 0xc5, 0x01, 0x74, 0xf2, 0x12, 0x42, 0x9f, 0x54, 0x77, 0xd0, 0xe9, 0x37, 0xa9,
4215
+	0xf7, 0xe9, 0x82, 0x28, 0x9b, 0xe5, 0x57, 0xd0, 0xd0, 0x1d, 0x8e, 0x3e, 0x3a, 0xe7, 0xe5, 0xe0,
4216
+	0x75, 0xcf, 0x56, 0xb4, 0xb6, 0x87, 0xb0, 0x52, 0x74, 0x09, 0xba, 0x59, 0x49, 0xef, 0xc8, 0x10,
4217
+	0xf0, 0x6e, 0x9d, 0x4b, 0xd7, 0x3a, 0xf9, 0x1e, 0x96, 0x6d, 0xf1, 0xa3, 0x1b, 0x67, 0xe0, 0x66,
4218
+	0x6d, 0xe8, 0xdd, 0x3c, 0x8f, 0xea, 0x2c, 0x8c, 0xa2, 0xc8, 0x2b, 0xc3, 0x38, 0xd6, 0x42, 0x95,
4219
+	0x61, 0x9c, 0xe8, 0x9a, 0x97, 0x50, 0x57, 0xdd, 0x80, 0xd6, 0x2b, 0x40, 0xa5, 0x76, 0xf1, 0xaa,
4220
+	0x8e, 0xeb, 0x48, 0x1b, 0x7d, 0xa7, 0xde, 0xa2, 0xfa, 0x2e, 0xed, 0x56, 0xc6, 0x5c, 0x7a, 0x2a,
4221
+	0x7a, 0x37, 0xce, 0xa1, 0x69, 0xcc, 0xf7, 0x5a, 0xef, 0x0e, 0xaf, 0x39, 0x7f, 0x1e, 0x5e, 0x73,
4222
+	0xfe, 0x3e, 0xbc, 0xe6, 0x0c, 0x96, 0xf4, 0x63, 0xff, 0xce, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff,
4223
+	0x7c, 0xf6, 0x53, 0x84, 0x3e, 0x0d, 0x00, 0x00,
4219 4224
 }
... ...
@@ -64,12 +64,25 @@ message SolveRequest {
64 64
 	pb.Definition Definition = 1;
65 65
 	string Frontend = 2;
66 66
 	map<string, string> FrontendOpt = 3;
67
-	repeated string ImportCacheRefs = 4;
67
+	// ImportCacheRefsDeprecated is deprecated in favor or the new Imports since BuildKit v0.4.0.
68
+        // When ImportCacheRefsDeprecated is set, the solver appends
69
+        // {.Type = "registry", .Attrs = {"ref": importCacheRef}}
70
+        // for each of the ImportCacheRefs entry to CacheImports for compatibility. (planned to be removed)
71
+	repeated string ImportCacheRefsDeprecated = 4;
68 72
 	bool allowResultReturn = 5;
69 73
 	
70 74
 	// apicaps.CapSolveInlineReturn deprecated
71 75
 	bool Final = 10;
72 76
 	bytes ExporterAttr = 11;
77
+	// CacheImports was added in BuildKit v0.4.0.
78
+	// apicaps:CapImportCaches
79
+	repeated CacheOptionsEntry CacheImports = 12;
80
+}
81
+
82
+// CacheOptionsEntry corresponds to the control.CacheOptionsEntry
83
+message CacheOptionsEntry {
84
+	string Type = 1;
85
+	map<string, string> Attrs = 2;
73 86
 }
74 87
 
75 88
 message SolveResponse {
... ...
@@ -122,4 +135,4 @@ message PongResponse{
122 122
 	repeated moby.buildkit.v1.apicaps.APICap FrontendAPICaps = 1 [(gogoproto.nullable) = false];
123 123
 	repeated moby.buildkit.v1.apicaps.APICap LLBCaps = 2 [(gogoproto.nullable) = false];
124 124
 	repeated moby.buildkit.v1.types.WorkerRecord Workers = 3;
125
-}
126 125
\ No newline at end of file
126
+}
... ...
@@ -1,16 +1,6 @@
1 1
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
2 2
 // source: auth.proto
3 3
 
4
-/*
5
-	Package auth is a generated protocol buffer package.
6
-
7
-	It is generated from these files:
8
-		auth.proto
9
-
10
-	It has these top-level messages:
11
-		CredentialsRequest
12
-		CredentialsResponse
13
-*/
14 4
 package auth
15 5
 
16 6
 import proto "github.com/gogo/protobuf/proto"
... ...
@@ -20,8 +10,10 @@ import math "math"
20 20
 import strings "strings"
21 21
 import reflect "reflect"
22 22
 
23
-import context "golang.org/x/net/context"
24
-import grpc "google.golang.org/grpc"
23
+import (
24
+	context "golang.org/x/net/context"
25
+	grpc "google.golang.org/grpc"
26
+)
25 27
 
26 28
 import io "io"
27 29
 
... ...
@@ -40,9 +32,37 @@ type CredentialsRequest struct {
40 40
 	Host string `protobuf:"bytes,1,opt,name=Host,proto3" json:"Host,omitempty"`
41 41
 }
42 42
 
43
-func (m *CredentialsRequest) Reset()                    { *m = CredentialsRequest{} }
44
-func (*CredentialsRequest) ProtoMessage()               {}
45
-func (*CredentialsRequest) Descriptor() ([]byte, []int) { return fileDescriptorAuth, []int{0} }
43
+func (m *CredentialsRequest) Reset()      { *m = CredentialsRequest{} }
44
+func (*CredentialsRequest) ProtoMessage() {}
45
+func (*CredentialsRequest) Descriptor() ([]byte, []int) {
46
+	return fileDescriptor_auth_0215b2f0213c0d57, []int{0}
47
+}
48
+func (m *CredentialsRequest) XXX_Unmarshal(b []byte) error {
49
+	return m.Unmarshal(b)
50
+}
51
+func (m *CredentialsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
52
+	if deterministic {
53
+		return xxx_messageInfo_CredentialsRequest.Marshal(b, m, deterministic)
54
+	} else {
55
+		b = b[:cap(b)]
56
+		n, err := m.MarshalTo(b)
57
+		if err != nil {
58
+			return nil, err
59
+		}
60
+		return b[:n], nil
61
+	}
62
+}
63
+func (dst *CredentialsRequest) XXX_Merge(src proto.Message) {
64
+	xxx_messageInfo_CredentialsRequest.Merge(dst, src)
65
+}
66
+func (m *CredentialsRequest) XXX_Size() int {
67
+	return m.Size()
68
+}
69
+func (m *CredentialsRequest) XXX_DiscardUnknown() {
70
+	xxx_messageInfo_CredentialsRequest.DiscardUnknown(m)
71
+}
72
+
73
+var xxx_messageInfo_CredentialsRequest proto.InternalMessageInfo
46 74
 
47 75
 func (m *CredentialsRequest) GetHost() string {
48 76
 	if m != nil {
... ...
@@ -56,9 +76,37 @@ type CredentialsResponse struct {
56 56
 	Secret   string `protobuf:"bytes,2,opt,name=Secret,proto3" json:"Secret,omitempty"`
57 57
 }
58 58
 
59
-func (m *CredentialsResponse) Reset()                    { *m = CredentialsResponse{} }
60
-func (*CredentialsResponse) ProtoMessage()               {}
61
-func (*CredentialsResponse) Descriptor() ([]byte, []int) { return fileDescriptorAuth, []int{1} }
59
+func (m *CredentialsResponse) Reset()      { *m = CredentialsResponse{} }
60
+func (*CredentialsResponse) ProtoMessage() {}
61
+func (*CredentialsResponse) Descriptor() ([]byte, []int) {
62
+	return fileDescriptor_auth_0215b2f0213c0d57, []int{1}
63
+}
64
+func (m *CredentialsResponse) XXX_Unmarshal(b []byte) error {
65
+	return m.Unmarshal(b)
66
+}
67
+func (m *CredentialsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
68
+	if deterministic {
69
+		return xxx_messageInfo_CredentialsResponse.Marshal(b, m, deterministic)
70
+	} else {
71
+		b = b[:cap(b)]
72
+		n, err := m.MarshalTo(b)
73
+		if err != nil {
74
+			return nil, err
75
+		}
76
+		return b[:n], nil
77
+	}
78
+}
79
+func (dst *CredentialsResponse) XXX_Merge(src proto.Message) {
80
+	xxx_messageInfo_CredentialsResponse.Merge(dst, src)
81
+}
82
+func (m *CredentialsResponse) XXX_Size() int {
83
+	return m.Size()
84
+}
85
+func (m *CredentialsResponse) XXX_DiscardUnknown() {
86
+	xxx_messageInfo_CredentialsResponse.DiscardUnknown(m)
87
+}
88
+
89
+var xxx_messageInfo_CredentialsResponse proto.InternalMessageInfo
62 90
 
63 91
 func (m *CredentialsResponse) GetUsername() string {
64 92
 	if m != nil {
... ...
@@ -167,8 +215,9 @@ var _ grpc.ClientConn
167 167
 // is compatible with the grpc package it is being compiled against.
168 168
 const _ = grpc.SupportPackageIsVersion4
169 169
 
170
-// Client API for Auth service
171
-
170
+// AuthClient is the client API for Auth service.
171
+//
172
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
172 173
 type AuthClient interface {
173 174
 	Credentials(ctx context.Context, in *CredentialsRequest, opts ...grpc.CallOption) (*CredentialsResponse, error)
174 175
 }
... ...
@@ -183,15 +232,14 @@ func NewAuthClient(cc *grpc.ClientConn) AuthClient {
183 183
 
184 184
 func (c *authClient) Credentials(ctx context.Context, in *CredentialsRequest, opts ...grpc.CallOption) (*CredentialsResponse, error) {
185 185
 	out := new(CredentialsResponse)
186
-	err := grpc.Invoke(ctx, "/moby.filesync.v1.Auth/Credentials", in, out, c.cc, opts...)
186
+	err := c.cc.Invoke(ctx, "/moby.filesync.v1.Auth/Credentials", in, out, opts...)
187 187
 	if err != nil {
188 188
 		return nil, err
189 189
 	}
190 190
 	return out, nil
191 191
 }
192 192
 
193
-// Server API for Auth service
194
-
193
+// AuthServer is the server API for Auth service.
195 194
 type AuthServer interface {
196 195
 	Credentials(context.Context, *CredentialsRequest) (*CredentialsResponse, error)
197 196
 }
... ...
@@ -295,6 +343,9 @@ func encodeVarintAuth(dAtA []byte, offset int, v uint64) int {
295 295
 	return offset + 1
296 296
 }
297 297
 func (m *CredentialsRequest) Size() (n int) {
298
+	if m == nil {
299
+		return 0
300
+	}
298 301
 	var l int
299 302
 	_ = l
300 303
 	l = len(m.Host)
... ...
@@ -305,6 +356,9 @@ func (m *CredentialsRequest) Size() (n int) {
305 305
 }
306 306
 
307 307
 func (m *CredentialsResponse) Size() (n int) {
308
+	if m == nil {
309
+		return 0
310
+	}
308 311
 	var l int
309 312
 	_ = l
310 313
 	l = len(m.Username)
... ...
@@ -652,10 +706,10 @@ var (
652 652
 	ErrIntOverflowAuth   = fmt.Errorf("proto: integer overflow")
653 653
 )
654 654
 
655
-func init() { proto.RegisterFile("auth.proto", fileDescriptorAuth) }
655
+func init() { proto.RegisterFile("auth.proto", fileDescriptor_auth_0215b2f0213c0d57) }
656 656
 
657
-var fileDescriptorAuth = []byte{
658
-	// 224 bytes of a gzipped FileDescriptorProto
657
+var fileDescriptor_auth_0215b2f0213c0d57 = []byte{
658
+	// 233 bytes of a gzipped FileDescriptorProto
659 659
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x2c, 0x2d, 0xc9,
660 660
 	0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xc8, 0xcd, 0x4f, 0xaa, 0xd4, 0x4b, 0xcb, 0xcc,
661 661
 	0x49, 0x2d, 0xae, 0xcc, 0x4b, 0xd6, 0x2b, 0x33, 0x54, 0xd2, 0xe0, 0x12, 0x72, 0x2e, 0x4a, 0x4d,
... ...
@@ -665,9 +719,10 @@ var fileDescriptorAuth = []byte{
665 665
 	0x16, 0xa7, 0x16, 0xe5, 0x25, 0xe6, 0xa6, 0x42, 0x95, 0xc3, 0xf9, 0x42, 0x62, 0x5c, 0x6c, 0xc1,
666 666
 	0xa9, 0xc9, 0x45, 0xa9, 0x25, 0x12, 0x4c, 0x60, 0x19, 0x28, 0xcf, 0x28, 0x89, 0x8b, 0xc5, 0xb1,
667 667
 	0xb4, 0x24, 0x43, 0x28, 0x8a, 0x8b, 0x1b, 0xc9, 0x48, 0x21, 0x15, 0x3d, 0x74, 0xe7, 0xe9, 0x61,
668
-	0xba, 0x4d, 0x4a, 0x95, 0x80, 0x2a, 0x88, 0xbb, 0x9c, 0x8c, 0x2e, 0x3c, 0x94, 0x63, 0xb8, 0xf1,
668
+	0xba, 0x4d, 0x4a, 0x95, 0x80, 0x2a, 0x88, 0xbb, 0x9c, 0xac, 0x2e, 0x3c, 0x94, 0x63, 0xb8, 0xf1,
669 669
 	0x50, 0x8e, 0xe1, 0xc3, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x2b, 0x1e, 0xc9, 0x31, 0x9e,
670 670
 	0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x2f, 0x1e, 0xc9, 0x31,
671
-	0x7c, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0x43, 0x14, 0x0b, 0x28, 0x90, 0x92, 0xd8, 0xc0,
672
-	0xa1, 0x64, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xaa, 0x73, 0xf3, 0xd5, 0x33, 0x01, 0x00, 0x00,
671
+	0x7c, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb,
672
+	0x31, 0x44, 0xb1, 0x80, 0x02, 0x2b, 0x89, 0x0d, 0x1c, 0x5a, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff,
673
+	0xff, 0x64, 0x61, 0x71, 0x59, 0x3b, 0x01, 0x00, 0x00,
673 674
 }
674 675
new file mode 100644
... ...
@@ -0,0 +1,132 @@
0
+package content
1
+
2
+import (
3
+	"context"
4
+
5
+	api "github.com/containerd/containerd/api/services/content/v1"
6
+	"github.com/containerd/containerd/content"
7
+	"github.com/containerd/containerd/errdefs"
8
+	contentservice "github.com/containerd/containerd/services/content"
9
+	"github.com/moby/buildkit/session"
10
+	digest "github.com/opencontainers/go-digest"
11
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
12
+	"github.com/pkg/errors"
13
+	"google.golang.org/grpc"
14
+	"google.golang.org/grpc/metadata"
15
+)
16
+
17
+// GRPCHeaderID is a gRPC header for store ID
18
+const GRPCHeaderID = "buildkit-attachable-store-id"
19
+
20
+type attachableContentStore struct {
21
+	stores map[string]content.Store
22
+}
23
+
24
+func (cs *attachableContentStore) choose(ctx context.Context) (content.Store, error) {
25
+	md, ok := metadata.FromIncomingContext(ctx)
26
+	if !ok {
27
+		return nil, errors.Wrap(errdefs.ErrInvalidArgument, "request lacks metadata")
28
+	}
29
+
30
+	values := md[GRPCHeaderID]
31
+	if len(values) == 0 {
32
+		return nil, errors.Wrapf(errdefs.ErrInvalidArgument, "request lacks metadata %q", GRPCHeaderID)
33
+	}
34
+	id := values[0]
35
+	store, ok := cs.stores[id]
36
+	if !ok {
37
+		return nil, errors.Wrapf(errdefs.ErrNotFound, "unknown store %s", id)
38
+	}
39
+	return store, nil
40
+}
41
+
42
+func (cs *attachableContentStore) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
43
+	store, err := cs.choose(ctx)
44
+	if err != nil {
45
+		return content.Info{}, err
46
+	}
47
+	return store.Info(ctx, dgst)
48
+}
49
+
50
+func (cs *attachableContentStore) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) {
51
+	store, err := cs.choose(ctx)
52
+	if err != nil {
53
+		return content.Info{}, err
54
+	}
55
+	return store.Update(ctx, info, fieldpaths...)
56
+}
57
+
58
+func (cs *attachableContentStore) Walk(ctx context.Context, fn content.WalkFunc, fs ...string) error {
59
+	store, err := cs.choose(ctx)
60
+	if err != nil {
61
+		return err
62
+	}
63
+	return store.Walk(ctx, fn, fs...)
64
+}
65
+
66
+func (cs *attachableContentStore) Delete(ctx context.Context, dgst digest.Digest) error {
67
+	store, err := cs.choose(ctx)
68
+	if err != nil {
69
+		return err
70
+	}
71
+	return store.Delete(ctx, dgst)
72
+}
73
+
74
+func (cs *attachableContentStore) ListStatuses(ctx context.Context, fs ...string) ([]content.Status, error) {
75
+	store, err := cs.choose(ctx)
76
+	if err != nil {
77
+		return nil, err
78
+	}
79
+	return store.ListStatuses(ctx, fs...)
80
+}
81
+
82
+func (cs *attachableContentStore) Status(ctx context.Context, ref string) (content.Status, error) {
83
+	store, err := cs.choose(ctx)
84
+	if err != nil {
85
+		return content.Status{}, err
86
+	}
87
+	return store.Status(ctx, ref)
88
+}
89
+
90
+func (cs *attachableContentStore) Abort(ctx context.Context, ref string) error {
91
+	store, err := cs.choose(ctx)
92
+	if err != nil {
93
+		return err
94
+	}
95
+	return store.Abort(ctx, ref)
96
+}
97
+
98
+func (cs *attachableContentStore) Writer(ctx context.Context, opts ...content.WriterOpt) (content.Writer, error) {
99
+	store, err := cs.choose(ctx)
100
+	if err != nil {
101
+		return nil, err
102
+	}
103
+	return store.Writer(ctx, opts...)
104
+}
105
+
106
+func (cs *attachableContentStore) ReaderAt(ctx context.Context, desc ocispec.Descriptor) (content.ReaderAt, error) {
107
+	store, err := cs.choose(ctx)
108
+	if err != nil {
109
+		return nil, err
110
+	}
111
+	return store.ReaderAt(ctx, desc)
112
+}
113
+
114
+type attachable struct {
115
+	service api.ContentServer
116
+}
117
+
118
+// NewAttachable creates session.Attachable from aggregated stores.
119
+// A key of the store map is an ID string that is used for choosing underlying store.
120
+func NewAttachable(stores map[string]content.Store) session.Attachable {
121
+	store := &attachableContentStore{stores: stores}
122
+	service := contentservice.NewService(store)
123
+	a := attachable{
124
+		service: service,
125
+	}
126
+	return &a
127
+}
128
+
129
+func (a *attachable) Register(server *grpc.Server) {
130
+	api.RegisterContentServer(server, a.service)
131
+}
0 132
new file mode 100644
... ...
@@ -0,0 +1,84 @@
0
+package content
1
+
2
+import (
3
+	"context"
4
+
5
+	api "github.com/containerd/containerd/api/services/content/v1"
6
+	"github.com/containerd/containerd/content"
7
+	"github.com/containerd/containerd/content/proxy"
8
+	"github.com/moby/buildkit/session"
9
+	digest "github.com/opencontainers/go-digest"
10
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
11
+	"google.golang.org/grpc/metadata"
12
+)
13
+
14
+type callerContentStore struct {
15
+	store   content.Store
16
+	storeID string
17
+}
18
+
19
+func (cs *callerContentStore) choose(ctx context.Context) context.Context {
20
+	nsheader := metadata.Pairs(GRPCHeaderID, cs.storeID)
21
+	md, ok := metadata.FromOutgoingContext(ctx) // merge with outgoing context.
22
+	if !ok {
23
+		md = nsheader
24
+	} else {
25
+		// order ensures the latest is first in this list.
26
+		md = metadata.Join(nsheader, md)
27
+	}
28
+	return metadata.NewOutgoingContext(ctx, md)
29
+}
30
+
31
+func (cs *callerContentStore) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
32
+	ctx = cs.choose(ctx)
33
+	return cs.store.Info(ctx, dgst)
34
+}
35
+
36
+func (cs *callerContentStore) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) {
37
+	ctx = cs.choose(ctx)
38
+	return cs.store.Update(ctx, info, fieldpaths...)
39
+}
40
+
41
+func (cs *callerContentStore) Walk(ctx context.Context, fn content.WalkFunc, fs ...string) error {
42
+	ctx = cs.choose(ctx)
43
+	return cs.store.Walk(ctx, fn, fs...)
44
+}
45
+
46
+func (cs *callerContentStore) Delete(ctx context.Context, dgst digest.Digest) error {
47
+	ctx = cs.choose(ctx)
48
+	return cs.store.Delete(ctx, dgst)
49
+}
50
+
51
+func (cs *callerContentStore) ListStatuses(ctx context.Context, fs ...string) ([]content.Status, error) {
52
+	ctx = cs.choose(ctx)
53
+	return cs.store.ListStatuses(ctx, fs...)
54
+}
55
+
56
+func (cs *callerContentStore) Status(ctx context.Context, ref string) (content.Status, error) {
57
+	ctx = cs.choose(ctx)
58
+	return cs.store.Status(ctx, ref)
59
+}
60
+
61
+func (cs *callerContentStore) Abort(ctx context.Context, ref string) error {
62
+	ctx = cs.choose(ctx)
63
+	return cs.store.Abort(ctx, ref)
64
+}
65
+
66
+func (cs *callerContentStore) Writer(ctx context.Context, opts ...content.WriterOpt) (content.Writer, error) {
67
+	ctx = cs.choose(ctx)
68
+	return cs.store.Writer(ctx, opts...)
69
+}
70
+
71
+func (cs *callerContentStore) ReaderAt(ctx context.Context, desc ocispec.Descriptor) (content.ReaderAt, error) {
72
+	ctx = cs.choose(ctx)
73
+	return cs.store.ReaderAt(ctx, desc)
74
+}
75
+
76
+// NewCallerStore creates content.Store from session.Caller with specified storeID
77
+func NewCallerStore(c session.Caller, storeID string) content.Store {
78
+	client := api.NewContentClient(c.Conn())
79
+	return &callerContentStore{
80
+		store:   proxy.NewContentStore(client),
81
+		storeID: storeID,
82
+	}
83
+}
... ...
@@ -1,15 +1,6 @@
1 1
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
2 2
 // source: filesync.proto
3 3
 
4
-/*
5
-Package filesync is a generated protocol buffer package.
6
-
7
-It is generated from these files:
8
-	filesync.proto
9
-
10
-It has these top-level messages:
11
-	BytesMessage
12
-*/
13 4
 package filesync
14 5
 
15 6
 import proto "github.com/gogo/protobuf/proto"
... ...
@@ -21,8 +12,10 @@ import bytes "bytes"
21 21
 import strings "strings"
22 22
 import reflect "reflect"
23 23
 
24
-import context "golang.org/x/net/context"
25
-import grpc "google.golang.org/grpc"
24
+import (
25
+	context "golang.org/x/net/context"
26
+	grpc "google.golang.org/grpc"
27
+)
26 28
 
27 29
 import io "io"
28 30
 
... ...
@@ -42,9 +35,37 @@ type BytesMessage struct {
42 42
 	Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
43 43
 }
44 44
 
45
-func (m *BytesMessage) Reset()                    { *m = BytesMessage{} }
46
-func (*BytesMessage) ProtoMessage()               {}
47
-func (*BytesMessage) Descriptor() ([]byte, []int) { return fileDescriptorFilesync, []int{0} }
45
+func (m *BytesMessage) Reset()      { *m = BytesMessage{} }
46
+func (*BytesMessage) ProtoMessage() {}
47
+func (*BytesMessage) Descriptor() ([]byte, []int) {
48
+	return fileDescriptor_filesync_26f8b7bce2e5ac0e, []int{0}
49
+}
50
+func (m *BytesMessage) XXX_Unmarshal(b []byte) error {
51
+	return m.Unmarshal(b)
52
+}
53
+func (m *BytesMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
54
+	if deterministic {
55
+		return xxx_messageInfo_BytesMessage.Marshal(b, m, deterministic)
56
+	} else {
57
+		b = b[:cap(b)]
58
+		n, err := m.MarshalTo(b)
59
+		if err != nil {
60
+			return nil, err
61
+		}
62
+		return b[:n], nil
63
+	}
64
+}
65
+func (dst *BytesMessage) XXX_Merge(src proto.Message) {
66
+	xxx_messageInfo_BytesMessage.Merge(dst, src)
67
+}
68
+func (m *BytesMessage) XXX_Size() int {
69
+	return m.Size()
70
+}
71
+func (m *BytesMessage) XXX_DiscardUnknown() {
72
+	xxx_messageInfo_BytesMessage.DiscardUnknown(m)
73
+}
74
+
75
+var xxx_messageInfo_BytesMessage proto.InternalMessageInfo
48 76
 
49 77
 func (m *BytesMessage) GetData() []byte {
50 78
 	if m != nil {
... ...
@@ -107,8 +128,9 @@ var _ grpc.ClientConn
107 107
 // is compatible with the grpc package it is being compiled against.
108 108
 const _ = grpc.SupportPackageIsVersion4
109 109
 
110
-// Client API for FileSync service
111
-
110
+// FileSyncClient is the client API for FileSync service.
111
+//
112
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
112 113
 type FileSyncClient interface {
113 114
 	DiffCopy(ctx context.Context, opts ...grpc.CallOption) (FileSync_DiffCopyClient, error)
114 115
 	TarStream(ctx context.Context, opts ...grpc.CallOption) (FileSync_TarStreamClient, error)
... ...
@@ -123,7 +145,7 @@ func NewFileSyncClient(cc *grpc.ClientConn) FileSyncClient {
123 123
 }
124 124
 
125 125
 func (c *fileSyncClient) DiffCopy(ctx context.Context, opts ...grpc.CallOption) (FileSync_DiffCopyClient, error) {
126
-	stream, err := grpc.NewClientStream(ctx, &_FileSync_serviceDesc.Streams[0], c.cc, "/moby.filesync.v1.FileSync/DiffCopy", opts...)
126
+	stream, err := c.cc.NewStream(ctx, &_FileSync_serviceDesc.Streams[0], "/moby.filesync.v1.FileSync/DiffCopy", opts...)
127 127
 	if err != nil {
128 128
 		return nil, err
129 129
 	}
... ...
@@ -154,7 +176,7 @@ func (x *fileSyncDiffCopyClient) Recv() (*BytesMessage, error) {
154 154
 }
155 155
 
156 156
 func (c *fileSyncClient) TarStream(ctx context.Context, opts ...grpc.CallOption) (FileSync_TarStreamClient, error) {
157
-	stream, err := grpc.NewClientStream(ctx, &_FileSync_serviceDesc.Streams[1], c.cc, "/moby.filesync.v1.FileSync/TarStream", opts...)
157
+	stream, err := c.cc.NewStream(ctx, &_FileSync_serviceDesc.Streams[1], "/moby.filesync.v1.FileSync/TarStream", opts...)
158 158
 	if err != nil {
159 159
 		return nil, err
160 160
 	}
... ...
@@ -184,8 +206,7 @@ func (x *fileSyncTarStreamClient) Recv() (*BytesMessage, error) {
184 184
 	return m, nil
185 185
 }
186 186
 
187
-// Server API for FileSync service
188
-
187
+// FileSyncServer is the server API for FileSync service.
189 188
 type FileSyncServer interface {
190 189
 	DiffCopy(FileSync_DiffCopyServer) error
191 190
 	TarStream(FileSync_TarStreamServer) error
... ...
@@ -268,8 +289,9 @@ var _FileSync_serviceDesc = grpc.ServiceDesc{
268 268
 	Metadata: "filesync.proto",
269 269
 }
270 270
 
271
-// Client API for FileSend service
272
-
271
+// FileSendClient is the client API for FileSend service.
272
+//
273
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
273 274
 type FileSendClient interface {
274 275
 	DiffCopy(ctx context.Context, opts ...grpc.CallOption) (FileSend_DiffCopyClient, error)
275 276
 }
... ...
@@ -283,7 +305,7 @@ func NewFileSendClient(cc *grpc.ClientConn) FileSendClient {
283 283
 }
284 284
 
285 285
 func (c *fileSendClient) DiffCopy(ctx context.Context, opts ...grpc.CallOption) (FileSend_DiffCopyClient, error) {
286
-	stream, err := grpc.NewClientStream(ctx, &_FileSend_serviceDesc.Streams[0], c.cc, "/moby.filesync.v1.FileSend/DiffCopy", opts...)
286
+	stream, err := c.cc.NewStream(ctx, &_FileSend_serviceDesc.Streams[0], "/moby.filesync.v1.FileSend/DiffCopy", opts...)
287 287
 	if err != nil {
288 288
 		return nil, err
289 289
 	}
... ...
@@ -313,8 +335,7 @@ func (x *fileSendDiffCopyClient) Recv() (*BytesMessage, error) {
313 313
 	return m, nil
314 314
 }
315 315
 
316
-// Server API for FileSend service
317
-
316
+// FileSendServer is the server API for FileSend service.
318 317
 type FileSendServer interface {
319 318
 	DiffCopy(FileSend_DiffCopyServer) error
320 319
 }
... ...
@@ -398,6 +419,9 @@ func encodeVarintFilesync(dAtA []byte, offset int, v uint64) int {
398 398
 	return offset + 1
399 399
 }
400 400
 func (m *BytesMessage) Size() (n int) {
401
+	if m == nil {
402
+		return 0
403
+	}
401 404
 	var l int
402 405
 	_ = l
403 406
 	l = len(m.Data)
... ...
@@ -624,10 +648,10 @@ var (
624 624
 	ErrIntOverflowFilesync   = fmt.Errorf("proto: integer overflow")
625 625
 )
626 626
 
627
-func init() { proto.RegisterFile("filesync.proto", fileDescriptorFilesync) }
627
+func init() { proto.RegisterFile("filesync.proto", fileDescriptor_filesync_26f8b7bce2e5ac0e) }
628 628
 
629
-var fileDescriptorFilesync = []byte{
630
-	// 208 bytes of a gzipped FileDescriptorProto
629
+var fileDescriptor_filesync_26f8b7bce2e5ac0e = []byte{
630
+	// 217 bytes of a gzipped FileDescriptorProto
631 631
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4b, 0xcb, 0xcc, 0x49,
632 632
 	0x2d, 0xae, 0xcc, 0x4b, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xc8, 0xcd, 0x4f, 0xaa,
633 633
 	0xd4, 0x83, 0x0b, 0x96, 0x19, 0x2a, 0x29, 0x71, 0xf1, 0x38, 0x55, 0x96, 0xa4, 0x16, 0xfb, 0xa6,
... ...
@@ -636,9 +660,10 @@ var fileDescriptorFilesync = []byte{
636 636
 	0x2b, 0xf3, 0x92, 0x85, 0xfc, 0xb8, 0x38, 0x5c, 0x32, 0xd3, 0xd2, 0x9c, 0xf3, 0x0b, 0x2a, 0x85,
637 637
 	0xe4, 0xf4, 0xd0, 0xcd, 0xd3, 0x43, 0x36, 0x4c, 0x8a, 0x80, 0xbc, 0x06, 0xa3, 0x01, 0xa3, 0x90,
638 638
 	0x3f, 0x17, 0x67, 0x48, 0x62, 0x51, 0x70, 0x49, 0x51, 0x6a, 0x62, 0x2e, 0x35, 0x0c, 0x34, 0x8a,
639
-	0x82, 0x3a, 0x36, 0x35, 0x2f, 0x85, 0xda, 0x8e, 0x75, 0x32, 0xbb, 0xf0, 0x50, 0x8e, 0xe1, 0xc6,
639
+	0x82, 0x3a, 0x36, 0x35, 0x2f, 0x85, 0xda, 0x8e, 0x75, 0xb2, 0xbb, 0xf0, 0x50, 0x8e, 0xe1, 0xc6,
640 640
 	0x43, 0x39, 0x86, 0x0f, 0x0f, 0xe5, 0x18, 0x1b, 0x1e, 0xc9, 0x31, 0xae, 0x78, 0x24, 0xc7, 0x78,
641 641
 	0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0xbe, 0x78, 0x24, 0xc7,
642
-	0xf0, 0xe1, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x51, 0x1c, 0x30, 0xb3, 0x92, 0xd8, 0xc0,
643
-	0xc1, 0x6f, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x72, 0x81, 0x1a, 0x91, 0x90, 0x01, 0x00, 0x00,
642
+	0xf0, 0xe1, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c,
643
+	0xc7, 0x10, 0xc5, 0x01, 0x33, 0x33, 0x89, 0x0d, 0x1c, 0x0d, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff,
644
+	0xff, 0x5e, 0xce, 0x52, 0xb3, 0x98, 0x01, 0x00, 0x00,
644 645
 }
... ...
@@ -1,16 +1,6 @@
1 1
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
2 2
 // source: secrets.proto
3 3
 
4
-/*
5
-	Package secrets is a generated protocol buffer package.
6
-
7
-	It is generated from these files:
8
-		secrets.proto
9
-
10
-	It has these top-level messages:
11
-		GetSecretRequest
12
-		GetSecretResponse
13
-*/
14 4
 package secrets
15 5
 
16 6
 import proto "github.com/gogo/protobuf/proto"
... ...
@@ -21,10 +11,12 @@ import bytes "bytes"
21 21
 
22 22
 import strings "strings"
23 23
 import reflect "reflect"
24
-import sortkeys "github.com/gogo/protobuf/sortkeys"
24
+import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
25 25
 
26
-import context "golang.org/x/net/context"
27
-import grpc "google.golang.org/grpc"
26
+import (
27
+	context "golang.org/x/net/context"
28
+	grpc "google.golang.org/grpc"
29
+)
28 30
 
29 31
 import io "io"
30 32
 
... ...
@@ -41,12 +33,40 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
41 41
 
42 42
 type GetSecretRequest struct {
43 43
 	ID          string            `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
44
-	Annotations map[string]string `protobuf:"bytes,2,rep,name=annotations" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
44
+	Annotations map[string]string `protobuf:"bytes,2,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
45 45
 }
46 46
 
47
-func (m *GetSecretRequest) Reset()                    { *m = GetSecretRequest{} }
48
-func (*GetSecretRequest) ProtoMessage()               {}
49
-func (*GetSecretRequest) Descriptor() ([]byte, []int) { return fileDescriptorSecrets, []int{0} }
47
+func (m *GetSecretRequest) Reset()      { *m = GetSecretRequest{} }
48
+func (*GetSecretRequest) ProtoMessage() {}
49
+func (*GetSecretRequest) Descriptor() ([]byte, []int) {
50
+	return fileDescriptor_secrets_21bd4adec74a381e, []int{0}
51
+}
52
+func (m *GetSecretRequest) XXX_Unmarshal(b []byte) error {
53
+	return m.Unmarshal(b)
54
+}
55
+func (m *GetSecretRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
56
+	if deterministic {
57
+		return xxx_messageInfo_GetSecretRequest.Marshal(b, m, deterministic)
58
+	} else {
59
+		b = b[:cap(b)]
60
+		n, err := m.MarshalTo(b)
61
+		if err != nil {
62
+			return nil, err
63
+		}
64
+		return b[:n], nil
65
+	}
66
+}
67
+func (dst *GetSecretRequest) XXX_Merge(src proto.Message) {
68
+	xxx_messageInfo_GetSecretRequest.Merge(dst, src)
69
+}
70
+func (m *GetSecretRequest) XXX_Size() int {
71
+	return m.Size()
72
+}
73
+func (m *GetSecretRequest) XXX_DiscardUnknown() {
74
+	xxx_messageInfo_GetSecretRequest.DiscardUnknown(m)
75
+}
76
+
77
+var xxx_messageInfo_GetSecretRequest proto.InternalMessageInfo
50 78
 
51 79
 func (m *GetSecretRequest) GetID() string {
52 80
 	if m != nil {
... ...
@@ -66,9 +86,37 @@ type GetSecretResponse struct {
66 66
 	Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
67 67
 }
68 68
 
69
-func (m *GetSecretResponse) Reset()                    { *m = GetSecretResponse{} }
70
-func (*GetSecretResponse) ProtoMessage()               {}
71
-func (*GetSecretResponse) Descriptor() ([]byte, []int) { return fileDescriptorSecrets, []int{1} }
69
+func (m *GetSecretResponse) Reset()      { *m = GetSecretResponse{} }
70
+func (*GetSecretResponse) ProtoMessage() {}
71
+func (*GetSecretResponse) Descriptor() ([]byte, []int) {
72
+	return fileDescriptor_secrets_21bd4adec74a381e, []int{1}
73
+}
74
+func (m *GetSecretResponse) XXX_Unmarshal(b []byte) error {
75
+	return m.Unmarshal(b)
76
+}
77
+func (m *GetSecretResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
78
+	if deterministic {
79
+		return xxx_messageInfo_GetSecretResponse.Marshal(b, m, deterministic)
80
+	} else {
81
+		b = b[:cap(b)]
82
+		n, err := m.MarshalTo(b)
83
+		if err != nil {
84
+			return nil, err
85
+		}
86
+		return b[:n], nil
87
+	}
88
+}
89
+func (dst *GetSecretResponse) XXX_Merge(src proto.Message) {
90
+	xxx_messageInfo_GetSecretResponse.Merge(dst, src)
91
+}
92
+func (m *GetSecretResponse) XXX_Size() int {
93
+	return m.Size()
94
+}
95
+func (m *GetSecretResponse) XXX_DiscardUnknown() {
96
+	xxx_messageInfo_GetSecretResponse.DiscardUnknown(m)
97
+}
98
+
99
+var xxx_messageInfo_GetSecretResponse proto.InternalMessageInfo
72 100
 
73 101
 func (m *GetSecretResponse) GetData() []byte {
74 102
 	if m != nil {
... ...
@@ -79,6 +127,7 @@ func (m *GetSecretResponse) GetData() []byte {
79 79
 
80 80
 func init() {
81 81
 	proto.RegisterType((*GetSecretRequest)(nil), "moby.buildkit.secrets.v1.GetSecretRequest")
82
+	proto.RegisterMapType((map[string]string)(nil), "moby.buildkit.secrets.v1.GetSecretRequest.AnnotationsEntry")
82 83
 	proto.RegisterType((*GetSecretResponse)(nil), "moby.buildkit.secrets.v1.GetSecretResponse")
83 84
 }
84 85
 func (this *GetSecretRequest) Equal(that interface{}) bool {
... ...
@@ -148,7 +197,7 @@ func (this *GetSecretRequest) GoString() string {
148 148
 	for k, _ := range this.Annotations {
149 149
 		keysForAnnotations = append(keysForAnnotations, k)
150 150
 	}
151
-	sortkeys.Strings(keysForAnnotations)
151
+	github_com_gogo_protobuf_sortkeys.Strings(keysForAnnotations)
152 152
 	mapStringForAnnotations := "map[string]string{"
153 153
 	for _, k := range keysForAnnotations {
154 154
 		mapStringForAnnotations += fmt.Sprintf("%#v: %#v,", k, this.Annotations[k])
... ...
@@ -187,8 +236,9 @@ var _ grpc.ClientConn
187 187
 // is compatible with the grpc package it is being compiled against.
188 188
 const _ = grpc.SupportPackageIsVersion4
189 189
 
190
-// Client API for Secrets service
191
-
190
+// SecretsClient is the client API for Secrets service.
191
+//
192
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
192 193
 type SecretsClient interface {
193 194
 	GetSecret(ctx context.Context, in *GetSecretRequest, opts ...grpc.CallOption) (*GetSecretResponse, error)
194 195
 }
... ...
@@ -203,15 +253,14 @@ func NewSecretsClient(cc *grpc.ClientConn) SecretsClient {
203 203
 
204 204
 func (c *secretsClient) GetSecret(ctx context.Context, in *GetSecretRequest, opts ...grpc.CallOption) (*GetSecretResponse, error) {
205 205
 	out := new(GetSecretResponse)
206
-	err := grpc.Invoke(ctx, "/moby.buildkit.secrets.v1.Secrets/GetSecret", in, out, c.cc, opts...)
206
+	err := c.cc.Invoke(ctx, "/moby.buildkit.secrets.v1.Secrets/GetSecret", in, out, opts...)
207 207
 	if err != nil {
208 208
 		return nil, err
209 209
 	}
210 210
 	return out, nil
211 211
 }
212 212
 
213
-// Server API for Secrets service
214
-
213
+// SecretsServer is the server API for Secrets service.
215 214
 type SecretsServer interface {
216 215
 	GetSecret(context.Context, *GetSecretRequest) (*GetSecretResponse, error)
217 216
 }
... ...
@@ -326,6 +375,9 @@ func encodeVarintSecrets(dAtA []byte, offset int, v uint64) int {
326 326
 	return offset + 1
327 327
 }
328 328
 func (m *GetSecretRequest) Size() (n int) {
329
+	if m == nil {
330
+		return 0
331
+	}
329 332
 	var l int
330 333
 	_ = l
331 334
 	l = len(m.ID)
... ...
@@ -344,6 +396,9 @@ func (m *GetSecretRequest) Size() (n int) {
344 344
 }
345 345
 
346 346
 func (m *GetSecretResponse) Size() (n int) {
347
+	if m == nil {
348
+		return 0
349
+	}
347 350
 	var l int
348 351
 	_ = l
349 352
 	l = len(m.Data)
... ...
@@ -374,7 +429,7 @@ func (this *GetSecretRequest) String() string {
374 374
 	for k, _ := range this.Annotations {
375 375
 		keysForAnnotations = append(keysForAnnotations, k)
376 376
 	}
377
-	sortkeys.Strings(keysForAnnotations)
377
+	github_com_gogo_protobuf_sortkeys.Strings(keysForAnnotations)
378 378
 	mapStringForAnnotations := "map[string]string{"
379 379
 	for _, k := range keysForAnnotations {
380 380
 		mapStringForAnnotations += fmt.Sprintf("%v: %v,", k, this.Annotations[k])
... ...
@@ -788,10 +843,10 @@ var (
788 788
 	ErrIntOverflowSecrets   = fmt.Errorf("proto: integer overflow")
789 789
 )
790 790
 
791
-func init() { proto.RegisterFile("secrets.proto", fileDescriptorSecrets) }
791
+func init() { proto.RegisterFile("secrets.proto", fileDescriptor_secrets_21bd4adec74a381e) }
792 792
 
793
-var fileDescriptorSecrets = []byte{
794
-	// 279 bytes of a gzipped FileDescriptorProto
793
+var fileDescriptor_secrets_21bd4adec74a381e = []byte{
794
+	// 288 bytes of a gzipped FileDescriptorProto
795 795
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2d, 0x4e, 0x4d, 0x2e,
796 796
 	0x4a, 0x2d, 0x29, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0xc8, 0xcd, 0x4f, 0xaa, 0xd4,
797 797
 	0x4b, 0x2a, 0xcd, 0xcc, 0x49, 0xc9, 0xce, 0x2c, 0xd1, 0x83, 0x49, 0x96, 0x19, 0x2a, 0x1d, 0x64,
... ...
@@ -805,9 +860,9 @@ var fileDescriptorSecrets = []byte{
805 805
 	0x41, 0x24, 0x1b, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x85, 0x84, 0xb8, 0x58, 0x52, 0x12, 0x4b,
806 806
 	0x12, 0xc1, 0x26, 0xf0, 0x04, 0x81, 0xd9, 0x46, 0xf9, 0x5c, 0xec, 0x10, 0x55, 0xc5, 0x42, 0x29,
807 807
 	0x5c, 0x9c, 0x70, 0x3d, 0x42, 0x5a, 0xc4, 0x7b, 0x45, 0x4a, 0x9b, 0x28, 0xb5, 0x10, 0x47, 0x38,
808
-	0x99, 0x5e, 0x78, 0x28, 0xc7, 0x70, 0xe3, 0xa1, 0x1c, 0xc3, 0x87, 0x87, 0x72, 0x8c, 0x0d, 0x8f,
808
+	0xd9, 0x5e, 0x78, 0x28, 0xc7, 0x70, 0xe3, 0xa1, 0x1c, 0xc3, 0x87, 0x87, 0x72, 0x8c, 0x0d, 0x8f,
809 809
 	0xe4, 0x18, 0x57, 0x3c, 0x92, 0x63, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07,
810 810
 	0x8f, 0xe4, 0x18, 0x5f, 0x3c, 0x92, 0x63, 0xf8, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86,
811
-	0x28, 0x76, 0xa8, 0x59, 0x49, 0x6c, 0xe0, 0x58, 0x33, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x05,
812
-	0x4e, 0x56, 0xde, 0xc6, 0x01, 0x00, 0x00,
811
+	0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x62, 0x87, 0x9a, 0x99, 0xc4, 0x06, 0x8e,
812
+	0x3d, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2c, 0x38, 0xec, 0x1f, 0xce, 0x01, 0x00, 0x00,
813 813
 }
... ...
@@ -1,17 +1,6 @@
1 1
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
2 2
 // source: ssh.proto
3 3
 
4
-/*
5
-Package sshforward is a generated protocol buffer package.
6
-
7
-It is generated from these files:
8
-	ssh.proto
9
-
10
-It has these top-level messages:
11
-	BytesMessage
12
-	CheckAgentRequest
13
-	CheckAgentResponse
14
-*/
15 4
 package sshforward
16 5
 
17 6
 import proto "github.com/gogo/protobuf/proto"
... ...
@@ -23,8 +12,10 @@ import bytes "bytes"
23 23
 import strings "strings"
24 24
 import reflect "reflect"
25 25
 
26
-import context "golang.org/x/net/context"
27
-import grpc "google.golang.org/grpc"
26
+import (
27
+	context "golang.org/x/net/context"
28
+	grpc "google.golang.org/grpc"
29
+)
28 30
 
29 31
 import io "io"
30 32
 
... ...
@@ -44,9 +35,37 @@ type BytesMessage struct {
44 44
 	Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
45 45
 }
46 46
 
47
-func (m *BytesMessage) Reset()                    { *m = BytesMessage{} }
48
-func (*BytesMessage) ProtoMessage()               {}
49
-func (*BytesMessage) Descriptor() ([]byte, []int) { return fileDescriptorSsh, []int{0} }
47
+func (m *BytesMessage) Reset()      { *m = BytesMessage{} }
48
+func (*BytesMessage) ProtoMessage() {}
49
+func (*BytesMessage) Descriptor() ([]byte, []int) {
50
+	return fileDescriptor_ssh_13bd2c34c031d472, []int{0}
51
+}
52
+func (m *BytesMessage) XXX_Unmarshal(b []byte) error {
53
+	return m.Unmarshal(b)
54
+}
55
+func (m *BytesMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
56
+	if deterministic {
57
+		return xxx_messageInfo_BytesMessage.Marshal(b, m, deterministic)
58
+	} else {
59
+		b = b[:cap(b)]
60
+		n, err := m.MarshalTo(b)
61
+		if err != nil {
62
+			return nil, err
63
+		}
64
+		return b[:n], nil
65
+	}
66
+}
67
+func (dst *BytesMessage) XXX_Merge(src proto.Message) {
68
+	xxx_messageInfo_BytesMessage.Merge(dst, src)
69
+}
70
+func (m *BytesMessage) XXX_Size() int {
71
+	return m.Size()
72
+}
73
+func (m *BytesMessage) XXX_DiscardUnknown() {
74
+	xxx_messageInfo_BytesMessage.DiscardUnknown(m)
75
+}
76
+
77
+var xxx_messageInfo_BytesMessage proto.InternalMessageInfo
50 78
 
51 79
 func (m *BytesMessage) GetData() []byte {
52 80
 	if m != nil {
... ...
@@ -59,9 +78,37 @@ type CheckAgentRequest struct {
59 59
 	ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
60 60
 }
61 61
 
62
-func (m *CheckAgentRequest) Reset()                    { *m = CheckAgentRequest{} }
63
-func (*CheckAgentRequest) ProtoMessage()               {}
64
-func (*CheckAgentRequest) Descriptor() ([]byte, []int) { return fileDescriptorSsh, []int{1} }
62
+func (m *CheckAgentRequest) Reset()      { *m = CheckAgentRequest{} }
63
+func (*CheckAgentRequest) ProtoMessage() {}
64
+func (*CheckAgentRequest) Descriptor() ([]byte, []int) {
65
+	return fileDescriptor_ssh_13bd2c34c031d472, []int{1}
66
+}
67
+func (m *CheckAgentRequest) XXX_Unmarshal(b []byte) error {
68
+	return m.Unmarshal(b)
69
+}
70
+func (m *CheckAgentRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
71
+	if deterministic {
72
+		return xxx_messageInfo_CheckAgentRequest.Marshal(b, m, deterministic)
73
+	} else {
74
+		b = b[:cap(b)]
75
+		n, err := m.MarshalTo(b)
76
+		if err != nil {
77
+			return nil, err
78
+		}
79
+		return b[:n], nil
80
+	}
81
+}
82
+func (dst *CheckAgentRequest) XXX_Merge(src proto.Message) {
83
+	xxx_messageInfo_CheckAgentRequest.Merge(dst, src)
84
+}
85
+func (m *CheckAgentRequest) XXX_Size() int {
86
+	return m.Size()
87
+}
88
+func (m *CheckAgentRequest) XXX_DiscardUnknown() {
89
+	xxx_messageInfo_CheckAgentRequest.DiscardUnknown(m)
90
+}
91
+
92
+var xxx_messageInfo_CheckAgentRequest proto.InternalMessageInfo
65 93
 
66 94
 func (m *CheckAgentRequest) GetID() string {
67 95
 	if m != nil {
... ...
@@ -73,9 +120,37 @@ func (m *CheckAgentRequest) GetID() string {
73 73
 type CheckAgentResponse struct {
74 74
 }
75 75
 
76
-func (m *CheckAgentResponse) Reset()                    { *m = CheckAgentResponse{} }
77
-func (*CheckAgentResponse) ProtoMessage()               {}
78
-func (*CheckAgentResponse) Descriptor() ([]byte, []int) { return fileDescriptorSsh, []int{2} }
76
+func (m *CheckAgentResponse) Reset()      { *m = CheckAgentResponse{} }
77
+func (*CheckAgentResponse) ProtoMessage() {}
78
+func (*CheckAgentResponse) Descriptor() ([]byte, []int) {
79
+	return fileDescriptor_ssh_13bd2c34c031d472, []int{2}
80
+}
81
+func (m *CheckAgentResponse) XXX_Unmarshal(b []byte) error {
82
+	return m.Unmarshal(b)
83
+}
84
+func (m *CheckAgentResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
85
+	if deterministic {
86
+		return xxx_messageInfo_CheckAgentResponse.Marshal(b, m, deterministic)
87
+	} else {
88
+		b = b[:cap(b)]
89
+		n, err := m.MarshalTo(b)
90
+		if err != nil {
91
+			return nil, err
92
+		}
93
+		return b[:n], nil
94
+	}
95
+}
96
+func (dst *CheckAgentResponse) XXX_Merge(src proto.Message) {
97
+	xxx_messageInfo_CheckAgentResponse.Merge(dst, src)
98
+}
99
+func (m *CheckAgentResponse) XXX_Size() int {
100
+	return m.Size()
101
+}
102
+func (m *CheckAgentResponse) XXX_DiscardUnknown() {
103
+	xxx_messageInfo_CheckAgentResponse.DiscardUnknown(m)
104
+}
105
+
106
+var xxx_messageInfo_CheckAgentResponse proto.InternalMessageInfo
79 107
 
80 108
 func init() {
81 109
 	proto.RegisterType((*BytesMessage)(nil), "moby.sshforward.v1.BytesMessage")
... ...
@@ -197,8 +272,9 @@ var _ grpc.ClientConn
197 197
 // is compatible with the grpc package it is being compiled against.
198 198
 const _ = grpc.SupportPackageIsVersion4
199 199
 
200
-// Client API for SSH service
201
-
200
+// SSHClient is the client API for SSH service.
201
+//
202
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
202 203
 type SSHClient interface {
203 204
 	CheckAgent(ctx context.Context, in *CheckAgentRequest, opts ...grpc.CallOption) (*CheckAgentResponse, error)
204 205
 	ForwardAgent(ctx context.Context, opts ...grpc.CallOption) (SSH_ForwardAgentClient, error)
... ...
@@ -214,7 +290,7 @@ func NewSSHClient(cc *grpc.ClientConn) SSHClient {
214 214
 
215 215
 func (c *sSHClient) CheckAgent(ctx context.Context, in *CheckAgentRequest, opts ...grpc.CallOption) (*CheckAgentResponse, error) {
216 216
 	out := new(CheckAgentResponse)
217
-	err := grpc.Invoke(ctx, "/moby.sshforward.v1.SSH/CheckAgent", in, out, c.cc, opts...)
217
+	err := c.cc.Invoke(ctx, "/moby.sshforward.v1.SSH/CheckAgent", in, out, opts...)
218 218
 	if err != nil {
219 219
 		return nil, err
220 220
 	}
... ...
@@ -222,7 +298,7 @@ func (c *sSHClient) CheckAgent(ctx context.Context, in *CheckAgentRequest, opts
222 222
 }
223 223
 
224 224
 func (c *sSHClient) ForwardAgent(ctx context.Context, opts ...grpc.CallOption) (SSH_ForwardAgentClient, error) {
225
-	stream, err := grpc.NewClientStream(ctx, &_SSH_serviceDesc.Streams[0], c.cc, "/moby.sshforward.v1.SSH/ForwardAgent", opts...)
225
+	stream, err := c.cc.NewStream(ctx, &_SSH_serviceDesc.Streams[0], "/moby.sshforward.v1.SSH/ForwardAgent", opts...)
226 226
 	if err != nil {
227 227
 		return nil, err
228 228
 	}
... ...
@@ -252,8 +328,7 @@ func (x *sSHForwardAgentClient) Recv() (*BytesMessage, error) {
252 252
 	return m, nil
253 253
 }
254 254
 
255
-// Server API for SSH service
256
-
255
+// SSHServer is the server API for SSH service.
257 256
 type SSHServer interface {
258 257
 	CheckAgent(context.Context, *CheckAgentRequest) (*CheckAgentResponse, error)
259 258
 	ForwardAgent(SSH_ForwardAgentServer) error
... ...
@@ -403,6 +478,9 @@ func encodeVarintSsh(dAtA []byte, offset int, v uint64) int {
403 403
 	return offset + 1
404 404
 }
405 405
 func (m *BytesMessage) Size() (n int) {
406
+	if m == nil {
407
+		return 0
408
+	}
406 409
 	var l int
407 410
 	_ = l
408 411
 	l = len(m.Data)
... ...
@@ -413,6 +491,9 @@ func (m *BytesMessage) Size() (n int) {
413 413
 }
414 414
 
415 415
 func (m *CheckAgentRequest) Size() (n int) {
416
+	if m == nil {
417
+		return 0
418
+	}
416 419
 	var l int
417 420
 	_ = l
418 421
 	l = len(m.ID)
... ...
@@ -423,6 +504,9 @@ func (m *CheckAgentRequest) Size() (n int) {
423 423
 }
424 424
 
425 425
 func (m *CheckAgentResponse) Size() (n int) {
426
+	if m == nil {
427
+		return 0
428
+	}
426 429
 	var l int
427 430
 	_ = l
428 431
 	return n
... ...
@@ -793,10 +877,10 @@ var (
793 793
 	ErrIntOverflowSsh   = fmt.Errorf("proto: integer overflow")
794 794
 )
795 795
 
796
-func init() { proto.RegisterFile("ssh.proto", fileDescriptorSsh) }
796
+func init() { proto.RegisterFile("ssh.proto", fileDescriptor_ssh_13bd2c34c031d472) }
797 797
 
798
-var fileDescriptorSsh = []byte{
799
-	// 243 bytes of a gzipped FileDescriptorProto
798
+var fileDescriptor_ssh_13bd2c34c031d472 = []byte{
799
+	// 252 bytes of a gzipped FileDescriptorProto
800 800
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2c, 0x2e, 0xce, 0xd0,
801 801
 	0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xca, 0xcd, 0x4f, 0xaa, 0xd4, 0x2b, 0x2e, 0xce, 0x48,
802 802
 	0xcb, 0x2f, 0x2a, 0x4f, 0x2c, 0x4a, 0xd1, 0x2b, 0x33, 0x54, 0x52, 0xe2, 0xe2, 0x71, 0xaa, 0x2c,
... ...
@@ -807,10 +891,10 @@ var fileDescriptorSsh = []byte{
807 807
 	0x90, 0x15, 0x15, 0x17, 0xe4, 0xe7, 0x15, 0xa7, 0x1a, 0xed, 0x62, 0xe4, 0x62, 0x0e, 0x0e, 0xf6,
808 808
 	0x10, 0x8a, 0xe6, 0xe2, 0x42, 0xc8, 0x0a, 0xa9, 0xea, 0x61, 0xba, 0x44, 0x0f, 0xc3, 0x0a, 0x29,
809 809
 	0x35, 0x42, 0xca, 0x20, 0x96, 0x08, 0x85, 0x71, 0xf1, 0xb8, 0x41, 0x14, 0x40, 0x8c, 0x57, 0xc0,
810
-	0xa6, 0x0f, 0xd9, 0x97, 0x52, 0x04, 0x55, 0x68, 0x30, 0x1a, 0x30, 0x3a, 0x59, 0x5c, 0x78, 0x28,
810
+	0xa6, 0x0f, 0xd9, 0x97, 0x52, 0x04, 0x55, 0x68, 0x30, 0x1a, 0x30, 0x3a, 0x39, 0x5c, 0x78, 0x28,
811 811
 	0xc7, 0x70, 0xe3, 0xa1, 0x1c, 0xc3, 0x87, 0x87, 0x72, 0x8c, 0x0d, 0x8f, 0xe4, 0x18, 0x57, 0x3c,
812 812
 	0x92, 0x63, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x5f,
813
-	0x3c, 0x92, 0x63, 0xf8, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x28, 0x2e, 0x84, 0x69,
814
-	0x49, 0x6c, 0xe0, 0x00, 0x37, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x31, 0x3e, 0x40, 0xab, 0x7d,
815
-	0x01, 0x00, 0x00,
813
+	0x3c, 0x92, 0x63, 0xf8, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18,
814
+	0x6e, 0x3c, 0x96, 0x63, 0x88, 0xe2, 0x42, 0x98, 0x9a, 0xc4, 0x06, 0x0e, 0x78, 0x63, 0x40, 0x00,
815
+	0x00, 0x00, 0xff, 0xff, 0x6c, 0xe6, 0x6d, 0xb7, 0x85, 0x01, 0x00, 0x00,
816 816
 }
... ...
@@ -3,7 +3,9 @@ package solver
3 3
 import (
4 4
 	"context"
5 5
 	"fmt"
6
+	"strings"
6 7
 	"sync"
8
+	"time"
7 9
 
8 10
 	"github.com/moby/buildkit/identity"
9 11
 	digest "github.com/opencontainers/go-digest"
... ...
@@ -142,15 +144,87 @@ func (c *cacheManager) Load(ctx context.Context, rec *CacheRecord) (Result, erro
142 142
 	return c.results.Load(ctx, res)
143 143
 }
144 144
 
145
-func (c *cacheManager) Save(k *CacheKey, r Result) (*ExportableCacheKey, error) {
145
+type LoadedResult struct {
146
+	Result      Result
147
+	CacheResult CacheResult
148
+	CacheKey    *CacheKey
149
+}
150
+
151
+func (c *cacheManager) filterResults(m map[string]Result, ck *CacheKey) (results []LoadedResult, err error) {
152
+	id := c.getID(ck)
153
+	if err := c.backend.WalkResults(id, func(cr CacheResult) error {
154
+		res, ok := m[id]
155
+		if ok {
156
+			results = append(results, LoadedResult{
157
+				Result:      res,
158
+				CacheKey:    ck,
159
+				CacheResult: cr,
160
+			})
161
+			delete(m, id)
162
+		}
163
+		return nil
164
+	}); err != nil {
165
+		for _, r := range results {
166
+			r.Result.Release(context.TODO())
167
+		}
168
+	}
169
+	for _, keys := range ck.Deps() {
170
+		for _, key := range keys {
171
+			res, err := c.filterResults(m, key.CacheKey.CacheKey)
172
+			if err != nil {
173
+				for _, r := range results {
174
+					r.Result.Release(context.TODO())
175
+				}
176
+				return nil, err
177
+			}
178
+			results = append(results, res...)
179
+		}
180
+	}
181
+	return
182
+}
183
+
184
+func (c *cacheManager) LoadWithParents(ctx context.Context, rec *CacheRecord) ([]LoadedResult, error) {
185
+	lwp, ok := c.results.(interface {
186
+		LoadWithParents(context.Context, CacheResult) (map[string]Result, error)
187
+	})
188
+	if !ok {
189
+		res, err := c.Load(ctx, rec)
190
+		if err != nil {
191
+			return nil, err
192
+		}
193
+		return []LoadedResult{{Result: res, CacheKey: rec.key, CacheResult: CacheResult{ID: c.getID(rec.key), CreatedAt: rec.CreatedAt}}}, nil
194
+	}
195
+	c.mu.RLock()
196
+	defer c.mu.RUnlock()
197
+
198
+	cr, err := c.backend.Load(c.getID(rec.key), rec.ID)
199
+	if err != nil {
200
+		return nil, err
201
+	}
202
+
203
+	m, err := lwp.LoadWithParents(ctx, cr)
204
+	if err != nil {
205
+		return nil, err
206
+	}
207
+
208
+	results, err := c.filterResults(m, rec.key)
209
+	if err != nil {
210
+		for _, r := range m {
211
+			r.Release(context.TODO())
212
+		}
213
+	}
214
+
215
+	return results, nil
216
+}
217
+
218
+func (c *cacheManager) Save(k *CacheKey, r Result, createdAt time.Time) (*ExportableCacheKey, error) {
146 219
 	c.mu.Lock()
147 220
 	defer c.mu.Unlock()
148 221
 
149
-	res, err := c.results.Save(r)
222
+	res, err := c.results.Save(r, createdAt)
150 223
 	if err != nil {
151 224
 		return nil, err
152 225
 	}
153
-
154 226
 	if err := c.backend.AddResult(c.getID(k), res); err != nil {
155 227
 		return nil, err
156 228
 	}
... ...
@@ -273,5 +347,8 @@ func (c *cacheManager) getIDFromDeps(k *CacheKey) string {
273 273
 }
274 274
 
275 275
 func rootKey(dgst digest.Digest, output Index) digest.Digest {
276
+	if strings.HasPrefix(dgst.String(), "random:") {
277
+		return digest.Digest("random:" + strings.TrimPrefix(digest.FromBytes([]byte(fmt.Sprintf("%s@%d", dgst, output))).String(), digest.Canonical.String()+":"))
278
+	}
276 279
 	return digest.FromBytes([]byte(fmt.Sprintf("%s@%d", dgst, output)))
277 280
 }
... ...
@@ -44,7 +44,7 @@ type CacheInfoLink struct {
44 44
 // CacheResultStorage is interface for converting cache metadata result to
45 45
 // actual solve result
46 46
 type CacheResultStorage interface {
47
-	Save(Result) (CacheResult, error)
47
+	Save(Result, time.Time) (CacheResult, error)
48 48
 	Load(ctx context.Context, res CacheResult) (Result, error)
49 49
 	LoadRemote(ctx context.Context, res CacheResult) (*Remote, error)
50 50
 	Exists(id string) bool
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"context"
5 5
 	"strings"
6 6
 	"sync"
7
+	"time"
7 8
 
8 9
 	digest "github.com/opencontainers/go-digest"
9 10
 	"github.com/pkg/errors"
... ...
@@ -66,19 +67,31 @@ func (cm *combinedCacheManager) Query(inp []CacheKeyWithSelector, inputIndex Ind
66 66
 	return out, nil
67 67
 }
68 68
 
69
-func (cm *combinedCacheManager) Load(ctx context.Context, rec *CacheRecord) (Result, error) {
70
-	res, err := rec.cacheManager.Load(ctx, rec)
69
+func (cm *combinedCacheManager) Load(ctx context.Context, rec *CacheRecord) (res Result, err error) {
70
+	results, err := rec.cacheManager.LoadWithParents(ctx, rec)
71 71
 	if err != nil {
72 72
 		return nil, err
73 73
 	}
74
-	if _, err := cm.main.Save(rec.key, res); err != nil {
75
-		return nil, err
74
+	defer func() {
75
+		for i, res := range results {
76
+			if err == nil && i == 0 {
77
+				continue
78
+			}
79
+			res.Result.Release(context.TODO())
80
+		}
81
+	}()
82
+	if rec.cacheManager != cm.main {
83
+		for _, res := range results {
84
+			if _, err := cm.main.Save(res.CacheKey, res.Result, res.CacheResult.CreatedAt); err != nil {
85
+				return nil, err
86
+			}
87
+		}
76 88
 	}
77
-	return res, nil
89
+	return results[0].Result, nil
78 90
 }
79 91
 
80
-func (cm *combinedCacheManager) Save(key *CacheKey, s Result) (*ExportableCacheKey, error) {
81
-	return cm.main.Save(key, s)
92
+func (cm *combinedCacheManager) Save(key *CacheKey, s Result, createdAt time.Time) (*ExportableCacheKey, error) {
93
+	return cm.main.Save(key, s, createdAt)
82 94
 }
83 95
 
84 96
 func (cm *combinedCacheManager) Records(ck *CacheKey) ([]*CacheRecord, error) {
... ...
@@ -3,6 +3,7 @@ package solver
3 3
 import (
4 4
 	"context"
5 5
 	"sync"
6
+	"time"
6 7
 
7 8
 	"github.com/moby/buildkit/solver/internal/pipe"
8 9
 	digest "github.com/opencontainers/go-digest"
... ...
@@ -28,7 +29,7 @@ func newEdge(ed Edge, op activeOp, index *edgeIndex) *edge {
28 28
 		edge:         ed,
29 29
 		op:           op,
30 30
 		depRequests:  map[pipe.Receiver]*dep{},
31
-		keyMap:       map[string]*CacheKey{},
31
+		keyMap:       map[string]struct{}{},
32 32
 		cacheRecords: map[string]*CacheRecord{},
33 33
 		index:        index,
34 34
 	}
... ...
@@ -50,7 +51,7 @@ type edge struct {
50 50
 	execReq         pipe.Receiver
51 51
 	err             error
52 52
 	cacheRecords    map[string]*CacheRecord
53
-	keyMap          map[string]*CacheKey
53
+	keyMap          map[string]struct{}
54 54
 
55 55
 	noCacheMatchPossible      bool
56 56
 	allDepsCompletedCacheFast bool
... ...
@@ -526,6 +527,10 @@ func (e *edge) recalcCurrentState() {
526 526
 		}
527 527
 	}
528 528
 
529
+	for key := range newKeys {
530
+		e.keyMap[key] = struct{}{}
531
+	}
532
+
529 533
 	for _, r := range newKeys {
530 534
 		// TODO: add all deps automatically
531 535
 		mergedKey := r.clone()
... ...
@@ -612,6 +617,36 @@ func (e *edge) recalcCurrentState() {
612 612
 		e.allDepsCompletedCacheSlow = e.cacheMapDone && allDepsCompletedCacheSlow
613 613
 		e.allDepsStateCacheSlow = e.cacheMapDone && allDepsStateCacheSlow
614 614
 		e.allDepsCompleted = e.cacheMapDone && allDepsCompleted
615
+
616
+		if e.allDepsStateCacheSlow && len(e.cacheRecords) > 0 && e.state == edgeStatusCacheFast {
617
+			openKeys := map[string]struct{}{}
618
+			for _, dep := range e.deps {
619
+				isSlowIncomplete := e.slowCacheFunc(dep) != nil && (dep.state == edgeStatusCacheSlow || (dep.state == edgeStatusComplete && !dep.slowCacheComplete))
620
+				if !isSlowIncomplete {
621
+					openDepKeys := map[string]struct{}{}
622
+					for key := range dep.keyMap {
623
+						if _, ok := e.keyMap[key]; !ok {
624
+							openDepKeys[key] = struct{}{}
625
+						}
626
+					}
627
+					if len(openKeys) != 0 {
628
+						for k := range openKeys {
629
+							if _, ok := openDepKeys[k]; !ok {
630
+								delete(openKeys, k)
631
+							}
632
+						}
633
+					} else {
634
+						openKeys = openDepKeys
635
+					}
636
+					if len(openKeys) == 0 {
637
+						e.state = edgeStatusCacheSlow
638
+						if debugScheduler {
639
+							logrus.Debugf("upgrade to cache-slow because no open keys")
640
+						}
641
+					}
642
+				}
643
+			}
644
+		}
615 645
 	}
616 646
 }
617 647
 
... ...
@@ -845,7 +880,7 @@ func (e *edge) execOp(ctx context.Context) (interface{}, error) {
845 845
 	var exporters []CacheExporter
846 846
 
847 847
 	for _, cacheKey := range cacheKeys {
848
-		ck, err := e.op.Cache().Save(cacheKey, res)
848
+		ck, err := e.op.Cache().Save(cacheKey, res, time.Now())
849 849
 		if err != nil {
850 850
 			return nil, err
851 851
 		}
... ...
@@ -177,7 +177,7 @@ func (sb *subBuilder) Context(ctx context.Context) context.Context {
177 177
 
178 178
 func (sb *subBuilder) EachValue(ctx context.Context, key string, fn func(interface{}) error) error {
179 179
 	sb.mu.Lock()
180
-	defer sb.mu.Lock()
180
+	defer sb.mu.Unlock()
181 181
 	for j := range sb.jobs {
182 182
 		if err := j.EachValue(ctx, key, fn); err != nil {
183 183
 			return err
... ...
@@ -6,30 +6,34 @@ import (
6 6
 	"io"
7 7
 	"strings"
8 8
 	"sync"
9
+	"time"
9 10
 
10 11
 	"github.com/containerd/containerd/platforms"
11
-	"github.com/docker/distribution/reference"
12 12
 	"github.com/moby/buildkit/cache"
13 13
 	"github.com/moby/buildkit/cache/remotecache"
14 14
 	"github.com/moby/buildkit/executor"
15 15
 	"github.com/moby/buildkit/frontend"
16 16
 	gw "github.com/moby/buildkit/frontend/gateway/client"
17
+	"github.com/moby/buildkit/identity"
18
+	"github.com/moby/buildkit/session"
17 19
 	"github.com/moby/buildkit/solver"
18 20
 	"github.com/moby/buildkit/util/tracing"
19 21
 	"github.com/moby/buildkit/worker"
20 22
 	digest "github.com/opencontainers/go-digest"
21 23
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
22 24
 	"github.com/pkg/errors"
25
+	"github.com/sirupsen/logrus"
23 26
 )
24 27
 
25 28
 type llbBridge struct {
26
-	builder              solver.Builder
27
-	frontends            map[string]frontend.Frontend
28
-	resolveWorker        func() (worker.Worker, error)
29
-	resolveCacheImporter remotecache.ResolveCacheImporterFunc
30
-	cms                  map[string]solver.CacheManager
31
-	cmsMu                sync.Mutex
32
-	platforms            []specs.Platform
29
+	builder                   solver.Builder
30
+	frontends                 map[string]frontend.Frontend
31
+	resolveWorker             func() (worker.Worker, error)
32
+	resolveCacheImporterFuncs map[string]remotecache.ResolveCacheImporterFunc
33
+	cms                       map[string]solver.CacheManager
34
+	cmsMu                     sync.Mutex
35
+	platforms                 []specs.Platform
36
+	sm                        *session.Manager
33 37
 }
34 38
 
35 39
 func (b *llbBridge) Solve(ctx context.Context, req frontend.SolveRequest) (res *frontend.Result, err error) {
... ...
@@ -38,36 +42,39 @@ func (b *llbBridge) Solve(ctx context.Context, req frontend.SolveRequest) (res *
38 38
 		return nil, err
39 39
 	}
40 40
 	var cms []solver.CacheManager
41
-	for _, ref := range req.ImportCacheRefs {
41
+	for _, im := range req.CacheImports {
42 42
 		b.cmsMu.Lock()
43 43
 		var cm solver.CacheManager
44
-		if prevCm, ok := b.cms[ref]; !ok {
45
-			r, err := reference.ParseNormalizedNamed(ref)
46
-			if err != nil {
47
-				return nil, err
44
+		cmId := identity.NewID()
45
+		if im.Type == "registry" {
46
+			// For compatibility with < v0.4.0
47
+			if ref := im.Attrs["ref"]; ref != "" {
48
+				cmId = ref
48 49
 			}
49
-			ref = reference.TagNameOnly(r).String()
50
-			func(ref string) {
51
-				cm = newLazyCacheManager(ref, func() (solver.CacheManager, error) {
50
+		}
51
+		if prevCm, ok := b.cms[cmId]; !ok {
52
+			func(cmId string) {
53
+				cm = newLazyCacheManager(cmId, func() (solver.CacheManager, error) {
52 54
 					var cmNew solver.CacheManager
53
-					if err := inVertexContext(b.builder.Context(ctx), "importing cache manifest from "+ref, "", func(ctx context.Context) error {
54
-						if b.resolveCacheImporter == nil {
55
-							return errors.New("no cache importer is available")
55
+					if err := inVertexContext(b.builder.Context(ctx), "importing cache manifest from "+cmId, "", func(ctx context.Context) error {
56
+						resolveCI, ok := b.resolveCacheImporterFuncs[im.Type]
57
+						if !ok {
58
+							return errors.Errorf("unknown cache importer: %s", im.Type)
56 59
 						}
57
-						typ := "" // TODO: support non-registry type
58
-						ci, desc, err := b.resolveCacheImporter(ctx, typ, ref)
60
+						ci, desc, err := resolveCI(ctx, im.Attrs)
59 61
 						if err != nil {
60 62
 							return err
61 63
 						}
62
-						cmNew, err = ci.Resolve(ctx, desc, ref, w)
64
+						cmNew, err = ci.Resolve(ctx, desc, cmId, w)
63 65
 						return err
64 66
 					}); err != nil {
67
+						logrus.Debugf("error while importing cache manifest from cmId=%s: %v", cmId, err)
65 68
 						return nil, err
66 69
 					}
67 70
 					return cmNew, nil
68 71
 				})
69
-			}(ref)
70
-			b.cms[ref] = cm
72
+			}(cmId)
73
+			b.cms[cmId] = cm
71 74
 		} else {
72 75
 			cm = prevCm
73 76
 		}
... ...
@@ -151,7 +158,7 @@ func (s *llbBridge) ResolveImageConfig(ctx context.Context, ref string, opt gw.R
151 151
 		id += platforms.Format(*platform)
152 152
 	}
153 153
 	err = inVertexContext(s.builder.Context(ctx), opt.LogName, id, func(ctx context.Context) error {
154
-		dgst, config, err = w.ResolveImageConfig(ctx, ref, opt)
154
+		dgst, config, err = w.ResolveImageConfig(ctx, ref, opt, s.sm)
155 155
 		return err
156 156
 	})
157 157
 	return dgst, config, err
... ...
@@ -186,11 +193,11 @@ func (lcm *lazyCacheManager) Load(ctx context.Context, rec *solver.CacheRecord)
186 186
 	}
187 187
 	return lcm.main.Load(ctx, rec)
188 188
 }
189
-func (lcm *lazyCacheManager) Save(key *solver.CacheKey, s solver.Result) (*solver.ExportableCacheKey, error) {
189
+func (lcm *lazyCacheManager) Save(key *solver.CacheKey, s solver.Result, createdAt time.Time) (*solver.ExportableCacheKey, error) {
190 190
 	if err := lcm.wait(); err != nil {
191 191
 		return nil, err
192 192
 	}
193
-	return lcm.main.Save(key, s)
193
+	return lcm.main.Save(key, s, createdAt)
194 194
 }
195 195
 
196 196
 func (lcm *lazyCacheManager) wait() error {
... ...
@@ -10,13 +10,13 @@ import (
10 10
 	"os"
11 11
 	"path"
12 12
 	"path/filepath"
13
-	"runtime"
14 13
 	"sort"
15 14
 	"strings"
16 15
 	"sync"
17 16
 	"time"
18 17
 
19 18
 	"github.com/containerd/containerd/mount"
19
+	"github.com/containerd/containerd/platforms"
20 20
 	"github.com/docker/docker/pkg/locker"
21 21
 	"github.com/moby/buildkit/cache"
22 22
 	"github.com/moby/buildkit/cache/metadata"
... ...
@@ -34,6 +34,7 @@ import (
34 34
 	utilsystem "github.com/moby/buildkit/util/system"
35 35
 	"github.com/moby/buildkit/worker"
36 36
 	digest "github.com/opencontainers/go-digest"
37
+	specs "github.com/opencontainers/image-spec/specs-go/v1"
37 38
 	"github.com/opencontainers/runc/libcontainer/system"
38 39
 	"github.com/pkg/errors"
39 40
 	"github.com/sirupsen/logrus"
... ...
@@ -51,12 +52,13 @@ type execOp struct {
51 51
 	md        *metadata.Store
52 52
 	exec      executor.Executor
53 53
 	w         worker.Worker
54
+	platform  *pb.Platform
54 55
 	numInputs int
55 56
 
56 57
 	cacheMounts map[string]*cacheRefShare
57 58
 }
58 59
 
59
-func NewExecOp(v solver.Vertex, op *pb.Op_Exec, cm cache.Manager, sm *session.Manager, md *metadata.Store, exec executor.Executor, w worker.Worker) (solver.Op, error) {
60
+func NewExecOp(v solver.Vertex, op *pb.Op_Exec, platform *pb.Platform, cm cache.Manager, sm *session.Manager, md *metadata.Store, exec executor.Executor, w worker.Worker) (solver.Op, error) {
60 61
 	return &execOp{
61 62
 		op:          op.Exec,
62 63
 		cm:          cm,
... ...
@@ -65,6 +67,7 @@ func NewExecOp(v solver.Vertex, op *pb.Op_Exec, cm cache.Manager, sm *session.Ma
65 65
 		exec:        exec,
66 66
 		numInputs:   len(v.Inputs()),
67 67
 		w:           w,
68
+		platform:    platform,
68 69
 		cacheMounts: map[string]*cacheRefShare{},
69 70
 	}, nil
70 71
 }
... ...
@@ -98,16 +101,27 @@ func (e *execOp) CacheMap(ctx context.Context, index int) (*solver.CacheMap, boo
98 98
 	}
99 99
 	op.Meta.ProxyEnv = nil
100 100
 
101
+	p := platforms.DefaultSpec()
102
+	if e.platform != nil {
103
+		p = specs.Platform{
104
+			OS:           e.platform.OS,
105
+			Architecture: e.platform.Architecture,
106
+			Variant:      e.platform.Variant,
107
+		}
108
+	}
109
+
101 110
 	dt, err := json.Marshal(struct {
102
-		Type string
103
-		Exec *pb.ExecOp
104
-		OS   string
105
-		Arch string
111
+		Type    string
112
+		Exec    *pb.ExecOp
113
+		OS      string
114
+		Arch    string
115
+		Variant string `json:",omitempty"`
106 116
 	}{
107
-		Type: execCacheType,
108
-		Exec: &op,
109
-		OS:   runtime.GOOS,
110
-		Arch: runtime.GOARCH,
117
+		Type:    execCacheType,
118
+		Exec:    &op,
119
+		OS:      p.OS,
120
+		Arch:    p.Architecture,
121
+		Variant: p.Variant,
111 122
 	})
112 123
 	if err != nil {
113 124
 		return nil, false, err
... ...
@@ -151,7 +165,7 @@ func dedupePaths(inp []string) []string {
151 151
 	for p1 := range old {
152 152
 		var skip bool
153 153
 		for p2 := range old {
154
-			if p1 != p2 && strings.HasPrefix(p1, p2) {
154
+			if p1 != p2 && strings.HasPrefix(p1, p2+"/") {
155 155
 				skip = true
156 156
 				break
157 157
 			}
... ...
@@ -2,8 +2,10 @@ package ops
2 2
 
3 3
 import (
4 4
 	"context"
5
+	"strings"
5 6
 	"sync"
6 7
 
8
+	"github.com/moby/buildkit/session"
7 9
 	"github.com/moby/buildkit/solver"
8 10
 	"github.com/moby/buildkit/solver/pb"
9 11
 	"github.com/moby/buildkit/source"
... ...
@@ -19,14 +21,16 @@ type sourceOp struct {
19 19
 	platform *pb.Platform
20 20
 	sm       *source.Manager
21 21
 	src      source.SourceInstance
22
+	sessM    *session.Manager
22 23
 	w        worker.Worker
23 24
 }
24 25
 
25
-func NewSourceOp(_ solver.Vertex, op *pb.Op_Source, platform *pb.Platform, sm *source.Manager, w worker.Worker) (solver.Op, error) {
26
+func NewSourceOp(_ solver.Vertex, op *pb.Op_Source, platform *pb.Platform, sm *source.Manager, sessM *session.Manager, w worker.Worker) (solver.Op, error) {
26 27
 	return &sourceOp{
27 28
 		op:       op,
28 29
 		sm:       sm,
29 30
 		w:        w,
31
+		sessM:    sessM,
30 32
 		platform: platform,
31 33
 	}, nil
32 34
 }
... ...
@@ -41,7 +45,7 @@ func (s *sourceOp) instance(ctx context.Context) (source.SourceInstance, error)
41 41
 	if err != nil {
42 42
 		return nil, err
43 43
 	}
44
-	src, err := s.sm.Resolve(ctx, id)
44
+	src, err := s.sm.Resolve(ctx, id, s.sessM)
45 45
 	if err != nil {
46 46
 		return nil, err
47 47
 	}
... ...
@@ -59,9 +63,15 @@ func (s *sourceOp) CacheMap(ctx context.Context, index int) (*solver.CacheMap, b
59 59
 		return nil, false, err
60 60
 	}
61 61
 
62
+	dgst := digest.FromBytes([]byte(sourceCacheType + ":" + k))
63
+
64
+	if strings.HasPrefix(k, "session:") {
65
+		dgst = digest.Digest("random:" + strings.TrimPrefix(dgst.String(), dgst.Algorithm().String()+":"))
66
+	}
67
+
62 68
 	return &solver.CacheMap{
63 69
 		// TODO: add os/arch
64
-		Digest: digest.FromBytes([]byte(sourceCacheType + ":" + k)),
70
+		Digest: dgst,
65 71
 	}, done, nil
66 72
 }
67 73
 
... ...
@@ -32,7 +32,7 @@ func NewContentHashFunc(selectors []string) solver.ResultBasedCacheFunc {
32 32
 			// FIXME(tonistiigi): enabling this parallelization seems to create wrong results for some big inputs(like gobuild)
33 33
 			// func(i int) {
34 34
 			// 	eg.Go(func() error {
35
-			dgst, err := contenthash.Checksum(ctx, ref.ImmutableRef, path.Join("/", sel))
35
+			dgst, err := contenthash.Checksum(ctx, ref.ImmutableRef, path.Join("/", sel), true)
36 36
 			if err != nil {
37 37
 				return "", err
38 38
 			}
... ...
@@ -2,6 +2,7 @@ package llbsolver
2 2
 
3 3
 import (
4 4
 	"context"
5
+	"fmt"
5 6
 	"strings"
6 7
 	"time"
7 8
 
... ...
@@ -10,6 +11,7 @@ import (
10 10
 	"github.com/moby/buildkit/client"
11 11
 	controlgateway "github.com/moby/buildkit/control/gateway"
12 12
 	"github.com/moby/buildkit/exporter"
13
+	"github.com/moby/buildkit/exporter/containerimage/exptypes"
13 14
 	"github.com/moby/buildkit/frontend"
14 15
 	"github.com/moby/buildkit/frontend/gateway"
15 16
 	"github.com/moby/buildkit/identity"
... ...
@@ -35,22 +37,24 @@ type ExporterRequest struct {
35 35
 type ResolveWorkerFunc func() (worker.Worker, error)
36 36
 
37 37
 type Solver struct {
38
-	workerController     *worker.Controller
39
-	solver               *solver.Solver
40
-	resolveWorker        ResolveWorkerFunc
41
-	frontends            map[string]frontend.Frontend
42
-	resolveCacheImporter remotecache.ResolveCacheImporterFunc
43
-	platforms            []specs.Platform
44
-	gatewayForwarder     *controlgateway.GatewayForwarder
38
+	workerController          *worker.Controller
39
+	solver                    *solver.Solver
40
+	resolveWorker             ResolveWorkerFunc
41
+	frontends                 map[string]frontend.Frontend
42
+	resolveCacheImporterFuncs map[string]remotecache.ResolveCacheImporterFunc
43
+	platforms                 []specs.Platform
44
+	gatewayForwarder          *controlgateway.GatewayForwarder
45
+	sm                        *session.Manager
45 46
 }
46 47
 
47
-func New(wc *worker.Controller, f map[string]frontend.Frontend, cache solver.CacheManager, resolveCI remotecache.ResolveCacheImporterFunc, gatewayForwarder *controlgateway.GatewayForwarder) (*Solver, error) {
48
+func New(wc *worker.Controller, f map[string]frontend.Frontend, cache solver.CacheManager, resolveCI map[string]remotecache.ResolveCacheImporterFunc, gatewayForwarder *controlgateway.GatewayForwarder, sm *session.Manager) (*Solver, error) {
48 49
 	s := &Solver{
49
-		workerController:     wc,
50
-		resolveWorker:        defaultResolver(wc),
51
-		frontends:            f,
52
-		resolveCacheImporter: resolveCI,
53
-		gatewayForwarder:     gatewayForwarder,
50
+		workerController:          wc,
51
+		resolveWorker:             defaultResolver(wc),
52
+		frontends:                 f,
53
+		resolveCacheImporterFuncs: resolveCI,
54
+		gatewayForwarder:          gatewayForwarder,
55
+		sm:                        sm,
54 56
 	}
55 57
 
56 58
 	// executing is currently only allowed on default worker
... ...
@@ -73,18 +77,19 @@ func (s *Solver) resolver() solver.ResolveOpFunc {
73 73
 		if err != nil {
74 74
 			return nil, err
75 75
 		}
76
-		return w.ResolveOp(v, s.Bridge(b))
76
+		return w.ResolveOp(v, s.Bridge(b), s.sm)
77 77
 	}
78 78
 }
79 79
 
80 80
 func (s *Solver) Bridge(b solver.Builder) frontend.FrontendLLBBridge {
81 81
 	return &llbBridge{
82
-		builder:              b,
83
-		frontends:            s.frontends,
84
-		resolveWorker:        s.resolveWorker,
85
-		resolveCacheImporter: s.resolveCacheImporter,
86
-		cms:                  map[string]solver.CacheManager{},
87
-		platforms:            s.platforms,
82
+		builder:                   b,
83
+		frontends:                 s.frontends,
84
+		resolveWorker:             s.resolveWorker,
85
+		resolveCacheImporterFuncs: s.resolveCacheImporterFuncs,
86
+		cms:                       map[string]solver.CacheManager{},
87
+		platforms:                 s.platforms,
88
+		sm:                        s.sm,
88 89
 	}
89 90
 }
90 91
 
... ...
@@ -138,7 +143,7 @@ func (s *Solver) Solve(ctx context.Context, id string, req frontend.SolveRequest
138 138
 	}()
139 139
 
140 140
 	var exporterResponse map[string]string
141
-	if exp := exp.Exporter; exp != nil {
141
+	if e := exp.Exporter; e != nil {
142 142
 		inp := exporter.Source{
143 143
 			Metadata: res.Metadata,
144 144
 		}
... ...
@@ -151,6 +156,14 @@ func (s *Solver) Solve(ctx context.Context, id string, req frontend.SolveRequest
151 151
 				return nil, errors.Errorf("invalid reference: %T", res.Sys())
152 152
 			}
153 153
 			inp.Ref = workerRef.ImmutableRef
154
+
155
+			dt, err := inlineCache(ctx, exp.CacheExporter, res)
156
+			if err != nil {
157
+				return nil, err
158
+			}
159
+			if dt != nil {
160
+				inp.Metadata[exptypes.ExporterInlineCache] = dt
161
+			}
154 162
 		}
155 163
 		if res.Refs != nil {
156 164
 			m := make(map[string]cache.ImmutableRef, len(res.Refs))
... ...
@@ -163,19 +176,28 @@ func (s *Solver) Solve(ctx context.Context, id string, req frontend.SolveRequest
163 163
 						return nil, errors.Errorf("invalid reference: %T", res.Sys())
164 164
 					}
165 165
 					m[k] = workerRef.ImmutableRef
166
+
167
+					dt, err := inlineCache(ctx, exp.CacheExporter, res)
168
+					if err != nil {
169
+						return nil, err
170
+					}
171
+					if dt != nil {
172
+						inp.Metadata[fmt.Sprintf("%s/%s", exptypes.ExporterInlineCache, k)] = dt
173
+					}
166 174
 				}
167 175
 			}
168 176
 			inp.Refs = m
169 177
 		}
170 178
 
171
-		if err := inVertexContext(j.Context(ctx), exp.Name(), "", func(ctx context.Context) error {
172
-			exporterResponse, err = exp.Export(ctx, inp)
179
+		if err := inVertexContext(j.Context(ctx), e.Name(), "", func(ctx context.Context) error {
180
+			exporterResponse, err = e.Export(ctx, inp)
173 181
 			return err
174 182
 		}); err != nil {
175 183
 			return nil, err
176 184
 		}
177 185
 	}
178 186
 
187
+	var cacheExporterResponse map[string]string
179 188
 	if e := exp.CacheExporter; e != nil {
180 189
 		if err := inVertexContext(j.Context(ctx), "exporting cache", "", func(ctx context.Context) error {
181 190
 			prepareDone := oneOffProgress(ctx, "preparing build cache for export")
... ...
@@ -190,7 +212,8 @@ func (s *Solver) Solve(ctx context.Context, id string, req frontend.SolveRequest
190 190
 				return prepareDone(err)
191 191
 			}
192 192
 			prepareDone(nil)
193
-			return e.Finalize(ctx)
193
+			cacheExporterResponse, err = e.Finalize(ctx)
194
+			return err
194 195
 		}); err != nil {
195 196
 			return nil, err
196 197
 		}
... ...
@@ -205,12 +228,48 @@ func (s *Solver) Solve(ctx context.Context, id string, req frontend.SolveRequest
205 205
 			exporterResponse[k] = string(v)
206 206
 		}
207 207
 	}
208
+	for k, v := range cacheExporterResponse {
209
+		if strings.HasPrefix(k, "cache.") {
210
+			exporterResponse[k] = v
211
+		}
212
+	}
208 213
 
209 214
 	return &client.SolveResponse{
210 215
 		ExporterResponse: exporterResponse,
211 216
 	}, nil
212 217
 }
213 218
 
219
+func inlineCache(ctx context.Context, e remotecache.Exporter, res solver.CachedResult) ([]byte, error) {
220
+	if efl, ok := e.(interface {
221
+		ExportForLayers([]digest.Digest) ([]byte, error)
222
+	}); ok {
223
+		workerRef, ok := res.Sys().(*worker.WorkerRef)
224
+		if !ok {
225
+			return nil, errors.Errorf("invalid reference: %T", res.Sys())
226
+		}
227
+
228
+		remote, err := workerRef.Worker.GetRemote(ctx, workerRef.ImmutableRef, true)
229
+		if err != nil || remote == nil {
230
+			return nil, nil
231
+		}
232
+
233
+		digests := make([]digest.Digest, 0, len(remote.Descriptors))
234
+		for _, desc := range remote.Descriptors {
235
+			digests = append(digests, desc.Digest)
236
+		}
237
+
238
+		if _, err := res.CacheKeys()[0].Exporter.ExportTo(ctx, e, solver.CacheExportOpt{
239
+			Convert: workerRefConverter,
240
+			Mode:    solver.CacheExportModeMin,
241
+		}); err != nil {
242
+			return nil, err
243
+		}
244
+
245
+		return efl.ExportForLayers(digests)
246
+	}
247
+	return nil, nil
248
+}
249
+
214 250
 func (s *Solver) Status(ctx context.Context, id string, statusChan chan *client.SolveStatus) error {
215 251
 	j, err := s.solver.Get(id)
216 252
 	if err != nil {
... ...
@@ -80,10 +80,20 @@ func RuntimePlatforms(p []specs.Platform) LoadOpt {
80 80
 				defaultPlatform = &pb.Platform{
81 81
 					OS:           p.OS,
82 82
 					Architecture: p.Architecture,
83
+					Variant:      p.Variant,
83 84
 				}
84 85
 			}
85 86
 			op.Platform = defaultPlatform
86 87
 		}
88
+		platform := specs.Platform{OS: op.Platform.OS, Architecture: op.Platform.Architecture, Variant: op.Platform.Variant}
89
+		normalizedPlatform := platforms.Normalize(platform)
90
+
91
+		op.Platform = &pb.Platform{
92
+			OS:           normalizedPlatform.OS,
93
+			Architecture: normalizedPlatform.Architecture,
94
+			Variant:      normalizedPlatform.Variant,
95
+		}
96
+
87 97
 		if _, ok := op.Op.(*pb.Op_Exec); ok {
88 98
 			var found bool
89 99
 			for _, pp := range pp {
... ...
@@ -186,7 +196,11 @@ func loadLLB(def *pb.Definition, fn func(digest.Digest, *pb.Op, func(digest.Dige
186 186
 		if v, ok := cache[dgst]; ok {
187 187
 			return v, nil
188 188
 		}
189
-		v, err := fn(dgst, allOps[dgst], rec)
189
+		op, ok := allOps[dgst]
190
+		if !ok {
191
+			return nil, errors.Errorf("invalid missing input digest %s", dgst)
192
+		}
193
+		v, err := fn(dgst, op, rec)
190 194
 		if err != nil {
191 195
 			return nil, err
192 196
 		}
... ...
@@ -284,9 +284,9 @@ type inMemoryResultStore struct {
284 284
 	m *sync.Map
285 285
 }
286 286
 
287
-func (s *inMemoryResultStore) Save(r Result) (CacheResult, error) {
287
+func (s *inMemoryResultStore) Save(r Result, createdAt time.Time) (CacheResult, error) {
288 288
 	s.m.Store(r.ID(), r)
289
-	return CacheResult{ID: r.ID(), CreatedAt: time.Now()}, nil
289
+	return CacheResult{ID: r.ID(), CreatedAt: createdAt}, nil
290 290
 }
291 291
 
292 292
 func (s *inMemoryResultStore) Load(ctx context.Context, res CacheResult) (Result, error) {
... ...
@@ -1,38 +1,12 @@
1 1
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
2 2
 // source: ops.proto
3 3
 
4
-/*
5
-	Package pb is a generated protocol buffer package.
4
+package pb
6 5
 
6
+/*
7 7
 	Package pb provides the protobuf definition of LLB: low-level builder instruction.
8 8
 	LLB is DAG-structured; Op represents a vertex, and Definition represents a graph.
9
-
10
-	It is generated from these files:
11
-		ops.proto
12
-
13
-	It has these top-level messages:
14
-		Op
15
-		Platform
16
-		Input
17
-		ExecOp
18
-		Meta
19
-		Mount
20
-		CacheOpt
21
-		SecretOpt
22
-		SSHOpt
23
-		CopyOp
24
-		CopySource
25
-		SourceOp
26
-		BuildOp
27
-		BuildInput
28
-		OpMetadata
29
-		ExportCache
30
-		ProxyEnv
31
-		WorkerConstraints
32
-		Definition
33
-		HostIP
34 9
 */
35
-package pb
36 10
 
37 11
 import proto "github.com/gogo/protobuf/proto"
38 12
 import fmt "fmt"
... ...
@@ -42,7 +16,7 @@ import _ "github.com/gogo/protobuf/gogoproto"
42 42
 import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest"
43 43
 import github_com_moby_buildkit_util_apicaps "github.com/moby/buildkit/util/apicaps"
44 44
 
45
-import sortkeys "github.com/gogo/protobuf/sortkeys"
45
+import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
46 46
 
47 47
 import io "io"
48 48
 
... ...
@@ -79,7 +53,9 @@ var NetMode_value = map[string]int32{
79 79
 func (x NetMode) String() string {
80 80
 	return proto.EnumName(NetMode_name, int32(x))
81 81
 }
82
-func (NetMode) EnumDescriptor() ([]byte, []int) { return fileDescriptorOps, []int{0} }
82
+func (NetMode) EnumDescriptor() ([]byte, []int) {
83
+	return fileDescriptor_ops_821a7942fdf920e6, []int{0}
84
+}
83 85
 
84 86
 // MountType defines a type of a mount from a supported set
85 87
 type MountType int32
... ...
@@ -110,7 +86,9 @@ var MountType_value = map[string]int32{
110 110
 func (x MountType) String() string {
111 111
 	return proto.EnumName(MountType_name, int32(x))
112 112
 }
113
-func (MountType) EnumDescriptor() ([]byte, []int) { return fileDescriptorOps, []int{1} }
113
+func (MountType) EnumDescriptor() ([]byte, []int) {
114
+	return fileDescriptor_ops_821a7942fdf920e6, []int{1}
115
+}
114 116
 
115 117
 // CacheSharingOpt defines different sharing modes for cache mount
116 118
 type CacheSharingOpt int32
... ...
@@ -138,26 +116,52 @@ var CacheSharingOpt_value = map[string]int32{
138 138
 func (x CacheSharingOpt) String() string {
139 139
 	return proto.EnumName(CacheSharingOpt_name, int32(x))
140 140
 }
141
-func (CacheSharingOpt) EnumDescriptor() ([]byte, []int) { return fileDescriptorOps, []int{2} }
141
+func (CacheSharingOpt) EnumDescriptor() ([]byte, []int) {
142
+	return fileDescriptor_ops_821a7942fdf920e6, []int{2}
143
+}
142 144
 
143 145
 // Op represents a vertex of the LLB DAG.
144 146
 type Op struct {
145 147
 	// inputs is a set of input edges.
146
-	Inputs []*Input `protobuf:"bytes,1,rep,name=inputs" json:"inputs,omitempty"`
148
+	Inputs []*Input `protobuf:"bytes,1,rep,name=inputs,proto3" json:"inputs,omitempty"`
147 149
 	// Types that are valid to be assigned to Op:
148 150
 	//	*Op_Exec
149 151
 	//	*Op_Source
150 152
 	//	*Op_Copy
151 153
 	//	*Op_Build
152 154
 	Op          isOp_Op            `protobuf_oneof:"op"`
153
-	Platform    *Platform          `protobuf:"bytes,10,opt,name=platform" json:"platform,omitempty"`
154
-	Constraints *WorkerConstraints `protobuf:"bytes,11,opt,name=constraints" json:"constraints,omitempty"`
155
+	Platform    *Platform          `protobuf:"bytes,10,opt,name=platform,proto3" json:"platform,omitempty"`
156
+	Constraints *WorkerConstraints `protobuf:"bytes,11,opt,name=constraints,proto3" json:"constraints,omitempty"`
155 157
 }
156 158
 
157
-func (m *Op) Reset()                    { *m = Op{} }
158
-func (m *Op) String() string            { return proto.CompactTextString(m) }
159
-func (*Op) ProtoMessage()               {}
160
-func (*Op) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{0} }
159
+func (m *Op) Reset()         { *m = Op{} }
160
+func (m *Op) String() string { return proto.CompactTextString(m) }
161
+func (*Op) ProtoMessage()    {}
162
+func (*Op) Descriptor() ([]byte, []int) {
163
+	return fileDescriptor_ops_821a7942fdf920e6, []int{0}
164
+}
165
+func (m *Op) XXX_Unmarshal(b []byte) error {
166
+	return m.Unmarshal(b)
167
+}
168
+func (m *Op) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
169
+	b = b[:cap(b)]
170
+	n, err := m.MarshalTo(b)
171
+	if err != nil {
172
+		return nil, err
173
+	}
174
+	return b[:n], nil
175
+}
176
+func (dst *Op) XXX_Merge(src proto.Message) {
177
+	xxx_messageInfo_Op.Merge(dst, src)
178
+}
179
+func (m *Op) XXX_Size() int {
180
+	return m.Size()
181
+}
182
+func (m *Op) XXX_DiscardUnknown() {
183
+	xxx_messageInfo_Op.DiscardUnknown(m)
184
+}
185
+
186
+var xxx_messageInfo_Op proto.InternalMessageInfo
161 187
 
162 188
 type isOp_Op interface {
163 189
 	isOp_Op()
... ...
@@ -166,16 +170,16 @@ type isOp_Op interface {
166 166
 }
167 167
 
168 168
 type Op_Exec struct {
169
-	Exec *ExecOp `protobuf:"bytes,2,opt,name=exec,oneof"`
169
+	Exec *ExecOp `protobuf:"bytes,2,opt,name=exec,proto3,oneof"`
170 170
 }
171 171
 type Op_Source struct {
172
-	Source *SourceOp `protobuf:"bytes,3,opt,name=source,oneof"`
172
+	Source *SourceOp `protobuf:"bytes,3,opt,name=source,proto3,oneof"`
173 173
 }
174 174
 type Op_Copy struct {
175
-	Copy *CopyOp `protobuf:"bytes,4,opt,name=copy,oneof"`
175
+	Copy *CopyOp `protobuf:"bytes,4,opt,name=copy,proto3,oneof"`
176 176
 }
177 177
 type Op_Build struct {
178
-	Build *BuildOp `protobuf:"bytes,5,opt,name=build,oneof"`
178
+	Build *BuildOp `protobuf:"bytes,5,opt,name=build,proto3,oneof"`
179 179
 }
180 180
 
181 181
 func (*Op_Exec) isOp_Op()   {}
... ...
@@ -326,22 +330,22 @@ func _Op_OneofSizer(msg proto.Message) (n int) {
326 326
 	switch x := m.Op.(type) {
327 327
 	case *Op_Exec:
328 328
 		s := proto.Size(x.Exec)
329
-		n += proto.SizeVarint(2<<3 | proto.WireBytes)
329
+		n += 1 // tag and wire
330 330
 		n += proto.SizeVarint(uint64(s))
331 331
 		n += s
332 332
 	case *Op_Source:
333 333
 		s := proto.Size(x.Source)
334
-		n += proto.SizeVarint(3<<3 | proto.WireBytes)
334
+		n += 1 // tag and wire
335 335
 		n += proto.SizeVarint(uint64(s))
336 336
 		n += s
337 337
 	case *Op_Copy:
338 338
 		s := proto.Size(x.Copy)
339
-		n += proto.SizeVarint(4<<3 | proto.WireBytes)
339
+		n += 1 // tag and wire
340 340
 		n += proto.SizeVarint(uint64(s))
341 341
 		n += s
342 342
 	case *Op_Build:
343 343
 		s := proto.Size(x.Build)
344
-		n += proto.SizeVarint(5<<3 | proto.WireBytes)
344
+		n += 1 // tag and wire
345 345
 		n += proto.SizeVarint(uint64(s))
346 346
 		n += s
347 347
 	case nil:
... ...
@@ -357,13 +361,37 @@ type Platform struct {
357 357
 	OS           string   `protobuf:"bytes,2,opt,name=OS,proto3" json:"OS,omitempty"`
358 358
 	Variant      string   `protobuf:"bytes,3,opt,name=Variant,proto3" json:"Variant,omitempty"`
359 359
 	OSVersion    string   `protobuf:"bytes,4,opt,name=OSVersion,proto3" json:"OSVersion,omitempty"`
360
-	OSFeatures   []string `protobuf:"bytes,5,rep,name=OSFeatures" json:"OSFeatures,omitempty"`
360
+	OSFeatures   []string `protobuf:"bytes,5,rep,name=OSFeatures,proto3" json:"OSFeatures,omitempty"`
361
+}
362
+
363
+func (m *Platform) Reset()         { *m = Platform{} }
364
+func (m *Platform) String() string { return proto.CompactTextString(m) }
365
+func (*Platform) ProtoMessage()    {}
366
+func (*Platform) Descriptor() ([]byte, []int) {
367
+	return fileDescriptor_ops_821a7942fdf920e6, []int{1}
368
+}
369
+func (m *Platform) XXX_Unmarshal(b []byte) error {
370
+	return m.Unmarshal(b)
371
+}
372
+func (m *Platform) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
373
+	b = b[:cap(b)]
374
+	n, err := m.MarshalTo(b)
375
+	if err != nil {
376
+		return nil, err
377
+	}
378
+	return b[:n], nil
379
+}
380
+func (dst *Platform) XXX_Merge(src proto.Message) {
381
+	xxx_messageInfo_Platform.Merge(dst, src)
382
+}
383
+func (m *Platform) XXX_Size() int {
384
+	return m.Size()
385
+}
386
+func (m *Platform) XXX_DiscardUnknown() {
387
+	xxx_messageInfo_Platform.DiscardUnknown(m)
361 388
 }
362 389
 
363
-func (m *Platform) Reset()                    { *m = Platform{} }
364
-func (m *Platform) String() string            { return proto.CompactTextString(m) }
365
-func (*Platform) ProtoMessage()               {}
366
-func (*Platform) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{1} }
390
+var xxx_messageInfo_Platform proto.InternalMessageInfo
367 391
 
368 392
 func (m *Platform) GetArchitecture() string {
369 393
 	if m != nil {
... ...
@@ -408,22 +436,70 @@ type Input struct {
408 408
 	Index OutputIndex `protobuf:"varint,2,opt,name=index,proto3,customtype=OutputIndex" json:"index"`
409 409
 }
410 410
 
411
-func (m *Input) Reset()                    { *m = Input{} }
412
-func (m *Input) String() string            { return proto.CompactTextString(m) }
413
-func (*Input) ProtoMessage()               {}
414
-func (*Input) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{2} }
411
+func (m *Input) Reset()         { *m = Input{} }
412
+func (m *Input) String() string { return proto.CompactTextString(m) }
413
+func (*Input) ProtoMessage()    {}
414
+func (*Input) Descriptor() ([]byte, []int) {
415
+	return fileDescriptor_ops_821a7942fdf920e6, []int{2}
416
+}
417
+func (m *Input) XXX_Unmarshal(b []byte) error {
418
+	return m.Unmarshal(b)
419
+}
420
+func (m *Input) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
421
+	b = b[:cap(b)]
422
+	n, err := m.MarshalTo(b)
423
+	if err != nil {
424
+		return nil, err
425
+	}
426
+	return b[:n], nil
427
+}
428
+func (dst *Input) XXX_Merge(src proto.Message) {
429
+	xxx_messageInfo_Input.Merge(dst, src)
430
+}
431
+func (m *Input) XXX_Size() int {
432
+	return m.Size()
433
+}
434
+func (m *Input) XXX_DiscardUnknown() {
435
+	xxx_messageInfo_Input.DiscardUnknown(m)
436
+}
437
+
438
+var xxx_messageInfo_Input proto.InternalMessageInfo
415 439
 
416 440
 // ExecOp executes a command in a container.
417 441
 type ExecOp struct {
418
-	Meta    *Meta    `protobuf:"bytes,1,opt,name=meta" json:"meta,omitempty"`
419
-	Mounts  []*Mount `protobuf:"bytes,2,rep,name=mounts" json:"mounts,omitempty"`
442
+	Meta    *Meta    `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
443
+	Mounts  []*Mount `protobuf:"bytes,2,rep,name=mounts,proto3" json:"mounts,omitempty"`
420 444
 	Network NetMode  `protobuf:"varint,3,opt,name=network,proto3,enum=pb.NetMode" json:"network,omitempty"`
421 445
 }
422 446
 
423
-func (m *ExecOp) Reset()                    { *m = ExecOp{} }
424
-func (m *ExecOp) String() string            { return proto.CompactTextString(m) }
425
-func (*ExecOp) ProtoMessage()               {}
426
-func (*ExecOp) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{3} }
447
+func (m *ExecOp) Reset()         { *m = ExecOp{} }
448
+func (m *ExecOp) String() string { return proto.CompactTextString(m) }
449
+func (*ExecOp) ProtoMessage()    {}
450
+func (*ExecOp) Descriptor() ([]byte, []int) {
451
+	return fileDescriptor_ops_821a7942fdf920e6, []int{3}
452
+}
453
+func (m *ExecOp) XXX_Unmarshal(b []byte) error {
454
+	return m.Unmarshal(b)
455
+}
456
+func (m *ExecOp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
457
+	b = b[:cap(b)]
458
+	n, err := m.MarshalTo(b)
459
+	if err != nil {
460
+		return nil, err
461
+	}
462
+	return b[:n], nil
463
+}
464
+func (dst *ExecOp) XXX_Merge(src proto.Message) {
465
+	xxx_messageInfo_ExecOp.Merge(dst, src)
466
+}
467
+func (m *ExecOp) XXX_Size() int {
468
+	return m.Size()
469
+}
470
+func (m *ExecOp) XXX_DiscardUnknown() {
471
+	xxx_messageInfo_ExecOp.DiscardUnknown(m)
472
+}
473
+
474
+var xxx_messageInfo_ExecOp proto.InternalMessageInfo
427 475
 
428 476
 func (m *ExecOp) GetMeta() *Meta {
429 477
 	if m != nil {
... ...
@@ -450,18 +526,42 @@ func (m *ExecOp) GetNetwork() NetMode {
450 450
 // Meta is unrelated to LLB metadata.
451 451
 // FIXME: rename (ExecContext? ExecArgs?)
452 452
 type Meta struct {
453
-	Args       []string  `protobuf:"bytes,1,rep,name=args" json:"args,omitempty"`
454
-	Env        []string  `protobuf:"bytes,2,rep,name=env" json:"env,omitempty"`
453
+	Args       []string  `protobuf:"bytes,1,rep,name=args,proto3" json:"args,omitempty"`
454
+	Env        []string  `protobuf:"bytes,2,rep,name=env,proto3" json:"env,omitempty"`
455 455
 	Cwd        string    `protobuf:"bytes,3,opt,name=cwd,proto3" json:"cwd,omitempty"`
456 456
 	User       string    `protobuf:"bytes,4,opt,name=user,proto3" json:"user,omitempty"`
457
-	ProxyEnv   *ProxyEnv `protobuf:"bytes,5,opt,name=proxy_env,json=proxyEnv" json:"proxy_env,omitempty"`
458
-	ExtraHosts []*HostIP `protobuf:"bytes,6,rep,name=extraHosts" json:"extraHosts,omitempty"`
457
+	ProxyEnv   *ProxyEnv `protobuf:"bytes,5,opt,name=proxy_env,json=proxyEnv,proto3" json:"proxy_env,omitempty"`
458
+	ExtraHosts []*HostIP `protobuf:"bytes,6,rep,name=extraHosts,proto3" json:"extraHosts,omitempty"`
459
+}
460
+
461
+func (m *Meta) Reset()         { *m = Meta{} }
462
+func (m *Meta) String() string { return proto.CompactTextString(m) }
463
+func (*Meta) ProtoMessage()    {}
464
+func (*Meta) Descriptor() ([]byte, []int) {
465
+	return fileDescriptor_ops_821a7942fdf920e6, []int{4}
466
+}
467
+func (m *Meta) XXX_Unmarshal(b []byte) error {
468
+	return m.Unmarshal(b)
469
+}
470
+func (m *Meta) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
471
+	b = b[:cap(b)]
472
+	n, err := m.MarshalTo(b)
473
+	if err != nil {
474
+		return nil, err
475
+	}
476
+	return b[:n], nil
477
+}
478
+func (dst *Meta) XXX_Merge(src proto.Message) {
479
+	xxx_messageInfo_Meta.Merge(dst, src)
480
+}
481
+func (m *Meta) XXX_Size() int {
482
+	return m.Size()
483
+}
484
+func (m *Meta) XXX_DiscardUnknown() {
485
+	xxx_messageInfo_Meta.DiscardUnknown(m)
459 486
 }
460 487
 
461
-func (m *Meta) Reset()                    { *m = Meta{} }
462
-func (m *Meta) String() string            { return proto.CompactTextString(m) }
463
-func (*Meta) ProtoMessage()               {}
464
-func (*Meta) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{4} }
488
+var xxx_messageInfo_Meta proto.InternalMessageInfo
465 489
 
466 490
 func (m *Meta) GetArgs() []string {
467 491
 	if m != nil {
... ...
@@ -513,15 +613,39 @@ type Mount struct {
513 513
 	Output    OutputIndex `protobuf:"varint,4,opt,name=output,proto3,customtype=OutputIndex" json:"output"`
514 514
 	Readonly  bool        `protobuf:"varint,5,opt,name=readonly,proto3" json:"readonly,omitempty"`
515 515
 	MountType MountType   `protobuf:"varint,6,opt,name=mountType,proto3,enum=pb.MountType" json:"mountType,omitempty"`
516
-	CacheOpt  *CacheOpt   `protobuf:"bytes,20,opt,name=cacheOpt" json:"cacheOpt,omitempty"`
517
-	SecretOpt *SecretOpt  `protobuf:"bytes,21,opt,name=secretOpt" json:"secretOpt,omitempty"`
518
-	SSHOpt    *SSHOpt     `protobuf:"bytes,22,opt,name=SSHOpt" json:"SSHOpt,omitempty"`
516
+	CacheOpt  *CacheOpt   `protobuf:"bytes,20,opt,name=cacheOpt,proto3" json:"cacheOpt,omitempty"`
517
+	SecretOpt *SecretOpt  `protobuf:"bytes,21,opt,name=secretOpt,proto3" json:"secretOpt,omitempty"`
518
+	SSHOpt    *SSHOpt     `protobuf:"bytes,22,opt,name=SSHOpt,proto3" json:"SSHOpt,omitempty"`
519 519
 }
520 520
 
521
-func (m *Mount) Reset()                    { *m = Mount{} }
522
-func (m *Mount) String() string            { return proto.CompactTextString(m) }
523
-func (*Mount) ProtoMessage()               {}
524
-func (*Mount) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{5} }
521
+func (m *Mount) Reset()         { *m = Mount{} }
522
+func (m *Mount) String() string { return proto.CompactTextString(m) }
523
+func (*Mount) ProtoMessage()    {}
524
+func (*Mount) Descriptor() ([]byte, []int) {
525
+	return fileDescriptor_ops_821a7942fdf920e6, []int{5}
526
+}
527
+func (m *Mount) XXX_Unmarshal(b []byte) error {
528
+	return m.Unmarshal(b)
529
+}
530
+func (m *Mount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
531
+	b = b[:cap(b)]
532
+	n, err := m.MarshalTo(b)
533
+	if err != nil {
534
+		return nil, err
535
+	}
536
+	return b[:n], nil
537
+}
538
+func (dst *Mount) XXX_Merge(src proto.Message) {
539
+	xxx_messageInfo_Mount.Merge(dst, src)
540
+}
541
+func (m *Mount) XXX_Size() int {
542
+	return m.Size()
543
+}
544
+func (m *Mount) XXX_DiscardUnknown() {
545
+	xxx_messageInfo_Mount.DiscardUnknown(m)
546
+}
547
+
548
+var xxx_messageInfo_Mount proto.InternalMessageInfo
525 549
 
526 550
 func (m *Mount) GetSelector() string {
527 551
 	if m != nil {
... ...
@@ -580,10 +704,34 @@ type CacheOpt struct {
580 580
 	Sharing CacheSharingOpt `protobuf:"varint,2,opt,name=sharing,proto3,enum=pb.CacheSharingOpt" json:"sharing,omitempty"`
581 581
 }
582 582
 
583
-func (m *CacheOpt) Reset()                    { *m = CacheOpt{} }
584
-func (m *CacheOpt) String() string            { return proto.CompactTextString(m) }
585
-func (*CacheOpt) ProtoMessage()               {}
586
-func (*CacheOpt) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{6} }
583
+func (m *CacheOpt) Reset()         { *m = CacheOpt{} }
584
+func (m *CacheOpt) String() string { return proto.CompactTextString(m) }
585
+func (*CacheOpt) ProtoMessage()    {}
586
+func (*CacheOpt) Descriptor() ([]byte, []int) {
587
+	return fileDescriptor_ops_821a7942fdf920e6, []int{6}
588
+}
589
+func (m *CacheOpt) XXX_Unmarshal(b []byte) error {
590
+	return m.Unmarshal(b)
591
+}
592
+func (m *CacheOpt) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
593
+	b = b[:cap(b)]
594
+	n, err := m.MarshalTo(b)
595
+	if err != nil {
596
+		return nil, err
597
+	}
598
+	return b[:n], nil
599
+}
600
+func (dst *CacheOpt) XXX_Merge(src proto.Message) {
601
+	xxx_messageInfo_CacheOpt.Merge(dst, src)
602
+}
603
+func (m *CacheOpt) XXX_Size() int {
604
+	return m.Size()
605
+}
606
+func (m *CacheOpt) XXX_DiscardUnknown() {
607
+	xxx_messageInfo_CacheOpt.DiscardUnknown(m)
608
+}
609
+
610
+var xxx_messageInfo_CacheOpt proto.InternalMessageInfo
587 611
 
588 612
 func (m *CacheOpt) GetID() string {
589 613
 	if m != nil {
... ...
@@ -614,10 +762,34 @@ type SecretOpt struct {
614 614
 	Optional bool `protobuf:"varint,5,opt,name=optional,proto3" json:"optional,omitempty"`
615 615
 }
616 616
 
617
-func (m *SecretOpt) Reset()                    { *m = SecretOpt{} }
618
-func (m *SecretOpt) String() string            { return proto.CompactTextString(m) }
619
-func (*SecretOpt) ProtoMessage()               {}
620
-func (*SecretOpt) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{7} }
617
+func (m *SecretOpt) Reset()         { *m = SecretOpt{} }
618
+func (m *SecretOpt) String() string { return proto.CompactTextString(m) }
619
+func (*SecretOpt) ProtoMessage()    {}
620
+func (*SecretOpt) Descriptor() ([]byte, []int) {
621
+	return fileDescriptor_ops_821a7942fdf920e6, []int{7}
622
+}
623
+func (m *SecretOpt) XXX_Unmarshal(b []byte) error {
624
+	return m.Unmarshal(b)
625
+}
626
+func (m *SecretOpt) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
627
+	b = b[:cap(b)]
628
+	n, err := m.MarshalTo(b)
629
+	if err != nil {
630
+		return nil, err
631
+	}
632
+	return b[:n], nil
633
+}
634
+func (dst *SecretOpt) XXX_Merge(src proto.Message) {
635
+	xxx_messageInfo_SecretOpt.Merge(dst, src)
636
+}
637
+func (m *SecretOpt) XXX_Size() int {
638
+	return m.Size()
639
+}
640
+func (m *SecretOpt) XXX_DiscardUnknown() {
641
+	xxx_messageInfo_SecretOpt.DiscardUnknown(m)
642
+}
643
+
644
+var xxx_messageInfo_SecretOpt proto.InternalMessageInfo
621 645
 
622 646
 func (m *SecretOpt) GetID() string {
623 647
 	if m != nil {
... ...
@@ -669,10 +841,34 @@ type SSHOpt struct {
669 669
 	Optional bool `protobuf:"varint,5,opt,name=optional,proto3" json:"optional,omitempty"`
670 670
 }
671 671
 
672
-func (m *SSHOpt) Reset()                    { *m = SSHOpt{} }
673
-func (m *SSHOpt) String() string            { return proto.CompactTextString(m) }
674
-func (*SSHOpt) ProtoMessage()               {}
675
-func (*SSHOpt) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{8} }
672
+func (m *SSHOpt) Reset()         { *m = SSHOpt{} }
673
+func (m *SSHOpt) String() string { return proto.CompactTextString(m) }
674
+func (*SSHOpt) ProtoMessage()    {}
675
+func (*SSHOpt) Descriptor() ([]byte, []int) {
676
+	return fileDescriptor_ops_821a7942fdf920e6, []int{8}
677
+}
678
+func (m *SSHOpt) XXX_Unmarshal(b []byte) error {
679
+	return m.Unmarshal(b)
680
+}
681
+func (m *SSHOpt) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
682
+	b = b[:cap(b)]
683
+	n, err := m.MarshalTo(b)
684
+	if err != nil {
685
+		return nil, err
686
+	}
687
+	return b[:n], nil
688
+}
689
+func (dst *SSHOpt) XXX_Merge(src proto.Message) {
690
+	xxx_messageInfo_SSHOpt.Merge(dst, src)
691
+}
692
+func (m *SSHOpt) XXX_Size() int {
693
+	return m.Size()
694
+}
695
+func (m *SSHOpt) XXX_DiscardUnknown() {
696
+	xxx_messageInfo_SSHOpt.DiscardUnknown(m)
697
+}
698
+
699
+var xxx_messageInfo_SSHOpt proto.InternalMessageInfo
676 700
 
677 701
 func (m *SSHOpt) GetID() string {
678 702
 	if m != nil {
... ...
@@ -711,14 +907,38 @@ func (m *SSHOpt) GetOptional() bool {
711 711
 
712 712
 // CopyOp copies files across Ops.
713 713
 type CopyOp struct {
714
-	Src  []*CopySource `protobuf:"bytes,1,rep,name=src" json:"src,omitempty"`
714
+	Src  []*CopySource `protobuf:"bytes,1,rep,name=src,proto3" json:"src,omitempty"`
715 715
 	Dest string        `protobuf:"bytes,2,opt,name=dest,proto3" json:"dest,omitempty"`
716 716
 }
717 717
 
718
-func (m *CopyOp) Reset()                    { *m = CopyOp{} }
719
-func (m *CopyOp) String() string            { return proto.CompactTextString(m) }
720
-func (*CopyOp) ProtoMessage()               {}
721
-func (*CopyOp) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{9} }
718
+func (m *CopyOp) Reset()         { *m = CopyOp{} }
719
+func (m *CopyOp) String() string { return proto.CompactTextString(m) }
720
+func (*CopyOp) ProtoMessage()    {}
721
+func (*CopyOp) Descriptor() ([]byte, []int) {
722
+	return fileDescriptor_ops_821a7942fdf920e6, []int{9}
723
+}
724
+func (m *CopyOp) XXX_Unmarshal(b []byte) error {
725
+	return m.Unmarshal(b)
726
+}
727
+func (m *CopyOp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
728
+	b = b[:cap(b)]
729
+	n, err := m.MarshalTo(b)
730
+	if err != nil {
731
+		return nil, err
732
+	}
733
+	return b[:n], nil
734
+}
735
+func (dst *CopyOp) XXX_Merge(src proto.Message) {
736
+	xxx_messageInfo_CopyOp.Merge(dst, src)
737
+}
738
+func (m *CopyOp) XXX_Size() int {
739
+	return m.Size()
740
+}
741
+func (m *CopyOp) XXX_DiscardUnknown() {
742
+	xxx_messageInfo_CopyOp.DiscardUnknown(m)
743
+}
744
+
745
+var xxx_messageInfo_CopyOp proto.InternalMessageInfo
722 746
 
723 747
 func (m *CopyOp) GetSrc() []*CopySource {
724 748
 	if m != nil {
... ...
@@ -740,10 +960,34 @@ type CopySource struct {
740 740
 	Selector string     `protobuf:"bytes,2,opt,name=selector,proto3" json:"selector,omitempty"`
741 741
 }
742 742
 
743
-func (m *CopySource) Reset()                    { *m = CopySource{} }
744
-func (m *CopySource) String() string            { return proto.CompactTextString(m) }
745
-func (*CopySource) ProtoMessage()               {}
746
-func (*CopySource) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{10} }
743
+func (m *CopySource) Reset()         { *m = CopySource{} }
744
+func (m *CopySource) String() string { return proto.CompactTextString(m) }
745
+func (*CopySource) ProtoMessage()    {}
746
+func (*CopySource) Descriptor() ([]byte, []int) {
747
+	return fileDescriptor_ops_821a7942fdf920e6, []int{10}
748
+}
749
+func (m *CopySource) XXX_Unmarshal(b []byte) error {
750
+	return m.Unmarshal(b)
751
+}
752
+func (m *CopySource) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
753
+	b = b[:cap(b)]
754
+	n, err := m.MarshalTo(b)
755
+	if err != nil {
756
+		return nil, err
757
+	}
758
+	return b[:n], nil
759
+}
760
+func (dst *CopySource) XXX_Merge(src proto.Message) {
761
+	xxx_messageInfo_CopySource.Merge(dst, src)
762
+}
763
+func (m *CopySource) XXX_Size() int {
764
+	return m.Size()
765
+}
766
+func (m *CopySource) XXX_DiscardUnknown() {
767
+	xxx_messageInfo_CopySource.DiscardUnknown(m)
768
+}
769
+
770
+var xxx_messageInfo_CopySource proto.InternalMessageInfo
747 771
 
748 772
 func (m *CopySource) GetSelector() string {
749 773
 	if m != nil {
... ...
@@ -758,13 +1002,37 @@ type SourceOp struct {
758 758
 	// identifier e.g. local://, docker-image://, git://, https://...
759 759
 	Identifier string `protobuf:"bytes,1,opt,name=identifier,proto3" json:"identifier,omitempty"`
760 760
 	// attrs are defined in attr.go
761
-	Attrs map[string]string `protobuf:"bytes,2,rep,name=attrs" json:"attrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
761
+	Attrs map[string]string `protobuf:"bytes,2,rep,name=attrs,proto3" json:"attrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
762 762
 }
763 763
 
764
-func (m *SourceOp) Reset()                    { *m = SourceOp{} }
765
-func (m *SourceOp) String() string            { return proto.CompactTextString(m) }
766
-func (*SourceOp) ProtoMessage()               {}
767
-func (*SourceOp) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{11} }
764
+func (m *SourceOp) Reset()         { *m = SourceOp{} }
765
+func (m *SourceOp) String() string { return proto.CompactTextString(m) }
766
+func (*SourceOp) ProtoMessage()    {}
767
+func (*SourceOp) Descriptor() ([]byte, []int) {
768
+	return fileDescriptor_ops_821a7942fdf920e6, []int{11}
769
+}
770
+func (m *SourceOp) XXX_Unmarshal(b []byte) error {
771
+	return m.Unmarshal(b)
772
+}
773
+func (m *SourceOp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
774
+	b = b[:cap(b)]
775
+	n, err := m.MarshalTo(b)
776
+	if err != nil {
777
+		return nil, err
778
+	}
779
+	return b[:n], nil
780
+}
781
+func (dst *SourceOp) XXX_Merge(src proto.Message) {
782
+	xxx_messageInfo_SourceOp.Merge(dst, src)
783
+}
784
+func (m *SourceOp) XXX_Size() int {
785
+	return m.Size()
786
+}
787
+func (m *SourceOp) XXX_DiscardUnknown() {
788
+	xxx_messageInfo_SourceOp.DiscardUnknown(m)
789
+}
790
+
791
+var xxx_messageInfo_SourceOp proto.InternalMessageInfo
768 792
 
769 793
 func (m *SourceOp) GetIdentifier() string {
770 794
 	if m != nil {
... ...
@@ -784,15 +1052,39 @@ func (m *SourceOp) GetAttrs() map[string]string {
784 784
 // BuildOp is experimental and can break without backwards compatibility
785 785
 type BuildOp struct {
786 786
 	Builder InputIndex             `protobuf:"varint,1,opt,name=builder,proto3,customtype=InputIndex" json:"builder"`
787
-	Inputs  map[string]*BuildInput `protobuf:"bytes,2,rep,name=inputs" json:"inputs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
788
-	Def     *Definition            `protobuf:"bytes,3,opt,name=def" json:"def,omitempty"`
789
-	Attrs   map[string]string      `protobuf:"bytes,4,rep,name=attrs" json:"attrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
787
+	Inputs  map[string]*BuildInput `protobuf:"bytes,2,rep,name=inputs,proto3" json:"inputs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
788
+	Def     *Definition            `protobuf:"bytes,3,opt,name=def,proto3" json:"def,omitempty"`
789
+	Attrs   map[string]string      `protobuf:"bytes,4,rep,name=attrs,proto3" json:"attrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
790 790
 }
791 791
 
792
-func (m *BuildOp) Reset()                    { *m = BuildOp{} }
793
-func (m *BuildOp) String() string            { return proto.CompactTextString(m) }
794
-func (*BuildOp) ProtoMessage()               {}
795
-func (*BuildOp) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{12} }
792
+func (m *BuildOp) Reset()         { *m = BuildOp{} }
793
+func (m *BuildOp) String() string { return proto.CompactTextString(m) }
794
+func (*BuildOp) ProtoMessage()    {}
795
+func (*BuildOp) Descriptor() ([]byte, []int) {
796
+	return fileDescriptor_ops_821a7942fdf920e6, []int{12}
797
+}
798
+func (m *BuildOp) XXX_Unmarshal(b []byte) error {
799
+	return m.Unmarshal(b)
800
+}
801
+func (m *BuildOp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
802
+	b = b[:cap(b)]
803
+	n, err := m.MarshalTo(b)
804
+	if err != nil {
805
+		return nil, err
806
+	}
807
+	return b[:n], nil
808
+}
809
+func (dst *BuildOp) XXX_Merge(src proto.Message) {
810
+	xxx_messageInfo_BuildOp.Merge(dst, src)
811
+}
812
+func (m *BuildOp) XXX_Size() int {
813
+	return m.Size()
814
+}
815
+func (m *BuildOp) XXX_DiscardUnknown() {
816
+	xxx_messageInfo_BuildOp.DiscardUnknown(m)
817
+}
818
+
819
+var xxx_messageInfo_BuildOp proto.InternalMessageInfo
796 820
 
797 821
 func (m *BuildOp) GetInputs() map[string]*BuildInput {
798 822
 	if m != nil {
... ...
@@ -820,27 +1112,75 @@ type BuildInput struct {
820 820
 	Input InputIndex `protobuf:"varint,1,opt,name=input,proto3,customtype=InputIndex" json:"input"`
821 821
 }
822 822
 
823
-func (m *BuildInput) Reset()                    { *m = BuildInput{} }
824
-func (m *BuildInput) String() string            { return proto.CompactTextString(m) }
825
-func (*BuildInput) ProtoMessage()               {}
826
-func (*BuildInput) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{13} }
823
+func (m *BuildInput) Reset()         { *m = BuildInput{} }
824
+func (m *BuildInput) String() string { return proto.CompactTextString(m) }
825
+func (*BuildInput) ProtoMessage()    {}
826
+func (*BuildInput) Descriptor() ([]byte, []int) {
827
+	return fileDescriptor_ops_821a7942fdf920e6, []int{13}
828
+}
829
+func (m *BuildInput) XXX_Unmarshal(b []byte) error {
830
+	return m.Unmarshal(b)
831
+}
832
+func (m *BuildInput) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
833
+	b = b[:cap(b)]
834
+	n, err := m.MarshalTo(b)
835
+	if err != nil {
836
+		return nil, err
837
+	}
838
+	return b[:n], nil
839
+}
840
+func (dst *BuildInput) XXX_Merge(src proto.Message) {
841
+	xxx_messageInfo_BuildInput.Merge(dst, src)
842
+}
843
+func (m *BuildInput) XXX_Size() int {
844
+	return m.Size()
845
+}
846
+func (m *BuildInput) XXX_DiscardUnknown() {
847
+	xxx_messageInfo_BuildInput.DiscardUnknown(m)
848
+}
849
+
850
+var xxx_messageInfo_BuildInput proto.InternalMessageInfo
827 851
 
828 852
 // OpMetadata is a per-vertex metadata entry, which can be defined for arbitrary Op vertex and overridable on the run time.
829 853
 type OpMetadata struct {
830 854
 	// ignore_cache specifies to ignore the cache for this Op.
831 855
 	IgnoreCache bool `protobuf:"varint,1,opt,name=ignore_cache,json=ignoreCache,proto3" json:"ignore_cache,omitempty"`
832 856
 	// Description can be used for keeping any text fields that builder doesn't parse
833
-	Description map[string]string `protobuf:"bytes,2,rep,name=description" json:"description,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
857
+	Description map[string]string `protobuf:"bytes,2,rep,name=description,proto3" json:"description,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
834 858
 	// index 3 reserved for WorkerConstraint in previous versions
835 859
 	// WorkerConstraint worker_constraint = 3;
836
-	ExportCache *ExportCache                                         `protobuf:"bytes,4,opt,name=export_cache,json=exportCache" json:"export_cache,omitempty"`
837
-	Caps        map[github_com_moby_buildkit_util_apicaps.CapID]bool `protobuf:"bytes,5,rep,name=caps,castkey=github.com/moby/buildkit/util/apicaps.CapID" json:"caps" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
860
+	ExportCache *ExportCache                                         `protobuf:"bytes,4,opt,name=export_cache,json=exportCache,proto3" json:"export_cache,omitempty"`
861
+	Caps        map[github_com_moby_buildkit_util_apicaps.CapID]bool `protobuf:"bytes,5,rep,name=caps,proto3,castkey=github.com/moby/buildkit/util/apicaps.CapID" json:"caps" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
838 862
 }
839 863
 
840
-func (m *OpMetadata) Reset()                    { *m = OpMetadata{} }
841
-func (m *OpMetadata) String() string            { return proto.CompactTextString(m) }
842
-func (*OpMetadata) ProtoMessage()               {}
843
-func (*OpMetadata) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{14} }
864
+func (m *OpMetadata) Reset()         { *m = OpMetadata{} }
865
+func (m *OpMetadata) String() string { return proto.CompactTextString(m) }
866
+func (*OpMetadata) ProtoMessage()    {}
867
+func (*OpMetadata) Descriptor() ([]byte, []int) {
868
+	return fileDescriptor_ops_821a7942fdf920e6, []int{14}
869
+}
870
+func (m *OpMetadata) XXX_Unmarshal(b []byte) error {
871
+	return m.Unmarshal(b)
872
+}
873
+func (m *OpMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
874
+	b = b[:cap(b)]
875
+	n, err := m.MarshalTo(b)
876
+	if err != nil {
877
+		return nil, err
878
+	}
879
+	return b[:n], nil
880
+}
881
+func (dst *OpMetadata) XXX_Merge(src proto.Message) {
882
+	xxx_messageInfo_OpMetadata.Merge(dst, src)
883
+}
884
+func (m *OpMetadata) XXX_Size() int {
885
+	return m.Size()
886
+}
887
+func (m *OpMetadata) XXX_DiscardUnknown() {
888
+	xxx_messageInfo_OpMetadata.DiscardUnknown(m)
889
+}
890
+
891
+var xxx_messageInfo_OpMetadata proto.InternalMessageInfo
844 892
 
845 893
 func (m *OpMetadata) GetIgnoreCache() bool {
846 894
 	if m != nil {
... ...
@@ -874,10 +1214,34 @@ type ExportCache struct {
874 874
 	Value bool `protobuf:"varint,1,opt,name=Value,proto3" json:"Value,omitempty"`
875 875
 }
876 876
 
877
-func (m *ExportCache) Reset()                    { *m = ExportCache{} }
878
-func (m *ExportCache) String() string            { return proto.CompactTextString(m) }
879
-func (*ExportCache) ProtoMessage()               {}
880
-func (*ExportCache) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{15} }
877
+func (m *ExportCache) Reset()         { *m = ExportCache{} }
878
+func (m *ExportCache) String() string { return proto.CompactTextString(m) }
879
+func (*ExportCache) ProtoMessage()    {}
880
+func (*ExportCache) Descriptor() ([]byte, []int) {
881
+	return fileDescriptor_ops_821a7942fdf920e6, []int{15}
882
+}
883
+func (m *ExportCache) XXX_Unmarshal(b []byte) error {
884
+	return m.Unmarshal(b)
885
+}
886
+func (m *ExportCache) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
887
+	b = b[:cap(b)]
888
+	n, err := m.MarshalTo(b)
889
+	if err != nil {
890
+		return nil, err
891
+	}
892
+	return b[:n], nil
893
+}
894
+func (dst *ExportCache) XXX_Merge(src proto.Message) {
895
+	xxx_messageInfo_ExportCache.Merge(dst, src)
896
+}
897
+func (m *ExportCache) XXX_Size() int {
898
+	return m.Size()
899
+}
900
+func (m *ExportCache) XXX_DiscardUnknown() {
901
+	xxx_messageInfo_ExportCache.DiscardUnknown(m)
902
+}
903
+
904
+var xxx_messageInfo_ExportCache proto.InternalMessageInfo
881 905
 
882 906
 func (m *ExportCache) GetValue() bool {
883 907
 	if m != nil {
... ...
@@ -893,10 +1257,34 @@ type ProxyEnv struct {
893 893
 	NoProxy    string `protobuf:"bytes,4,opt,name=no_proxy,json=noProxy,proto3" json:"no_proxy,omitempty"`
894 894
 }
895 895
 
896
-func (m *ProxyEnv) Reset()                    { *m = ProxyEnv{} }
897
-func (m *ProxyEnv) String() string            { return proto.CompactTextString(m) }
898
-func (*ProxyEnv) ProtoMessage()               {}
899
-func (*ProxyEnv) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{16} }
896
+func (m *ProxyEnv) Reset()         { *m = ProxyEnv{} }
897
+func (m *ProxyEnv) String() string { return proto.CompactTextString(m) }
898
+func (*ProxyEnv) ProtoMessage()    {}
899
+func (*ProxyEnv) Descriptor() ([]byte, []int) {
900
+	return fileDescriptor_ops_821a7942fdf920e6, []int{16}
901
+}
902
+func (m *ProxyEnv) XXX_Unmarshal(b []byte) error {
903
+	return m.Unmarshal(b)
904
+}
905
+func (m *ProxyEnv) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
906
+	b = b[:cap(b)]
907
+	n, err := m.MarshalTo(b)
908
+	if err != nil {
909
+		return nil, err
910
+	}
911
+	return b[:n], nil
912
+}
913
+func (dst *ProxyEnv) XXX_Merge(src proto.Message) {
914
+	xxx_messageInfo_ProxyEnv.Merge(dst, src)
915
+}
916
+func (m *ProxyEnv) XXX_Size() int {
917
+	return m.Size()
918
+}
919
+func (m *ProxyEnv) XXX_DiscardUnknown() {
920
+	xxx_messageInfo_ProxyEnv.DiscardUnknown(m)
921
+}
922
+
923
+var xxx_messageInfo_ProxyEnv proto.InternalMessageInfo
900 924
 
901 925
 func (m *ProxyEnv) GetHttpProxy() string {
902 926
 	if m != nil {
... ...
@@ -928,13 +1316,37 @@ func (m *ProxyEnv) GetNoProxy() string {
928 928
 
929 929
 // WorkerConstraints defines conditions for the worker
930 930
 type WorkerConstraints struct {
931
-	Filter []string `protobuf:"bytes,1,rep,name=filter" json:"filter,omitempty"`
931
+	Filter []string `protobuf:"bytes,1,rep,name=filter,proto3" json:"filter,omitempty"`
932 932
 }
933 933
 
934
-func (m *WorkerConstraints) Reset()                    { *m = WorkerConstraints{} }
935
-func (m *WorkerConstraints) String() string            { return proto.CompactTextString(m) }
936
-func (*WorkerConstraints) ProtoMessage()               {}
937
-func (*WorkerConstraints) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{17} }
934
+func (m *WorkerConstraints) Reset()         { *m = WorkerConstraints{} }
935
+func (m *WorkerConstraints) String() string { return proto.CompactTextString(m) }
936
+func (*WorkerConstraints) ProtoMessage()    {}
937
+func (*WorkerConstraints) Descriptor() ([]byte, []int) {
938
+	return fileDescriptor_ops_821a7942fdf920e6, []int{17}
939
+}
940
+func (m *WorkerConstraints) XXX_Unmarshal(b []byte) error {
941
+	return m.Unmarshal(b)
942
+}
943
+func (m *WorkerConstraints) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
944
+	b = b[:cap(b)]
945
+	n, err := m.MarshalTo(b)
946
+	if err != nil {
947
+		return nil, err
948
+	}
949
+	return b[:n], nil
950
+}
951
+func (dst *WorkerConstraints) XXX_Merge(src proto.Message) {
952
+	xxx_messageInfo_WorkerConstraints.Merge(dst, src)
953
+}
954
+func (m *WorkerConstraints) XXX_Size() int {
955
+	return m.Size()
956
+}
957
+func (m *WorkerConstraints) XXX_DiscardUnknown() {
958
+	xxx_messageInfo_WorkerConstraints.DiscardUnknown(m)
959
+}
960
+
961
+var xxx_messageInfo_WorkerConstraints proto.InternalMessageInfo
938 962
 
939 963
 func (m *WorkerConstraints) GetFilter() []string {
940 964
 	if m != nil {
... ...
@@ -946,16 +1358,40 @@ func (m *WorkerConstraints) GetFilter() []string {
946 946
 // Definition is the LLB definition structure with per-vertex metadata entries
947 947
 type Definition struct {
948 948
 	// def is a list of marshaled Op messages
949
-	Def [][]byte `protobuf:"bytes,1,rep,name=def" json:"def,omitempty"`
949
+	Def [][]byte `protobuf:"bytes,1,rep,name=def,proto3" json:"def,omitempty"`
950 950
 	// metadata contains metadata for the each of the Op messages.
951 951
 	// A key must be an LLB op digest string. Currently, empty string is not expected as a key, but it may change in the future.
952
-	Metadata map[github_com_opencontainers_go_digest.Digest]OpMetadata `protobuf:"bytes,2,rep,name=metadata,castkey=github.com/opencontainers/go-digest.Digest" json:"metadata" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
952
+	Metadata map[github_com_opencontainers_go_digest.Digest]OpMetadata `protobuf:"bytes,2,rep,name=metadata,proto3,castkey=github.com/opencontainers/go-digest.Digest" json:"metadata" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
953 953
 }
954 954
 
955
-func (m *Definition) Reset()                    { *m = Definition{} }
956
-func (m *Definition) String() string            { return proto.CompactTextString(m) }
957
-func (*Definition) ProtoMessage()               {}
958
-func (*Definition) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{18} }
955
+func (m *Definition) Reset()         { *m = Definition{} }
956
+func (m *Definition) String() string { return proto.CompactTextString(m) }
957
+func (*Definition) ProtoMessage()    {}
958
+func (*Definition) Descriptor() ([]byte, []int) {
959
+	return fileDescriptor_ops_821a7942fdf920e6, []int{18}
960
+}
961
+func (m *Definition) XXX_Unmarshal(b []byte) error {
962
+	return m.Unmarshal(b)
963
+}
964
+func (m *Definition) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
965
+	b = b[:cap(b)]
966
+	n, err := m.MarshalTo(b)
967
+	if err != nil {
968
+		return nil, err
969
+	}
970
+	return b[:n], nil
971
+}
972
+func (dst *Definition) XXX_Merge(src proto.Message) {
973
+	xxx_messageInfo_Definition.Merge(dst, src)
974
+}
975
+func (m *Definition) XXX_Size() int {
976
+	return m.Size()
977
+}
978
+func (m *Definition) XXX_DiscardUnknown() {
979
+	xxx_messageInfo_Definition.DiscardUnknown(m)
980
+}
981
+
982
+var xxx_messageInfo_Definition proto.InternalMessageInfo
959 983
 
960 984
 func (m *Definition) GetDef() [][]byte {
961 985
 	if m != nil {
... ...
@@ -976,10 +1412,34 @@ type HostIP struct {
976 976
 	IP   string `protobuf:"bytes,2,opt,name=IP,proto3" json:"IP,omitempty"`
977 977
 }
978 978
 
979
-func (m *HostIP) Reset()                    { *m = HostIP{} }
980
-func (m *HostIP) String() string            { return proto.CompactTextString(m) }
981
-func (*HostIP) ProtoMessage()               {}
982
-func (*HostIP) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{19} }
979
+func (m *HostIP) Reset()         { *m = HostIP{} }
980
+func (m *HostIP) String() string { return proto.CompactTextString(m) }
981
+func (*HostIP) ProtoMessage()    {}
982
+func (*HostIP) Descriptor() ([]byte, []int) {
983
+	return fileDescriptor_ops_821a7942fdf920e6, []int{19}
984
+}
985
+func (m *HostIP) XXX_Unmarshal(b []byte) error {
986
+	return m.Unmarshal(b)
987
+}
988
+func (m *HostIP) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
989
+	b = b[:cap(b)]
990
+	n, err := m.MarshalTo(b)
991
+	if err != nil {
992
+		return nil, err
993
+	}
994
+	return b[:n], nil
995
+}
996
+func (dst *HostIP) XXX_Merge(src proto.Message) {
997
+	xxx_messageInfo_HostIP.Merge(dst, src)
998
+}
999
+func (m *HostIP) XXX_Size() int {
1000
+	return m.Size()
1001
+}
1002
+func (m *HostIP) XXX_DiscardUnknown() {
1003
+	xxx_messageInfo_HostIP.DiscardUnknown(m)
1004
+}
1005
+
1006
+var xxx_messageInfo_HostIP proto.InternalMessageInfo
983 1007
 
984 1008
 func (m *HostIP) GetHost() string {
985 1009
 	if m != nil {
... ...
@@ -1008,13 +1468,19 @@ func init() {
1008 1008
 	proto.RegisterType((*CopyOp)(nil), "pb.CopyOp")
1009 1009
 	proto.RegisterType((*CopySource)(nil), "pb.CopySource")
1010 1010
 	proto.RegisterType((*SourceOp)(nil), "pb.SourceOp")
1011
+	proto.RegisterMapType((map[string]string)(nil), "pb.SourceOp.AttrsEntry")
1011 1012
 	proto.RegisterType((*BuildOp)(nil), "pb.BuildOp")
1013
+	proto.RegisterMapType((map[string]string)(nil), "pb.BuildOp.AttrsEntry")
1014
+	proto.RegisterMapType((map[string]*BuildInput)(nil), "pb.BuildOp.InputsEntry")
1012 1015
 	proto.RegisterType((*BuildInput)(nil), "pb.BuildInput")
1013 1016
 	proto.RegisterType((*OpMetadata)(nil), "pb.OpMetadata")
1017
+	proto.RegisterMapType((map[github_com_moby_buildkit_util_apicaps.CapID]bool)(nil), "pb.OpMetadata.CapsEntry")
1018
+	proto.RegisterMapType((map[string]string)(nil), "pb.OpMetadata.DescriptionEntry")
1014 1019
 	proto.RegisterType((*ExportCache)(nil), "pb.ExportCache")
1015 1020
 	proto.RegisterType((*ProxyEnv)(nil), "pb.ProxyEnv")
1016 1021
 	proto.RegisterType((*WorkerConstraints)(nil), "pb.WorkerConstraints")
1017 1022
 	proto.RegisterType((*Definition)(nil), "pb.Definition")
1023
+	proto.RegisterMapType((map[github_com_opencontainers_go_digest.Digest]OpMetadata)(nil), "pb.Definition.MetadataEntry")
1018 1024
 	proto.RegisterType((*HostIP)(nil), "pb.HostIP")
1019 1025
 	proto.RegisterEnum("pb.NetMode", NetMode_name, NetMode_value)
1020 1026
 	proto.RegisterEnum("pb.MountType", MountType_name, MountType_value)
... ...
@@ -1655,7 +2121,7 @@ func (m *SourceOp) MarshalTo(dAtA []byte) (int, error) {
1655 1655
 		for k, _ := range m.Attrs {
1656 1656
 			keysForAttrs = append(keysForAttrs, string(k))
1657 1657
 		}
1658
-		sortkeys.Strings(keysForAttrs)
1658
+		github_com_gogo_protobuf_sortkeys.Strings(keysForAttrs)
1659 1659
 		for _, k := range keysForAttrs {
1660 1660
 			dAtA[i] = 0x12
1661 1661
 			i++
... ...
@@ -1700,7 +2166,7 @@ func (m *BuildOp) MarshalTo(dAtA []byte) (int, error) {
1700 1700
 		for k, _ := range m.Inputs {
1701 1701
 			keysForInputs = append(keysForInputs, string(k))
1702 1702
 		}
1703
-		sortkeys.Strings(keysForInputs)
1703
+		github_com_gogo_protobuf_sortkeys.Strings(keysForInputs)
1704 1704
 		for _, k := range keysForInputs {
1705 1705
 			dAtA[i] = 0x12
1706 1706
 			i++
... ...
@@ -1743,7 +2209,7 @@ func (m *BuildOp) MarshalTo(dAtA []byte) (int, error) {
1743 1743
 		for k, _ := range m.Attrs {
1744 1744
 			keysForAttrs = append(keysForAttrs, string(k))
1745 1745
 		}
1746
-		sortkeys.Strings(keysForAttrs)
1746
+		github_com_gogo_protobuf_sortkeys.Strings(keysForAttrs)
1747 1747
 		for _, k := range keysForAttrs {
1748 1748
 			dAtA[i] = 0x22
1749 1749
 			i++
... ...
@@ -1816,7 +2282,7 @@ func (m *OpMetadata) MarshalTo(dAtA []byte) (int, error) {
1816 1816
 		for k, _ := range m.Description {
1817 1817
 			keysForDescription = append(keysForDescription, string(k))
1818 1818
 		}
1819
-		sortkeys.Strings(keysForDescription)
1819
+		github_com_gogo_protobuf_sortkeys.Strings(keysForDescription)
1820 1820
 		for _, k := range keysForDescription {
1821 1821
 			dAtA[i] = 0x12
1822 1822
 			i++
... ...
@@ -1848,7 +2314,7 @@ func (m *OpMetadata) MarshalTo(dAtA []byte) (int, error) {
1848 1848
 		for k, _ := range m.Caps {
1849 1849
 			keysForCaps = append(keysForCaps, string(k))
1850 1850
 		}
1851
-		sortkeys.Strings(keysForCaps)
1851
+		github_com_gogo_protobuf_sortkeys.Strings(keysForCaps)
1852 1852
 		for _, k := range keysForCaps {
1853 1853
 			dAtA[i] = 0x2a
1854 1854
 			i++
... ...
@@ -2003,7 +2469,7 @@ func (m *Definition) MarshalTo(dAtA []byte) (int, error) {
2003 2003
 		for k, _ := range m.Metadata {
2004 2004
 			keysForMetadata = append(keysForMetadata, string(k))
2005 2005
 		}
2006
-		sortkeys.Strings(keysForMetadata)
2006
+		github_com_gogo_protobuf_sortkeys.Strings(keysForMetadata)
2007 2007
 		for _, k := range keysForMetadata {
2008 2008
 			dAtA[i] = 0x12
2009 2009
 			i++
... ...
@@ -2072,6 +2538,9 @@ func encodeVarintOps(dAtA []byte, offset int, v uint64) int {
2072 2072
 	return offset + 1
2073 2073
 }
2074 2074
 func (m *Op) Size() (n int) {
2075
+	if m == nil {
2076
+		return 0
2077
+	}
2075 2078
 	var l int
2076 2079
 	_ = l
2077 2080
 	if len(m.Inputs) > 0 {
... ...
@@ -2095,6 +2564,9 @@ func (m *Op) Size() (n int) {
2095 2095
 }
2096 2096
 
2097 2097
 func (m *Op_Exec) Size() (n int) {
2098
+	if m == nil {
2099
+		return 0
2100
+	}
2098 2101
 	var l int
2099 2102
 	_ = l
2100 2103
 	if m.Exec != nil {
... ...
@@ -2104,6 +2576,9 @@ func (m *Op_Exec) Size() (n int) {
2104 2104
 	return n
2105 2105
 }
2106 2106
 func (m *Op_Source) Size() (n int) {
2107
+	if m == nil {
2108
+		return 0
2109
+	}
2107 2110
 	var l int
2108 2111
 	_ = l
2109 2112
 	if m.Source != nil {
... ...
@@ -2113,6 +2588,9 @@ func (m *Op_Source) Size() (n int) {
2113 2113
 	return n
2114 2114
 }
2115 2115
 func (m *Op_Copy) Size() (n int) {
2116
+	if m == nil {
2117
+		return 0
2118
+	}
2116 2119
 	var l int
2117 2120
 	_ = l
2118 2121
 	if m.Copy != nil {
... ...
@@ -2122,6 +2600,9 @@ func (m *Op_Copy) Size() (n int) {
2122 2122
 	return n
2123 2123
 }
2124 2124
 func (m *Op_Build) Size() (n int) {
2125
+	if m == nil {
2126
+		return 0
2127
+	}
2125 2128
 	var l int
2126 2129
 	_ = l
2127 2130
 	if m.Build != nil {
... ...
@@ -2131,6 +2612,9 @@ func (m *Op_Build) Size() (n int) {
2131 2131
 	return n
2132 2132
 }
2133 2133
 func (m *Platform) Size() (n int) {
2134
+	if m == nil {
2135
+		return 0
2136
+	}
2134 2137
 	var l int
2135 2138
 	_ = l
2136 2139
 	l = len(m.Architecture)
... ...
@@ -2159,6 +2643,9 @@ func (m *Platform) Size() (n int) {
2159 2159
 }
2160 2160
 
2161 2161
 func (m *Input) Size() (n int) {
2162
+	if m == nil {
2163
+		return 0
2164
+	}
2162 2165
 	var l int
2163 2166
 	_ = l
2164 2167
 	l = len(m.Digest)
... ...
@@ -2172,6 +2659,9 @@ func (m *Input) Size() (n int) {
2172 2172
 }
2173 2173
 
2174 2174
 func (m *ExecOp) Size() (n int) {
2175
+	if m == nil {
2176
+		return 0
2177
+	}
2175 2178
 	var l int
2176 2179
 	_ = l
2177 2180
 	if m.Meta != nil {
... ...
@@ -2191,6 +2681,9 @@ func (m *ExecOp) Size() (n int) {
2191 2191
 }
2192 2192
 
2193 2193
 func (m *Meta) Size() (n int) {
2194
+	if m == nil {
2195
+		return 0
2196
+	}
2194 2197
 	var l int
2195 2198
 	_ = l
2196 2199
 	if len(m.Args) > 0 {
... ...
@@ -2227,6 +2720,9 @@ func (m *Meta) Size() (n int) {
2227 2227
 }
2228 2228
 
2229 2229
 func (m *Mount) Size() (n int) {
2230
+	if m == nil {
2231
+		return 0
2232
+	}
2230 2233
 	var l int
2231 2234
 	_ = l
2232 2235
 	if m.Input != 0 {
... ...
@@ -2265,6 +2761,9 @@ func (m *Mount) Size() (n int) {
2265 2265
 }
2266 2266
 
2267 2267
 func (m *CacheOpt) Size() (n int) {
2268
+	if m == nil {
2269
+		return 0
2270
+	}
2268 2271
 	var l int
2269 2272
 	_ = l
2270 2273
 	l = len(m.ID)
... ...
@@ -2278,6 +2777,9 @@ func (m *CacheOpt) Size() (n int) {
2278 2278
 }
2279 2279
 
2280 2280
 func (m *SecretOpt) Size() (n int) {
2281
+	if m == nil {
2282
+		return 0
2283
+	}
2281 2284
 	var l int
2282 2285
 	_ = l
2283 2286
 	l = len(m.ID)
... ...
@@ -2300,6 +2802,9 @@ func (m *SecretOpt) Size() (n int) {
2300 2300
 }
2301 2301
 
2302 2302
 func (m *SSHOpt) Size() (n int) {
2303
+	if m == nil {
2304
+		return 0
2305
+	}
2303 2306
 	var l int
2304 2307
 	_ = l
2305 2308
 	l = len(m.ID)
... ...
@@ -2322,6 +2827,9 @@ func (m *SSHOpt) Size() (n int) {
2322 2322
 }
2323 2323
 
2324 2324
 func (m *CopyOp) Size() (n int) {
2325
+	if m == nil {
2326
+		return 0
2327
+	}
2325 2328
 	var l int
2326 2329
 	_ = l
2327 2330
 	if len(m.Src) > 0 {
... ...
@@ -2338,6 +2846,9 @@ func (m *CopyOp) Size() (n int) {
2338 2338
 }
2339 2339
 
2340 2340
 func (m *CopySource) Size() (n int) {
2341
+	if m == nil {
2342
+		return 0
2343
+	}
2341 2344
 	var l int
2342 2345
 	_ = l
2343 2346
 	if m.Input != 0 {
... ...
@@ -2351,6 +2862,9 @@ func (m *CopySource) Size() (n int) {
2351 2351
 }
2352 2352
 
2353 2353
 func (m *SourceOp) Size() (n int) {
2354
+	if m == nil {
2355
+		return 0
2356
+	}
2354 2357
 	var l int
2355 2358
 	_ = l
2356 2359
 	l = len(m.Identifier)
... ...
@@ -2369,6 +2883,9 @@ func (m *SourceOp) Size() (n int) {
2369 2369
 }
2370 2370
 
2371 2371
 func (m *BuildOp) Size() (n int) {
2372
+	if m == nil {
2373
+		return 0
2374
+	}
2372 2375
 	var l int
2373 2376
 	_ = l
2374 2377
 	if m.Builder != 0 {
... ...
@@ -2403,6 +2920,9 @@ func (m *BuildOp) Size() (n int) {
2403 2403
 }
2404 2404
 
2405 2405
 func (m *BuildInput) Size() (n int) {
2406
+	if m == nil {
2407
+		return 0
2408
+	}
2406 2409
 	var l int
2407 2410
 	_ = l
2408 2411
 	if m.Input != 0 {
... ...
@@ -2412,6 +2932,9 @@ func (m *BuildInput) Size() (n int) {
2412 2412
 }
2413 2413
 
2414 2414
 func (m *OpMetadata) Size() (n int) {
2415
+	if m == nil {
2416
+		return 0
2417
+	}
2415 2418
 	var l int
2416 2419
 	_ = l
2417 2420
 	if m.IgnoreCache {
... ...
@@ -2441,6 +2964,9 @@ func (m *OpMetadata) Size() (n int) {
2441 2441
 }
2442 2442
 
2443 2443
 func (m *ExportCache) Size() (n int) {
2444
+	if m == nil {
2445
+		return 0
2446
+	}
2444 2447
 	var l int
2445 2448
 	_ = l
2446 2449
 	if m.Value {
... ...
@@ -2450,6 +2976,9 @@ func (m *ExportCache) Size() (n int) {
2450 2450
 }
2451 2451
 
2452 2452
 func (m *ProxyEnv) Size() (n int) {
2453
+	if m == nil {
2454
+		return 0
2455
+	}
2453 2456
 	var l int
2454 2457
 	_ = l
2455 2458
 	l = len(m.HttpProxy)
... ...
@@ -2472,6 +3001,9 @@ func (m *ProxyEnv) Size() (n int) {
2472 2472
 }
2473 2473
 
2474 2474
 func (m *WorkerConstraints) Size() (n int) {
2475
+	if m == nil {
2476
+		return 0
2477
+	}
2475 2478
 	var l int
2476 2479
 	_ = l
2477 2480
 	if len(m.Filter) > 0 {
... ...
@@ -2484,6 +3016,9 @@ func (m *WorkerConstraints) Size() (n int) {
2484 2484
 }
2485 2485
 
2486 2486
 func (m *Definition) Size() (n int) {
2487
+	if m == nil {
2488
+		return 0
2489
+	}
2487 2490
 	var l int
2488 2491
 	_ = l
2489 2492
 	if len(m.Def) > 0 {
... ...
@@ -2505,6 +3040,9 @@ func (m *Definition) Size() (n int) {
2505 2505
 }
2506 2506
 
2507 2507
 func (m *HostIP) Size() (n int) {
2508
+	if m == nil {
2509
+		return 0
2510
+	}
2508 2511
 	var l int
2509 2512
 	_ = l
2510 2513
 	l = len(m.Host)
... ...
@@ -6033,99 +6571,99 @@ var (
6033 6033
 	ErrIntOverflowOps   = fmt.Errorf("proto: integer overflow")
6034 6034
 )
6035 6035
 
6036
-func init() { proto.RegisterFile("ops.proto", fileDescriptorOps) }
6037
-
6038
-var fileDescriptorOps = []byte{
6039
-	// 1444 bytes of a gzipped FileDescriptorProto
6040
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x4b, 0x6f, 0x1b, 0x47,
6041
-	0x12, 0x16, 0x87, 0xcf, 0x29, 0x4a, 0x32, 0xb7, 0xfd, 0x58, 0xae, 0xd6, 0x2b, 0x69, 0xc7, 0xbb,
6042
-	0x81, 0x2c, 0x59, 0x14, 0x40, 0x03, 0xb6, 0x91, 0x83, 0x11, 0xf1, 0x61, 0x88, 0x71, 0x24, 0x0a,
6043
-	0x4d, 0x45, 0x39, 0x1a, 0xa3, 0x61, 0x93, 0x1a, 0x88, 0x9a, 0x1e, 0xcc, 0x34, 0x6d, 0xf1, 0x92,
6044
-	0x83, 0x7f, 0x41, 0x80, 0x00, 0xb9, 0xe7, 0x98, 0x1f, 0x91, 0xbb, 0x8f, 0x41, 0x4e, 0x49, 0x0e,
6045
-	0x4e, 0xa0, 0xfc, 0x91, 0xa0, 0xaa, 0x7b, 0x38, 0xe3, 0x47, 0x10, 0x1b, 0x09, 0x72, 0x62, 0x75,
6046
-	0xd5, 0xd7, 0x5f, 0xd7, 0xab, 0xbb, 0x86, 0x60, 0xcb, 0x30, 0x6e, 0x84, 0x91, 0x54, 0x92, 0x59,
6047
-	0xe1, 0xc9, 0xca, 0xf6, 0xd8, 0x57, 0xa7, 0xd3, 0x93, 0x86, 0x27, 0xcf, 0x77, 0xc6, 0x72, 0x2c,
6048
-	0x77, 0xc8, 0x74, 0x32, 0x1d, 0xd1, 0x8a, 0x16, 0x24, 0xe9, 0x2d, 0xce, 0xd7, 0x16, 0x58, 0xfd,
6049
-	0x90, 0xfd, 0x17, 0x4a, 0x7e, 0x10, 0x4e, 0x55, 0x5c, 0xcf, 0xad, 0xe7, 0x37, 0xaa, 0x4d, 0xbb,
6050
-	0x11, 0x9e, 0x34, 0x7a, 0xa8, 0xe1, 0xc6, 0xc0, 0xd6, 0xa1, 0x20, 0x2e, 0x84, 0x57, 0xb7, 0xd6,
6051
-	0x73, 0x1b, 0xd5, 0x26, 0x20, 0xa0, 0x7b, 0x21, 0xbc, 0x7e, 0xb8, 0xb7, 0xc0, 0xc9, 0xc2, 0x3e,
6052
-	0x80, 0x52, 0x2c, 0xa7, 0x91, 0x27, 0xea, 0x79, 0xc2, 0x2c, 0x22, 0x66, 0x40, 0x1a, 0x42, 0x19,
6053
-	0x2b, 0x32, 0x79, 0x32, 0x9c, 0xd5, 0x0b, 0x29, 0x53, 0x5b, 0x86, 0x33, 0xcd, 0x84, 0x16, 0x76,
6054
-	0x0b, 0x8a, 0x27, 0x53, 0x7f, 0x32, 0xac, 0x17, 0x09, 0x52, 0x45, 0x48, 0x0b, 0x15, 0x84, 0xd1,
6055
-	0x36, 0xb6, 0x01, 0x95, 0x70, 0xe2, 0xaa, 0x91, 0x8c, 0xce, 0xeb, 0x90, 0x1e, 0x78, 0x68, 0x74,
6056
-	0x7c, 0x6e, 0x65, 0xf7, 0xa1, 0xea, 0xc9, 0x20, 0x56, 0x91, 0xeb, 0x07, 0x2a, 0xae, 0x57, 0x09,
6057
-	0x7c, 0x1d, 0xc1, 0x9f, 0xc9, 0xe8, 0x4c, 0x44, 0xed, 0xd4, 0xc8, 0xb3, 0xc8, 0x56, 0x01, 0x2c,
6058
-	0x19, 0x3a, 0x5f, 0xe5, 0xa0, 0x92, 0xb0, 0x32, 0x07, 0x16, 0x77, 0x23, 0xef, 0xd4, 0x57, 0xc2,
6059
-	0x53, 0xd3, 0x48, 0xd4, 0x73, 0xeb, 0xb9, 0x0d, 0x9b, 0xbf, 0xa2, 0x63, 0xcb, 0x60, 0xf5, 0x07,
6060
-	0x94, 0x28, 0x9b, 0x5b, 0xfd, 0x01, 0xab, 0x43, 0xf9, 0xd8, 0x8d, 0x7c, 0x37, 0x50, 0x94, 0x19,
6061
-	0x9b, 0x27, 0x4b, 0x76, 0x13, 0xec, 0xfe, 0xe0, 0x58, 0x44, 0xb1, 0x2f, 0x03, 0xca, 0x87, 0xcd,
6062
-	0x53, 0x05, 0x5b, 0x05, 0xe8, 0x0f, 0x1e, 0x09, 0x17, 0x49, 0xe3, 0x7a, 0x71, 0x3d, 0xbf, 0x61,
6063
-	0xf3, 0x8c, 0xc6, 0xf9, 0x1c, 0x8a, 0x54, 0x23, 0xf6, 0x31, 0x94, 0x86, 0xfe, 0x58, 0xc4, 0x4a,
6064
-	0xbb, 0xd3, 0x6a, 0xbe, 0x78, 0xb9, 0xb6, 0xf0, 0xd3, 0xcb, 0xb5, 0xcd, 0x4c, 0x33, 0xc8, 0x50,
6065
-	0x04, 0x9e, 0x0c, 0x94, 0xeb, 0x07, 0x22, 0x8a, 0x77, 0xc6, 0x72, 0x5b, 0x6f, 0x69, 0x74, 0xe8,
6066
-	0x87, 0x1b, 0x06, 0x76, 0x1b, 0x8a, 0x7e, 0x30, 0x14, 0x17, 0xe4, 0x7f, 0xbe, 0x75, 0xd5, 0x50,
6067
-	0x55, 0xfb, 0x53, 0x15, 0x4e, 0x55, 0x0f, 0x4d, 0x5c, 0x23, 0x9c, 0x10, 0x4a, 0xba, 0x05, 0xd8,
6068
-	0x4d, 0x28, 0x9c, 0x0b, 0xe5, 0xd2, 0xf1, 0xd5, 0x66, 0x05, 0x53, 0xbb, 0x2f, 0x94, 0xcb, 0x49,
6069
-	0x8b, 0xdd, 0x75, 0x2e, 0xa7, 0x98, 0x7a, 0x2b, 0xed, 0xae, 0x7d, 0xd4, 0x70, 0x63, 0x60, 0xff,
6070
-	0x87, 0x72, 0x20, 0xd4, 0x33, 0x19, 0x9d, 0x51, 0x8a, 0x96, 0x75, 0xcd, 0x0f, 0x84, 0xda, 0x97,
6071
-	0x43, 0xc1, 0x13, 0x9b, 0xf3, 0x4d, 0x0e, 0x0a, 0x48, 0xcc, 0x18, 0x14, 0xdc, 0x68, 0xac, 0xdb,
6072
-	0xd5, 0xe6, 0x24, 0xb3, 0x1a, 0xe4, 0x45, 0xf0, 0x94, 0xce, 0xb0, 0x39, 0x8a, 0xa8, 0xf1, 0x9e,
6073
-	0x0d, 0x4d, 0xd2, 0x51, 0xc4, 0x7d, 0xd3, 0x58, 0x44, 0x26, 0xd7, 0x24, 0xb3, 0xdb, 0x60, 0x87,
6074
-	0x91, 0xbc, 0x98, 0x3d, 0xc1, 0xdd, 0xc5, 0x4c, 0x27, 0xa1, 0xb2, 0x1b, 0x3c, 0xe5, 0x95, 0xd0,
6075
-	0x48, 0x6c, 0x13, 0x40, 0x5c, 0xa8, 0xc8, 0xdd, 0x93, 0xb1, 0x8a, 0xeb, 0x25, 0x8a, 0x86, 0x1a,
6076
-	0x18, 0x15, 0xbd, 0x43, 0x9e, 0xb1, 0x3a, 0xdf, 0x5b, 0x50, 0xa4, 0x20, 0xd9, 0x06, 0xa6, 0x34,
6077
-	0x9c, 0xea, 0xea, 0xe4, 0x5b, 0xcc, 0xa4, 0x14, 0xa8, 0x78, 0xf3, 0x8c, 0x62, 0x21, 0x57, 0xa0,
6078
-	0x12, 0x8b, 0x89, 0xf0, 0x94, 0x8c, 0x4c, 0xff, 0xcc, 0xd7, 0xe8, 0xfa, 0x10, 0x4b, 0xac, 0xa3,
6079
-	0x21, 0x99, 0x6d, 0x41, 0x49, 0x52, 0x5d, 0x28, 0xa0, 0xdf, 0xa9, 0x96, 0x81, 0x20, 0x79, 0x24,
6080
-	0xdc, 0xa1, 0x0c, 0x26, 0x33, 0x0a, 0xb3, 0xc2, 0xe7, 0x6b, 0xb6, 0x05, 0x36, 0x55, 0xe2, 0x68,
6081
-	0x16, 0x8a, 0x7a, 0x89, 0x2a, 0xb0, 0x34, 0xaf, 0x12, 0x2a, 0x79, 0x6a, 0xc7, 0x9b, 0xe7, 0xb9,
6082
-	0xde, 0xa9, 0xe8, 0x87, 0xaa, 0x7e, 0x2d, 0xcd, 0x57, 0xdb, 0xe8, 0xf8, 0xdc, 0x8a, 0xb4, 0xb1,
6083
-	0xf0, 0x22, 0xa1, 0x10, 0x7a, 0x9d, 0xa0, 0x44, 0x3b, 0x48, 0x94, 0x3c, 0xb5, 0x33, 0x07, 0x4a,
6084
-	0x83, 0xc1, 0x1e, 0x22, 0x6f, 0xa4, 0x2f, 0x83, 0xd6, 0x70, 0x63, 0x71, 0x7a, 0x50, 0x49, 0x8e,
6085
-	0xc1, 0x6b, 0xd6, 0xeb, 0x98, 0x0b, 0x68, 0xf5, 0x3a, 0x6c, 0x1b, 0xca, 0xf1, 0xa9, 0x1b, 0xf9,
6086
-	0xc1, 0x98, 0x72, 0xb7, 0xdc, 0xbc, 0x3a, 0xf7, 0x6a, 0xa0, 0xf5, 0xc8, 0x94, 0x60, 0x1c, 0x09,
6087
-	0xf6, 0xdc, 0x8d, 0x37, 0xb8, 0x6a, 0x90, 0x9f, 0xfa, 0x43, 0xe2, 0x59, 0xe2, 0x28, 0xa2, 0x66,
6088
-	0xec, 0xeb, 0x5e, 0x5a, 0xe2, 0x28, 0x62, 0x41, 0xce, 0xe5, 0x50, 0x50, 0xea, 0x97, 0x38, 0xc9,
6089
-	0x98, 0x63, 0x19, 0x2a, 0x5f, 0x06, 0xee, 0x24, 0xc9, 0x71, 0xb2, 0x76, 0x26, 0x49, 0x7c, 0x7f,
6090
-	0xcb, 0x69, 0x0f, 0xa1, 0xa4, 0x5f, 0x55, 0xb6, 0x0e, 0xf9, 0x38, 0xf2, 0xcc, 0xcb, 0xbe, 0x9c,
6091
-	0x3c, 0xb7, 0xfa, 0x61, 0xe6, 0x68, 0x9a, 0xb7, 0x96, 0x95, 0xb6, 0x96, 0xc3, 0x01, 0x52, 0xd8,
6092
-	0x5f, 0xd3, 0xc2, 0xce, 0x97, 0x39, 0xa8, 0x24, 0x03, 0x01, 0x5f, 0x37, 0x7f, 0x28, 0x02, 0xe5,
6093
-	0x8f, 0x7c, 0x11, 0x99, 0x64, 0x64, 0x34, 0x6c, 0x1b, 0x8a, 0xae, 0x52, 0x51, 0xf2, 0x68, 0xfc,
6094
-	0x33, 0x3b, 0x4d, 0x1a, 0xbb, 0x68, 0xe9, 0x06, 0x2a, 0x9a, 0x71, 0x8d, 0x5a, 0x79, 0x00, 0x90,
6095
-	0x2a, 0x31, 0x7f, 0x67, 0x62, 0x66, 0x58, 0x51, 0x64, 0xd7, 0xa0, 0xf8, 0xd4, 0x9d, 0x4c, 0x85,
6096
-	0x71, 0x4a, 0x2f, 0x3e, 0xb4, 0x1e, 0xe4, 0x9c, 0x6f, 0x2d, 0x28, 0x9b, 0xe9, 0xc2, 0xee, 0x40,
6097
-	0x99, 0xa6, 0x8b, 0xf1, 0xe8, 0xed, 0x91, 0x26, 0x10, 0xb6, 0x33, 0x1f, 0x9b, 0x19, 0x1f, 0x0d,
6098
-	0x95, 0x1e, 0x9f, 0xc6, 0xc7, 0x74, 0x88, 0xe6, 0x87, 0x62, 0x64, 0xe6, 0x23, 0x95, 0xa2, 0x23,
6099
-	0x46, 0x7e, 0xe0, 0x63, 0xcd, 0x38, 0x9a, 0xd8, 0x9d, 0x24, 0xea, 0x02, 0x31, 0xde, 0xc8, 0x32,
6100
-	0xbe, 0x19, 0x74, 0x0f, 0xaa, 0x99, 0x63, 0xde, 0x12, 0xf5, 0xff, 0xb2, 0x51, 0x9b, 0x23, 0x89,
6101
-	0x4e, 0x0f, 0xf7, 0x34, 0x0b, 0x7f, 0x22, 0x7f, 0xf7, 0x00, 0x52, 0xca, 0x77, 0xef, 0x14, 0xe7,
6102
-	0x79, 0x1e, 0xa0, 0x1f, 0xe2, 0x73, 0x3e, 0x74, 0x69, 0x4a, 0x2c, 0xfa, 0xe3, 0x40, 0x46, 0xe2,
6103
-	0x09, 0x3d, 0x1f, 0xb4, 0xbf, 0xc2, 0xab, 0x5a, 0x47, 0xb7, 0x98, 0xed, 0x42, 0x75, 0x28, 0x62,
6104
-	0x2f, 0xf2, 0xa9, 0xc9, 0x4d, 0xd2, 0xd7, 0x30, 0xa6, 0x94, 0xa7, 0xd1, 0x49, 0x11, 0x3a, 0x57,
6105
-	0xd9, 0x3d, 0xac, 0x09, 0x8b, 0xe2, 0x22, 0x94, 0x91, 0x32, 0xa7, 0xe8, 0x8f, 0x90, 0x2b, 0xfa,
6106
-	0x73, 0x06, 0xf5, 0x74, 0x12, 0xaf, 0x8a, 0x74, 0xc1, 0x5c, 0x28, 0x78, 0x6e, 0xa8, 0x27, 0x70,
6107
-	0xb5, 0x59, 0x7f, 0xed, 0xbc, 0xb6, 0x1b, 0xea, 0xa4, 0xb5, 0xee, 0x62, 0xac, 0xcf, 0x7f, 0x5e,
6108
-	0xdb, 0xca, 0x8c, 0xdd, 0x73, 0x79, 0x32, 0xdb, 0xa1, 0x7e, 0x39, 0xf3, 0xd5, 0xce, 0x54, 0xf9,
6109
-	0x93, 0x1d, 0x37, 0xf4, 0x91, 0x0e, 0x37, 0xf6, 0x3a, 0x9c, 0xa8, 0x57, 0x1e, 0x42, 0xed, 0x75,
6110
-	0xbf, 0xdf, 0xa7, 0x06, 0x2b, 0xf7, 0xc1, 0x9e, 0xfb, 0xf1, 0x47, 0x1b, 0x2b, 0xd9, 0xe2, 0xdd,
6111
-	0x82, 0x6a, 0x26, 0x6e, 0x04, 0x1e, 0x13, 0x50, 0x67, 0x5f, 0x2f, 0x9c, 0xe7, 0xf8, 0x05, 0x94,
6112
-	0xcc, 0xc0, 0xff, 0x00, 0x9c, 0x2a, 0x15, 0x3e, 0xa1, 0xa1, 0x68, 0x0e, 0xb1, 0x51, 0x43, 0x08,
6113
-	0xb6, 0x06, 0x55, 0x5c, 0xc4, 0xc6, 0xae, 0x3d, 0xa5, 0x1d, 0xb1, 0x06, 0xfc, 0x1b, 0xec, 0xd1,
6114
-	0x7c, 0xbb, 0x1e, 0x66, 0x95, 0x51, 0xb2, 0xfb, 0x5f, 0x50, 0x09, 0xa4, 0xb1, 0xe9, 0x19, 0x5d,
6115
-	0x0e, 0x24, 0x99, 0x9c, 0x2d, 0xf8, 0xc7, 0x1b, 0x9f, 0x6b, 0xec, 0x06, 0x94, 0x46, 0xfe, 0x44,
6116
-	0xd1, 0x75, 0xc5, 0xb1, 0x6f, 0x56, 0xce, 0x8f, 0x39, 0x80, 0xf4, 0x6a, 0x61, 0x46, 0xf0, 0xde,
6117
-	0x21, 0x66, 0x51, 0xdf, 0xb3, 0x09, 0x54, 0xce, 0x4d, 0x05, 0x4d, 0x1f, 0xdd, 0x7c, 0xf5, 0x3a,
6118
-	0x36, 0x92, 0x02, 0xeb, 0xda, 0x36, 0x4d, 0x6d, 0xdf, 0xe7, 0x93, 0x6a, 0x7e, 0xc2, 0xca, 0x63,
6119
-	0x58, 0x7a, 0x85, 0xee, 0x1d, 0x6f, 0x6a, 0xda, 0x65, 0xd9, 0x92, 0xdd, 0x81, 0x92, 0xfe, 0xdc,
6120
-	0xc0, 0x77, 0x1b, 0x25, 0x43, 0x43, 0x32, 0xcd, 0x96, 0xc3, 0xe4, 0xe3, 0xb3, 0x77, 0xb8, 0xb9,
6121
-	0x01, 0x65, 0xf3, 0x19, 0xc5, 0x6c, 0x28, 0x7e, 0x7a, 0x30, 0xe8, 0x1e, 0xd5, 0x16, 0x58, 0x05,
6122
-	0x0a, 0x7b, 0xfd, 0xc1, 0x51, 0x2d, 0x87, 0xd2, 0x41, 0xff, 0xa0, 0x5b, 0xb3, 0x36, 0x3f, 0x02,
6123
-	0x7b, 0x3e, 0xee, 0x51, 0xdd, 0xea, 0x1d, 0x74, 0x6a, 0x0b, 0x0c, 0xa0, 0x34, 0xe8, 0xb6, 0x79,
6124
-	0x17, 0xc1, 0x65, 0xc8, 0x0f, 0x06, 0x7b, 0x35, 0x0b, 0xa9, 0xda, 0xbb, 0xed, 0xbd, 0x6e, 0x2d,
6125
-	0x8f, 0xe2, 0xd1, 0xfe, 0xe1, 0xa3, 0x41, 0xad, 0xb0, 0x79, 0x0f, 0xae, 0xbc, 0x36, 0x6e, 0x69,
6126
-	0xf7, 0xde, 0x2e, 0xef, 0x22, 0x53, 0x15, 0xca, 0x87, 0xbc, 0x77, 0xbc, 0x7b, 0xd4, 0xad, 0xe5,
6127
-	0xd0, 0xf0, 0x49, 0xbf, 0xfd, 0xb8, 0xdb, 0xa9, 0x59, 0xad, 0x6b, 0x2f, 0x2e, 0x57, 0x73, 0xdf,
6128
-	0x5d, 0xae, 0xe6, 0x7e, 0xb8, 0x5c, 0xcd, 0xfd, 0x72, 0xb9, 0x9a, 0xfb, 0xe2, 0xd7, 0xd5, 0x85,
6129
-	0x93, 0x12, 0xfd, 0x45, 0xb9, 0xfb, 0x5b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x84, 0xfe, 0x08, 0x0c,
6130
-	0xe2, 0x0c, 0x00, 0x00,
6036
+func init() { proto.RegisterFile("ops.proto", fileDescriptor_ops_821a7942fdf920e6) }
6037
+
6038
+var fileDescriptor_ops_821a7942fdf920e6 = []byte{
6039
+	// 1452 bytes of a gzipped FileDescriptorProto
6040
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x4b, 0x6f, 0x1b, 0xc9,
6041
+	0x11, 0x16, 0x87, 0xcf, 0x29, 0x4a, 0x32, 0xd3, 0x7e, 0x84, 0x51, 0x14, 0x4a, 0x19, 0x27, 0x81,
6042
+	0x2c, 0x59, 0x14, 0x40, 0x03, 0xb6, 0x91, 0x83, 0x11, 0xf1, 0x61, 0x88, 0x71, 0x24, 0x0a, 0x4d,
6043
+	0x45, 0x39, 0x1a, 0xa3, 0x61, 0x93, 0x1a, 0x88, 0x9a, 0x1e, 0xcc, 0x34, 0x6d, 0xf1, 0x92, 0x83,
6044
+	0x7f, 0x41, 0x80, 0x00, 0xb9, 0xe7, 0x98, 0x1f, 0x91, 0xbb, 0x8f, 0x46, 0x4e, 0x4e, 0x0e, 0xce,
6045
+	0x42, 0xfe, 0x23, 0x8b, 0xaa, 0xee, 0xe1, 0x8c, 0x1f, 0x8b, 0xb5, 0xb1, 0x8b, 0x3d, 0xb1, 0xba,
6046
+	0xea, 0xeb, 0xaf, 0xeb, 0xd5, 0x5d, 0x43, 0xb0, 0x65, 0x18, 0x37, 0xc3, 0x48, 0x2a, 0xc9, 0xac,
6047
+	0xf0, 0x6c, 0x6d, 0x77, 0xe2, 0xab, 0xf3, 0xd9, 0x59, 0xd3, 0x93, 0x97, 0x7b, 0x13, 0x39, 0x91,
6048
+	0x7b, 0x64, 0x3a, 0x9b, 0x8d, 0x69, 0x45, 0x0b, 0x92, 0xf4, 0x16, 0xe7, 0x9f, 0x16, 0x58, 0x83,
6049
+	0x90, 0xfd, 0x1a, 0x4a, 0x7e, 0x10, 0xce, 0x54, 0x5c, 0xcf, 0x6d, 0xe6, 0xb7, 0xaa, 0x2d, 0xbb,
6050
+	0x19, 0x9e, 0x35, 0xfb, 0xa8, 0xe1, 0xc6, 0xc0, 0x36, 0xa1, 0x20, 0xae, 0x84, 0x57, 0xb7, 0x36,
6051
+	0x73, 0x5b, 0xd5, 0x16, 0x20, 0xa0, 0x77, 0x25, 0xbc, 0x41, 0x78, 0xb0, 0xc4, 0xc9, 0xc2, 0x7e,
6052
+	0x07, 0xa5, 0x58, 0xce, 0x22, 0x4f, 0xd4, 0xf3, 0x84, 0x59, 0x46, 0xcc, 0x90, 0x34, 0x84, 0x32,
6053
+	0x56, 0x64, 0xf2, 0x64, 0x38, 0xaf, 0x17, 0x52, 0xa6, 0x8e, 0x0c, 0xe7, 0x9a, 0x09, 0x2d, 0xec,
6054
+	0x2e, 0x14, 0xcf, 0x66, 0xfe, 0x74, 0x54, 0x2f, 0x12, 0xa4, 0x8a, 0x90, 0x36, 0x2a, 0x08, 0xa3,
6055
+	0x6d, 0x6c, 0x0b, 0x2a, 0xe1, 0xd4, 0x55, 0x63, 0x19, 0x5d, 0xd6, 0x21, 0x3d, 0xf0, 0xd8, 0xe8,
6056
+	0xf8, 0xc2, 0xca, 0x1e, 0x41, 0xd5, 0x93, 0x41, 0xac, 0x22, 0xd7, 0x0f, 0x54, 0x5c, 0xaf, 0x12,
6057
+	0xf8, 0x36, 0x82, 0xff, 0x22, 0xa3, 0x0b, 0x11, 0x75, 0x52, 0x23, 0xcf, 0x22, 0xdb, 0x05, 0xb0,
6058
+	0x64, 0xe8, 0xfc, 0x23, 0x07, 0x95, 0x84, 0x95, 0x39, 0xb0, 0xbc, 0x1f, 0x79, 0xe7, 0xbe, 0x12,
6059
+	0x9e, 0x9a, 0x45, 0xa2, 0x9e, 0xdb, 0xcc, 0x6d, 0xd9, 0xfc, 0x03, 0x1d, 0x5b, 0x05, 0x6b, 0x30,
6060
+	0xa4, 0x44, 0xd9, 0xdc, 0x1a, 0x0c, 0x59, 0x1d, 0xca, 0xa7, 0x6e, 0xe4, 0xbb, 0x81, 0xa2, 0xcc,
6061
+	0xd8, 0x3c, 0x59, 0xb2, 0x75, 0xb0, 0x07, 0xc3, 0x53, 0x11, 0xc5, 0xbe, 0x0c, 0x28, 0x1f, 0x36,
6062
+	0x4f, 0x15, 0xac, 0x01, 0x30, 0x18, 0x3e, 0x15, 0x2e, 0x92, 0xc6, 0xf5, 0xe2, 0x66, 0x7e, 0xcb,
6063
+	0xe6, 0x19, 0x8d, 0xf3, 0x57, 0x28, 0x52, 0x8d, 0xd8, 0x1f, 0xa1, 0x34, 0xf2, 0x27, 0x22, 0x56,
6064
+	0xda, 0x9d, 0x76, 0xeb, 0xf5, 0xbb, 0x8d, 0xa5, 0xff, 0xbd, 0xdb, 0xd8, 0xce, 0x34, 0x83, 0x0c,
6065
+	0x45, 0xe0, 0xc9, 0x40, 0xb9, 0x7e, 0x20, 0xa2, 0x78, 0x6f, 0x22, 0x77, 0xf5, 0x96, 0x66, 0x97,
6066
+	0x7e, 0xb8, 0x61, 0x60, 0xf7, 0xa0, 0xe8, 0x07, 0x23, 0x71, 0x45, 0xfe, 0xe7, 0xdb, 0x37, 0x0d,
6067
+	0x55, 0x75, 0x30, 0x53, 0xe1, 0x4c, 0xf5, 0xd1, 0xc4, 0x35, 0xc2, 0x09, 0xa1, 0xa4, 0x5b, 0x80,
6068
+	0xad, 0x43, 0xe1, 0x52, 0x28, 0x97, 0x8e, 0xaf, 0xb6, 0x2a, 0x98, 0xda, 0x43, 0xa1, 0x5c, 0x4e,
6069
+	0x5a, 0xec, 0xae, 0x4b, 0x39, 0xc3, 0xd4, 0x5b, 0x69, 0x77, 0x1d, 0xa2, 0x86, 0x1b, 0x03, 0xfb,
6070
+	0x2d, 0x94, 0x03, 0xa1, 0x5e, 0xca, 0xe8, 0x82, 0x52, 0xb4, 0xaa, 0x6b, 0x7e, 0x24, 0xd4, 0xa1,
6071
+	0x1c, 0x09, 0x9e, 0xd8, 0x9c, 0x7f, 0xe5, 0xa0, 0x80, 0xc4, 0x8c, 0x41, 0xc1, 0x8d, 0x26, 0xba,
6072
+	0x5d, 0x6d, 0x4e, 0x32, 0xab, 0x41, 0x5e, 0x04, 0x2f, 0xe8, 0x0c, 0x9b, 0xa3, 0x88, 0x1a, 0xef,
6073
+	0xe5, 0xc8, 0x24, 0x1d, 0x45, 0xdc, 0x37, 0x8b, 0x45, 0x64, 0x72, 0x4d, 0x32, 0xbb, 0x07, 0x76,
6074
+	0x18, 0xc9, 0xab, 0xf9, 0x73, 0xdc, 0x5d, 0xcc, 0x74, 0x12, 0x2a, 0x7b, 0xc1, 0x0b, 0x5e, 0x09,
6075
+	0x8d, 0xc4, 0xb6, 0x01, 0xc4, 0x95, 0x8a, 0xdc, 0x03, 0x19, 0xab, 0xb8, 0x5e, 0xa2, 0x68, 0xa8,
6076
+	0x81, 0x51, 0xd1, 0x3f, 0xe6, 0x19, 0xab, 0xf3, 0x1f, 0x0b, 0x8a, 0x14, 0x24, 0xdb, 0xc2, 0x94,
6077
+	0x86, 0x33, 0x5d, 0x9d, 0x7c, 0x9b, 0x99, 0x94, 0x02, 0x15, 0x6f, 0x91, 0x51, 0x2c, 0xe4, 0x1a,
6078
+	0x54, 0x62, 0x31, 0x15, 0x9e, 0x92, 0x91, 0xe9, 0x9f, 0xc5, 0x1a, 0x5d, 0x1f, 0x61, 0x89, 0x75,
6079
+	0x34, 0x24, 0xb3, 0x1d, 0x28, 0x49, 0xaa, 0x0b, 0x05, 0xf4, 0x1d, 0xd5, 0x32, 0x10, 0x24, 0x8f,
6080
+	0x84, 0x3b, 0x92, 0xc1, 0x74, 0x4e, 0x61, 0x56, 0xf8, 0x62, 0xcd, 0x76, 0xc0, 0xa6, 0x4a, 0x9c,
6081
+	0xcc, 0x43, 0x51, 0x2f, 0x51, 0x05, 0x56, 0x16, 0x55, 0x42, 0x25, 0x4f, 0xed, 0x78, 0xf3, 0x3c,
6082
+	0xd7, 0x3b, 0x17, 0x83, 0x50, 0xd5, 0x6f, 0xa5, 0xf9, 0xea, 0x18, 0x1d, 0x5f, 0x58, 0x91, 0x36,
6083
+	0x16, 0x5e, 0x24, 0x14, 0x42, 0x6f, 0x13, 0x94, 0x68, 0x87, 0x89, 0x92, 0xa7, 0x76, 0xe6, 0x40,
6084
+	0x69, 0x38, 0x3c, 0x40, 0xe4, 0x9d, 0xf4, 0x65, 0xd0, 0x1a, 0x6e, 0x2c, 0x4e, 0x1f, 0x2a, 0xc9,
6085
+	0x31, 0x78, 0xcd, 0xfa, 0x5d, 0x73, 0x01, 0xad, 0x7e, 0x97, 0xed, 0x42, 0x39, 0x3e, 0x77, 0x23,
6086
+	0x3f, 0x98, 0x50, 0xee, 0x56, 0x5b, 0x37, 0x17, 0x5e, 0x0d, 0xb5, 0x1e, 0x99, 0x12, 0x8c, 0x23,
6087
+	0xc1, 0x5e, 0xb8, 0xf1, 0x09, 0x57, 0x0d, 0xf2, 0x33, 0x7f, 0x44, 0x3c, 0x2b, 0x1c, 0x45, 0xd4,
6088
+	0x4c, 0x7c, 0xdd, 0x4b, 0x2b, 0x1c, 0x45, 0x2c, 0xc8, 0xa5, 0x1c, 0x09, 0x4a, 0xfd, 0x0a, 0x27,
6089
+	0x19, 0x73, 0x2c, 0x43, 0xe5, 0xcb, 0xc0, 0x9d, 0x26, 0x39, 0x4e, 0xd6, 0xce, 0x34, 0x89, 0xef,
6090
+	0x27, 0x39, 0xed, 0x09, 0x94, 0xf4, 0xab, 0xca, 0x36, 0x21, 0x1f, 0x47, 0x9e, 0x79, 0xd9, 0x57,
6091
+	0x93, 0xe7, 0x56, 0x3f, 0xcc, 0x1c, 0x4d, 0x8b, 0xd6, 0xb2, 0xd2, 0xd6, 0x72, 0x38, 0x40, 0x0a,
6092
+	0xfb, 0x71, 0x5a, 0xd8, 0xf9, 0x7b, 0x0e, 0x2a, 0xc9, 0x40, 0xc0, 0xd7, 0xcd, 0x1f, 0x89, 0x40,
6093
+	0xf9, 0x63, 0x5f, 0x44, 0x26, 0x19, 0x19, 0x0d, 0xdb, 0x85, 0xa2, 0xab, 0x54, 0x94, 0x3c, 0x1a,
6094
+	0x3f, 0xcf, 0x4e, 0x93, 0xe6, 0x3e, 0x5a, 0x7a, 0x81, 0x8a, 0xe6, 0x5c, 0xa3, 0xd6, 0x1e, 0x03,
6095
+	0xa4, 0x4a, 0xcc, 0xdf, 0x85, 0x98, 0x1b, 0x56, 0x14, 0xd9, 0x2d, 0x28, 0xbe, 0x70, 0xa7, 0x33,
6096
+	0x61, 0x9c, 0xd2, 0x8b, 0xdf, 0x5b, 0x8f, 0x73, 0xce, 0xbf, 0x2d, 0x28, 0x9b, 0xe9, 0xc2, 0xee,
6097
+	0x43, 0x99, 0xa6, 0x8b, 0xf1, 0xe8, 0xf3, 0x91, 0x26, 0x10, 0xb6, 0xb7, 0x18, 0x9b, 0x19, 0x1f,
6098
+	0x0d, 0x95, 0x1e, 0x9f, 0xc6, 0xc7, 0x74, 0x88, 0xe6, 0x47, 0x62, 0x6c, 0xe6, 0x23, 0x95, 0xa2,
6099
+	0x2b, 0xc6, 0x7e, 0xe0, 0x63, 0xcd, 0x38, 0x9a, 0xd8, 0xfd, 0x24, 0xea, 0x02, 0x31, 0xde, 0xc9,
6100
+	0x32, 0x7e, 0x1a, 0x74, 0x1f, 0xaa, 0x99, 0x63, 0x3e, 0x13, 0xf5, 0x6f, 0xb2, 0x51, 0x9b, 0x23,
6101
+	0x89, 0x4e, 0x0f, 0xf7, 0x34, 0x0b, 0x3f, 0x20, 0x7f, 0x0f, 0x01, 0x52, 0xca, 0x2f, 0xef, 0x14,
6102
+	0xe7, 0x55, 0x1e, 0x60, 0x10, 0xe2, 0x73, 0x3e, 0x72, 0x69, 0x4a, 0x2c, 0xfb, 0x93, 0x40, 0x46,
6103
+	0xe2, 0x39, 0x3d, 0x1f, 0xb4, 0xbf, 0xc2, 0xab, 0x5a, 0x47, 0xb7, 0x98, 0xed, 0x43, 0x75, 0x24,
6104
+	0x62, 0x2f, 0xf2, 0xa9, 0xc9, 0x4d, 0xd2, 0x37, 0x30, 0xa6, 0x94, 0xa7, 0xd9, 0x4d, 0x11, 0x3a,
6105
+	0x57, 0xd9, 0x3d, 0xac, 0x05, 0xcb, 0xe2, 0x2a, 0x94, 0x91, 0x32, 0xa7, 0xe8, 0x8f, 0x90, 0x1b,
6106
+	0xfa, 0x73, 0x06, 0xf5, 0x74, 0x12, 0xaf, 0x8a, 0x74, 0xc1, 0x5c, 0x28, 0x78, 0x6e, 0xa8, 0x27,
6107
+	0x70, 0xb5, 0x55, 0xff, 0xe8, 0xbc, 0x8e, 0x1b, 0xea, 0xa4, 0xb5, 0x1f, 0x60, 0xac, 0xaf, 0xfe,
6108
+	0xbf, 0xb1, 0x93, 0x19, 0xbb, 0x97, 0xf2, 0x6c, 0xbe, 0x47, 0xfd, 0x72, 0xe1, 0xab, 0xbd, 0x99,
6109
+	0xf2, 0xa7, 0x7b, 0x6e, 0xe8, 0x23, 0x1d, 0x6e, 0xec, 0x77, 0x39, 0x51, 0xaf, 0x3d, 0x81, 0xda,
6110
+	0xc7, 0x7e, 0x7f, 0x4d, 0x0d, 0xd6, 0x1e, 0x81, 0xbd, 0xf0, 0xe3, 0xfb, 0x36, 0x56, 0xb2, 0xc5,
6111
+	0xbb, 0x0b, 0xd5, 0x4c, 0xdc, 0x08, 0x3c, 0x25, 0xa0, 0xce, 0xbe, 0x5e, 0x38, 0xaf, 0xf0, 0x0b,
6112
+	0x28, 0x99, 0x81, 0xbf, 0x02, 0x38, 0x57, 0x2a, 0x7c, 0x4e, 0x43, 0xd1, 0x1c, 0x62, 0xa3, 0x86,
6113
+	0x10, 0x6c, 0x03, 0xaa, 0xb8, 0x88, 0x8d, 0x5d, 0x7b, 0x4a, 0x3b, 0x62, 0x0d, 0xf8, 0x25, 0xd8,
6114
+	0xe3, 0xc5, 0x76, 0x3d, 0xcc, 0x2a, 0xe3, 0x64, 0xf7, 0x2f, 0xa0, 0x12, 0x48, 0x63, 0xd3, 0x33,
6115
+	0xba, 0x1c, 0x48, 0x32, 0x39, 0x3b, 0xf0, 0xb3, 0x4f, 0x3e, 0xd7, 0xd8, 0x1d, 0x28, 0x8d, 0xfd,
6116
+	0xa9, 0xa2, 0xeb, 0x8a, 0x63, 0xdf, 0xac, 0x9c, 0xff, 0xe6, 0x00, 0xd2, 0xab, 0x85, 0x19, 0xc1,
6117
+	0x7b, 0x87, 0x98, 0x65, 0x7d, 0xcf, 0xa6, 0x50, 0xb9, 0x34, 0x15, 0x34, 0x7d, 0xb4, 0xfe, 0xe1,
6118
+	0x75, 0x6c, 0x26, 0x05, 0xd6, 0xb5, 0x6d, 0x99, 0xda, 0x7e, 0xcd, 0x27, 0xd5, 0xe2, 0x84, 0xb5,
6119
+	0x67, 0xb0, 0xf2, 0x01, 0xdd, 0x17, 0xde, 0xd4, 0xb4, 0xcb, 0xb2, 0x25, 0xbb, 0x0f, 0x25, 0xfd,
6120
+	0xb9, 0x81, 0xef, 0x36, 0x4a, 0x86, 0x86, 0x64, 0x9a, 0x2d, 0xc7, 0xc9, 0xc7, 0x67, 0xff, 0x78,
6121
+	0x7b, 0x0b, 0xca, 0xe6, 0x33, 0x8a, 0xd9, 0x50, 0xfc, 0xf3, 0xd1, 0xb0, 0x77, 0x52, 0x5b, 0x62,
6122
+	0x15, 0x28, 0x1c, 0x0c, 0x86, 0x27, 0xb5, 0x1c, 0x4a, 0x47, 0x83, 0xa3, 0x5e, 0xcd, 0xda, 0xfe,
6123
+	0x03, 0xd8, 0x8b, 0x71, 0x8f, 0xea, 0x76, 0xff, 0xa8, 0x5b, 0x5b, 0x62, 0x00, 0xa5, 0x61, 0xaf,
6124
+	0xc3, 0x7b, 0x08, 0x2e, 0x43, 0x7e, 0x38, 0x3c, 0xa8, 0x59, 0x48, 0xd5, 0xd9, 0xef, 0x1c, 0xf4,
6125
+	0x6a, 0x79, 0x14, 0x4f, 0x0e, 0x8f, 0x9f, 0x0e, 0x6b, 0x85, 0xed, 0x87, 0x70, 0xe3, 0xa3, 0x71,
6126
+	0x4b, 0xbb, 0x0f, 0xf6, 0x79, 0x0f, 0x99, 0xaa, 0x50, 0x3e, 0xe6, 0xfd, 0xd3, 0xfd, 0x93, 0x5e,
6127
+	0x2d, 0x87, 0x86, 0x3f, 0x0d, 0x3a, 0xcf, 0x7a, 0xdd, 0x9a, 0xd5, 0x5e, 0x7f, 0x7d, 0xdd, 0xc8,
6128
+	0xbd, 0xb9, 0x6e, 0xe4, 0xde, 0x5e, 0x37, 0x72, 0xdf, 0x5c, 0x37, 0x72, 0x7f, 0x7b, 0xdf, 0x58,
6129
+	0x7a, 0xf3, 0xbe, 0xb1, 0xf4, 0xf6, 0x7d, 0x63, 0xe9, 0xac, 0x44, 0x7f, 0x55, 0x1e, 0x7c, 0x1b,
6130
+	0x00, 0x00, 0xff, 0xff, 0x26, 0x19, 0xc9, 0x11, 0xea, 0x0c, 0x00, 0x00,
6131 6131
 }
... ...
@@ -164,5 +164,5 @@ type CacheManager interface {
164 164
 	// Load pulls and returns the cached result
165 165
 	Load(ctx context.Context, rec *CacheRecord) (Result, error)
166 166
 	// Save saves a result based on a cache key
167
-	Save(key *CacheKey, s Result) (*ExportableCacheKey, error)
167
+	Save(key *CacheKey, s Result, createdAt time.Time) (*ExportableCacheKey, error)
168 168
 }
... ...
@@ -16,6 +16,7 @@ import (
16 16
 	"github.com/moby/buildkit/cache/metadata"
17 17
 	"github.com/moby/buildkit/client"
18 18
 	"github.com/moby/buildkit/identity"
19
+	"github.com/moby/buildkit/session"
19 20
 	"github.com/moby/buildkit/snapshot"
20 21
 	"github.com/moby/buildkit/source"
21 22
 	"github.com/moby/buildkit/util/progress/logs"
... ...
@@ -152,7 +153,7 @@ type gitSourceHandler struct {
152 152
 	cacheKey string
153 153
 }
154 154
 
155
-func (gs *gitSource) Resolve(ctx context.Context, id source.Identifier) (source.SourceInstance, error) {
155
+func (gs *gitSource) Resolve(ctx context.Context, id source.Identifier, _ *session.Manager) (source.SourceInstance, error) {
156 156
 	gitIdentifier, ok := id.(*source.GitIdentifier)
157 157
 	if !ok {
158 158
 		return nil, errors.Errorf("invalid git identifier %v", id)
... ...
@@ -248,6 +249,9 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context) (out cache.ImmutableRe
248 248
 	}
249 249
 
250 250
 	if doFetch {
251
+		// make sure no old lock files have leaked
252
+		os.RemoveAll(filepath.Join(gitDir, "shallow.lock"))
253
+
251 254
 		args := []string{"fetch"}
252 255
 		if !isCommitSHA(ref) { // TODO: find a branch from ls-remote?
253 256
 			args = append(args, "--depth=1", "--no-tags")
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"context"
7 7
 	"os/exec"
8 8
 	"syscall"
9
+	"time"
9 10
 )
10 11
 
11 12
 func runProcessGroup(ctx context.Context, cmd *exec.Cmd) error {
... ...
@@ -17,7 +18,14 @@ func runProcessGroup(ctx context.Context, cmd *exec.Cmd) error {
17 17
 	go func() {
18 18
 		select {
19 19
 		case <-ctx.Done():
20
-			syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
20
+			syscall.Kill(-cmd.Process.Pid, syscall.SIGTERM)
21
+			go func() {
22
+				select {
23
+				case <-waitDone:
24
+				case <-time.After(10 * time.Second):
25
+					syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
26
+				}
27
+			}()
21 28
 		case <-waitDone:
22 29
 		}
23 30
 	}()
... ...
@@ -18,6 +18,7 @@ import (
18 18
 	"github.com/docker/docker/pkg/locker"
19 19
 	"github.com/moby/buildkit/cache"
20 20
 	"github.com/moby/buildkit/cache/metadata"
21
+	"github.com/moby/buildkit/session"
21 22
 	"github.com/moby/buildkit/snapshot"
22 23
 	"github.com/moby/buildkit/source"
23 24
 	"github.com/moby/buildkit/util/tracing"
... ...
@@ -66,7 +67,7 @@ type httpSourceHandler struct {
66 66
 	cacheKey digest.Digest
67 67
 }
68 68
 
69
-func (hs *httpSource) Resolve(ctx context.Context, id source.Identifier) (source.SourceInstance, error) {
69
+func (hs *httpSource) Resolve(ctx context.Context, id source.Identifier, _ *session.Manager) (source.SourceInstance, error) {
70 70
 	httpIdentifier, ok := id.(*source.HttpIdentifier)
71 71
 	if !ok {
72 72
 		return nil, errors.Errorf("invalid http identifier %v", id)
... ...
@@ -146,11 +147,42 @@ func (hs *httpSourceHandler) CacheKey(ctx context.Context, index int) (string, b
146 146
 			if etag := getETag(si); etag != "" {
147 147
 				if dgst := getChecksum(si); dgst != "" {
148 148
 					m[etag] = si
149
-					req.Header.Add("If-None-Match", etag)
150 149
 				}
151 150
 			}
152 151
 			// }
153 152
 		}
153
+		if len(m) > 0 {
154
+			etags := make([]string, 0, len(m))
155
+			for t := range m {
156
+				etags = append(etags, t)
157
+			}
158
+			req.Header.Add("If-None-Match", strings.Join(etags, ", "))
159
+		}
160
+	}
161
+
162
+	// Some servers seem to have trouble supporting If-None-Match properly even
163
+	// though they return ETag-s. So first, optionally try a HEAD request with
164
+	// manual ETag value comparison.
165
+	if len(m) > 0 {
166
+		req.Method = "HEAD"
167
+		resp, err := hs.client.Do(req)
168
+		if err == nil {
169
+			if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotModified {
170
+				respETag := resp.Header.Get("ETag")
171
+				si, ok := m[respETag]
172
+				if ok {
173
+					hs.refID = si.ID()
174
+					dgst := getChecksum(si)
175
+					if dgst != "" {
176
+						modTime := getModTime(si)
177
+						resp.Body.Close()
178
+						return hs.formatCacheKey(getFileName(hs.src.URL, hs.src.Filename, resp), dgst, modTime).String(), true, nil
179
+					}
180
+				}
181
+			}
182
+			resp.Body.Close()
183
+		}
184
+		req.Method = "GET"
154 185
 	}
155 186
 
156 187
 	resp, err := hs.client.Do(req)
... ...
@@ -28,14 +28,12 @@ import (
28 28
 const keySharedKey = "local.sharedKey"
29 29
 
30 30
 type Opt struct {
31
-	SessionManager *session.Manager
32
-	CacheAccessor  cache.Accessor
33
-	MetadataStore  *metadata.Store
31
+	CacheAccessor cache.Accessor
32
+	MetadataStore *metadata.Store
34 33
 }
35 34
 
36 35
 func NewSource(opt Opt) (source.Source, error) {
37 36
 	ls := &localSource{
38
-		sm: opt.SessionManager,
39 37
 		cm: opt.CacheAccessor,
40 38
 		md: opt.MetadataStore,
41 39
 	}
... ...
@@ -43,7 +41,6 @@ func NewSource(opt Opt) (source.Source, error) {
43 43
 }
44 44
 
45 45
 type localSource struct {
46
-	sm *session.Manager
47 46
 	cm cache.Accessor
48 47
 	md *metadata.Store
49 48
 }
... ...
@@ -52,7 +49,7 @@ func (ls *localSource) ID() string {
52 52
 	return source.LocalScheme
53 53
 }
54 54
 
55
-func (ls *localSource) Resolve(ctx context.Context, id source.Identifier) (source.SourceInstance, error) {
55
+func (ls *localSource) Resolve(ctx context.Context, id source.Identifier, sm *session.Manager) (source.SourceInstance, error) {
56 56
 	localIdentifier, ok := id.(*source.LocalIdentifier)
57 57
 	if !ok {
58 58
 		return nil, errors.Errorf("invalid local identifier %v", id)
... ...
@@ -60,12 +57,14 @@ func (ls *localSource) Resolve(ctx context.Context, id source.Identifier) (sourc
60 60
 
61 61
 	return &localSourceHandler{
62 62
 		src:         *localIdentifier,
63
+		sm:          sm,
63 64
 		localSource: ls,
64 65
 	}, nil
65 66
 }
66 67
 
67 68
 type localSourceHandler struct {
68 69
 	src source.LocalIdentifier
70
+	sm  *session.Manager
69 71
 	*localSource
70 72
 }
71 73
 
... ...
@@ -5,12 +5,13 @@ import (
5 5
 	"sync"
6 6
 
7 7
 	"github.com/moby/buildkit/cache"
8
+	"github.com/moby/buildkit/session"
8 9
 	"github.com/pkg/errors"
9 10
 )
10 11
 
11 12
 type Source interface {
12 13
 	ID() string
13
-	Resolve(ctx context.Context, id Identifier) (SourceInstance, error)
14
+	Resolve(ctx context.Context, id Identifier, sm *session.Manager) (SourceInstance, error)
14 15
 }
15 16
 
16 17
 type SourceInstance interface {
... ...
@@ -35,7 +36,7 @@ func (sm *Manager) Register(src Source) {
35 35
 	sm.mu.Unlock()
36 36
 }
37 37
 
38
-func (sm *Manager) Resolve(ctx context.Context, id Identifier) (SourceInstance, error) {
38
+func (sm *Manager) Resolve(ctx context.Context, id Identifier, sessM *session.Manager) (SourceInstance, error) {
39 39
 	sm.mu.Lock()
40 40
 	src, ok := sm.sources[id.ID()]
41 41
 	sm.mu.Unlock()
... ...
@@ -44,5 +45,5 @@ func (sm *Manager) Resolve(ctx context.Context, id Identifier) (SourceInstance,
44 44
 		return nil, errors.Errorf("no handler for %s", id.ID())
45 45
 	}
46 46
 
47
-	return src.Resolve(ctx, id)
47
+	return src.Resolve(ctx, id, sessM)
48 48
 }
... ...
@@ -1,15 +1,6 @@
1 1
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
2 2
 // source: caps.proto
3 3
 
4
-/*
5
-	Package moby_buildkit_v1_apicaps is a generated protocol buffer package.
6
-
7
-	It is generated from these files:
8
-		caps.proto
9
-
10
-	It has these top-level messages:
11
-		APICap
12
-*/
13 4
 package moby_buildkit_v1_apicaps
14 5
 
15 6
 import proto "github.com/gogo/protobuf/proto"
... ...
@@ -32,18 +23,49 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
32 32
 
33 33
 // APICap defines a capability supported by the service
34 34
 type APICap struct {
35
-	ID                  string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
36
-	Enabled             bool   `protobuf:"varint,2,opt,name=Enabled,proto3" json:"Enabled,omitempty"`
37
-	Deprecated          bool   `protobuf:"varint,3,opt,name=Deprecated,proto3" json:"Deprecated,omitempty"`
38
-	DisabledReason      string `protobuf:"bytes,4,opt,name=DisabledReason,proto3" json:"DisabledReason,omitempty"`
39
-	DisabledReasonMsg   string `protobuf:"bytes,5,opt,name=DisabledReasonMsg,proto3" json:"DisabledReasonMsg,omitempty"`
40
-	DisabledAlternative string `protobuf:"bytes,6,opt,name=DisabledAlternative,proto3" json:"DisabledAlternative,omitempty"`
35
+	ID                   string   `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
36
+	Enabled              bool     `protobuf:"varint,2,opt,name=Enabled,proto3" json:"Enabled,omitempty"`
37
+	Deprecated           bool     `protobuf:"varint,3,opt,name=Deprecated,proto3" json:"Deprecated,omitempty"`
38
+	DisabledReason       string   `protobuf:"bytes,4,opt,name=DisabledReason,proto3" json:"DisabledReason,omitempty"`
39
+	DisabledReasonMsg    string   `protobuf:"bytes,5,opt,name=DisabledReasonMsg,proto3" json:"DisabledReasonMsg,omitempty"`
40
+	DisabledAlternative  string   `protobuf:"bytes,6,opt,name=DisabledAlternative,proto3" json:"DisabledAlternative,omitempty"`
41
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
42
+	XXX_unrecognized     []byte   `json:"-"`
43
+	XXX_sizecache        int32    `json:"-"`
44
+}
45
+
46
+func (m *APICap) Reset()         { *m = APICap{} }
47
+func (m *APICap) String() string { return proto.CompactTextString(m) }
48
+func (*APICap) ProtoMessage()    {}
49
+func (*APICap) Descriptor() ([]byte, []int) {
50
+	return fileDescriptor_caps_04e1bcd232e9a565, []int{0}
51
+}
52
+func (m *APICap) XXX_Unmarshal(b []byte) error {
53
+	return m.Unmarshal(b)
54
+}
55
+func (m *APICap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
56
+	if deterministic {
57
+		return xxx_messageInfo_APICap.Marshal(b, m, deterministic)
58
+	} else {
59
+		b = b[:cap(b)]
60
+		n, err := m.MarshalTo(b)
61
+		if err != nil {
62
+			return nil, err
63
+		}
64
+		return b[:n], nil
65
+	}
66
+}
67
+func (dst *APICap) XXX_Merge(src proto.Message) {
68
+	xxx_messageInfo_APICap.Merge(dst, src)
69
+}
70
+func (m *APICap) XXX_Size() int {
71
+	return m.Size()
72
+}
73
+func (m *APICap) XXX_DiscardUnknown() {
74
+	xxx_messageInfo_APICap.DiscardUnknown(m)
41 75
 }
42 76
 
43
-func (m *APICap) Reset()                    { *m = APICap{} }
44
-func (m *APICap) String() string            { return proto.CompactTextString(m) }
45
-func (*APICap) ProtoMessage()               {}
46
-func (*APICap) Descriptor() ([]byte, []int) { return fileDescriptorCaps, []int{0} }
77
+var xxx_messageInfo_APICap proto.InternalMessageInfo
47 78
 
48 79
 func (m *APICap) GetID() string {
49 80
 	if m != nil {
... ...
@@ -149,6 +171,9 @@ func (m *APICap) MarshalTo(dAtA []byte) (int, error) {
149 149
 		i = encodeVarintCaps(dAtA, i, uint64(len(m.DisabledAlternative)))
150 150
 		i += copy(dAtA[i:], m.DisabledAlternative)
151 151
 	}
152
+	if m.XXX_unrecognized != nil {
153
+		i += copy(dAtA[i:], m.XXX_unrecognized)
154
+	}
152 155
 	return i, nil
153 156
 }
154 157
 
... ...
@@ -162,6 +187,9 @@ func encodeVarintCaps(dAtA []byte, offset int, v uint64) int {
162 162
 	return offset + 1
163 163
 }
164 164
 func (m *APICap) Size() (n int) {
165
+	if m == nil {
166
+		return 0
167
+	}
165 168
 	var l int
166 169
 	_ = l
167 170
 	l = len(m.ID)
... ...
@@ -186,6 +214,9 @@ func (m *APICap) Size() (n int) {
186 186
 	if l > 0 {
187 187
 		n += 1 + l + sovCaps(uint64(l))
188 188
 	}
189
+	if m.XXX_unrecognized != nil {
190
+		n += len(m.XXX_unrecognized)
191
+	}
189 192
 	return n
190 193
 }
191 194
 
... ...
@@ -399,6 +430,7 @@ func (m *APICap) Unmarshal(dAtA []byte) error {
399 399
 			if (iNdEx + skippy) > l {
400 400
 				return io.ErrUnexpectedEOF
401 401
 			}
402
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
402 403
 			iNdEx += skippy
403 404
 		}
404 405
 	}
... ...
@@ -513,9 +545,9 @@ var (
513 513
 	ErrIntOverflowCaps   = fmt.Errorf("proto: integer overflow")
514 514
 )
515 515
 
516
-func init() { proto.RegisterFile("caps.proto", fileDescriptorCaps) }
516
+func init() { proto.RegisterFile("caps.proto", fileDescriptor_caps_04e1bcd232e9a565) }
517 517
 
518
-var fileDescriptorCaps = []byte{
518
+var fileDescriptor_caps_04e1bcd232e9a565 = []byte{
519 519
 	// 236 bytes of a gzipped FileDescriptorProto
520 520
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x4e, 0x2c, 0x28,
521 521
 	0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0xc8, 0xcd, 0x4f, 0xaa, 0xd4, 0x4b, 0x2a, 0xcd,
... ...
@@ -67,7 +67,7 @@ func CopyChain(ctx context.Context, ingester content.Ingester, provider content.
67 67
 		remotes.FetchHandler(ingester, &localFetcher{provider}),
68 68
 	}
69 69
 
70
-	if err := images.Dispatch(ctx, images.Handlers(handlers...), desc); err != nil {
70
+	if err := images.Dispatch(ctx, images.Handlers(handlers...), nil, desc); err != nil {
71 71
 		return errors.WithStack(err)
72 72
 	}
73 73
 
... ...
@@ -66,7 +66,7 @@ func Config(ctx context.Context, str string, resolver remotes.Resolver, cache Co
66 66
 		remotes.FetchHandler(cache, fetcher),
67 67
 		childrenConfigHandler(cache, platform),
68 68
 	}
69
-	if err := images.Dispatch(ctx, images.Handlers(handlers...), desc); err != nil {
69
+	if err := images.Dispatch(ctx, images.Handlers(handlers...), nil, desc); err != nil {
70 70
 		return "", nil, err
71 71
 	}
72 72
 	config, err := images.Config(ctx, cache, desc, platform)
... ...
@@ -135,17 +135,21 @@ func childrenConfigHandler(provider content.Provider, platform platforms.MatchCo
135 135
 func DetectManifestMediaType(ra content.ReaderAt) (string, error) {
136 136
 	// TODO: schema1
137 137
 
138
-	p := make([]byte, ra.Size())
139
-	if _, err := ra.ReadAt(p, 0); err != nil {
138
+	dt := make([]byte, ra.Size())
139
+	if _, err := ra.ReadAt(dt, 0); err != nil {
140 140
 		return "", err
141 141
 	}
142 142
 
143
+	return DetectManifestBlobMediaType(dt)
144
+}
145
+
146
+func DetectManifestBlobMediaType(dt []byte) (string, error) {
143 147
 	var mfst struct {
144 148
 		MediaType string          `json:"mediaType"`
145 149
 		Config    json.RawMessage `json:"config"`
146 150
 	}
147 151
 
148
-	if err := json.Unmarshal(p, &mfst); err != nil {
152
+	if err := json.Unmarshal(dt, &mfst); err != nil {
149 153
 		return "", err
150 154
 	}
151 155
 
152 156
deleted file mode 100644
... ...
@@ -1,69 +0,0 @@
1
-github.com/pkg/errors v0.8.0
2
-go.etcd.io/bbolt v1.3.1-etcd.8
3
-
4
-github.com/stretchr/testify v1.1.4
5
-github.com/davecgh/go-spew v1.1.0
6
-github.com/pmezard/go-difflib v1.0.0
7
-golang.org/x/sys 1b2967e3c290b7c545b3db0deeda16e9be4f98a2
8
-
9
-github.com/containerd/containerd 47b328aab79146a9e81e37704db60e7e04a09256
10
-github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
11
-golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
12
-github.com/sirupsen/logrus v1.0.3
13
-google.golang.org/grpc v1.12.0
14
-github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
15
-golang.org/x/net 0ed95abb35c445290478a5348a7b38bb154135fd
16
-github.com/gogo/protobuf v1.0.0
17
-github.com/gogo/googleapis b23578765ee54ff6bceff57f397d833bf4ca6869
18
-github.com/golang/protobuf v1.1.0
19
-github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
20
-github.com/opencontainers/image-spec v1.0.1
21
-github.com/opencontainers/runc 96ec2177ae841256168fcf76954f7177af9446eb
22
-github.com/Microsoft/go-winio v0.4.11
23
-github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
24
-github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d
25
-github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3
26
-github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
27
-google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
28
-golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
29
-github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
30
-github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
31
-github.com/Microsoft/hcsshim v0.7.9
32
-golang.org/x/crypto 0709b304e793a5edb4a2c0145f281ecdc20838a4
33
-github.com/containerd/cri f913714917d2456d7e65a0be84962b1ce8acb487 # release/1.2 branch
34
-
35
-github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
36
-github.com/morikuni/aec 39771216ff4c63d11f5e604076f9c45e8be1067b
37
-github.com/docker/go-units v0.3.1
38
-github.com/google/shlex 6f45313302b9c56850fc17f99e40caebce98c716
39
-golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631
40
-
41
-github.com/docker/docker 71cd53e4a197b303c6ba086bd584ffd67a884281
42
-github.com/pkg/profile 5b67d428864e92711fcbd2f8629456121a56d91f
43
-
44
-github.com/tonistiigi/fsutil 2862f6bc5ac9b97124e552a5c108230b38a1b0ca
45
-github.com/hashicorp/go-immutable-radix 826af9ccf0feeee615d546d69b11f8e98da8c8f1 https://github.com/tonistiigi/go-immutable-radix
46
-github.com/hashicorp/golang-lru a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4
47
-github.com/mitchellh/hashstructure 2bca23e0e452137f789efbc8610126fd8b94f73b
48
-github.com/docker/go-connections 3ede32e2033de7505e6500d6c868c2b9ed9f169d
49
-github.com/docker/distribution 30578ca32960a4d368bf6db67b0a33c2a1f3dc6f
50
-
51
-github.com/tonistiigi/units 6950e57a87eaf136bbe44ef2ec8e75b9e3569de2
52
-github.com/docker/cli 99576756eb3303b7af8102c502f21a912e3c1af6 https://github.com/tonistiigi/docker-cli.git
53
-github.com/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1
54
-github.com/docker/libnetwork 36d3bed0e9f4b3c8c66df9bd45278bb90b33e911
55
-github.com/BurntSushi/toml 3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005
56
-github.com/ishidawataru/sctp 07191f837fedd2f13d1ec7b5f885f0f3ec54b1cb
57
-
58
-github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
59
-github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7
60
-github.com/uber/jaeger-client-go e02c85f9069ea625a96fc4e1afb5e9ac6c569a6d
61
-github.com/apache/thrift b2a4d4ae21c789b689dd162deb819665567f481c
62
-github.com/uber/jaeger-lib c48167d9cae5887393dd5e61efd06a4a48b7fbb3
63
-github.com/codahale/hdrhistogram f8ad88b59a584afeee9d334eff879b104439117b
64
-
65
-github.com/opentracing-contrib/go-stdlib b1a47cfbdd7543e70e9ef3e73d0802ad306cc1cc
66
-
67
-# used by dockerfile tests
68
-gotest.tools v2.1.0
69
-github.com/google/go-cmp v0.2.0
... ...
@@ -20,7 +20,7 @@ type cacheResultStorage struct {
20 20
 	wc *Controller
21 21
 }
22 22
 
23
-func (s *cacheResultStorage) Save(res solver.Result) (solver.CacheResult, error) {
23
+func (s *cacheResultStorage) Save(res solver.Result, createdAt time.Time) (solver.CacheResult, error) {
24 24
 	ref, ok := res.Sys().(*WorkerRef)
25 25
 	if !ok {
26 26
 		return solver.CacheResult{}, errors.Errorf("invalid result: %T", res.Sys())
... ...
@@ -33,7 +33,7 @@ func (s *cacheResultStorage) Save(res solver.Result) (solver.CacheResult, error)
33 33
 			ref.ImmutableRef.Metadata().Commit()
34 34
 		}
35 35
 	}
36
-	return solver.CacheResult{ID: ref.ID(), CreatedAt: time.Now()}, nil
36
+	return solver.CacheResult{ID: ref.ID(), CreatedAt: createdAt}, nil
37 37
 }
38 38
 func (s *cacheResultStorage) Load(ctx context.Context, res solver.CacheResult) (solver.Result, error) {
39 39
 	return s.load(res.ID, false)
... ...
@@ -10,6 +10,7 @@ import (
10 10
 	"github.com/moby/buildkit/exporter"
11 11
 	"github.com/moby/buildkit/frontend"
12 12
 	gw "github.com/moby/buildkit/frontend/gateway/client"
13
+	"github.com/moby/buildkit/session"
13 14
 	"github.com/moby/buildkit/solver"
14 15
 	digest "github.com/opencontainers/go-digest"
15 16
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
... ...
@@ -23,12 +24,12 @@ type Worker interface {
23 23
 	GCPolicy() []client.PruneInfo
24 24
 	LoadRef(id string, hidden bool) (cache.ImmutableRef, error)
25 25
 	// ResolveOp resolves Vertex.Sys() to Op implementation.
26
-	ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge) (solver.Op, error)
27
-	ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt) (digest.Digest, []byte, error)
26
+	ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge, sm *session.Manager) (solver.Op, error)
27
+	ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt, sm *session.Manager) (digest.Digest, []byte, error)
28 28
 	// Exec is similar to executor.Exec but without []mount.Mount
29 29
 	Exec(ctx context.Context, meta executor.Meta, rootFS cache.ImmutableRef, stdin io.ReadCloser, stdout, stderr io.WriteCloser) error
30 30
 	DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*client.UsageInfo, error)
31
-	Exporter(name string) (exporter.Exporter, error)
31
+	Exporter(name string, sm *session.Manager) (exporter.Exporter, error)
32 32
 	Prune(ctx context.Context, ch chan client.UsageInfo, opt ...client.PruneInfo) error
33 33
 	GetRemote(ctx context.Context, ref cache.ImmutableRef, createIfNeeded bool) (*solver.Remote, error)
34 34
 	FromRemote(ctx context.Context, remote *solver.Remote) (cache.ImmutableRef, error)
... ...
@@ -92,7 +92,13 @@ func (w *dynamicWalker) fill(ctx context.Context, pathC chan<- *currentPath) err
92 92
 			if !ok {
93 93
 				return nil
94 94
 			}
95
-			pathC <- p
95
+			select {
96
+			case pathC <- p:
97
+			case <-ctx.Done():
98
+				w.err = ctx.Err()
99
+				close(w.closeCh)
100
+				return ctx.Err()
101
+			}
96 102
 		case <-ctx.Done():
97 103
 			w.err = ctx.Err()
98 104
 			close(w.closeCh)