Browse code

vendor: update buildkit to df35e9818

Update to new buildkit and fix upgrade bugs

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

Tonis Tiigi authored on 2020/06/15 14:28:06
Showing 85 changed files
... ...
@@ -395,7 +395,7 @@ func (s *snapshotter) View(ctx context.Context, key, parent string, opts ...snap
395 395
 }
396 396
 
397 397
 func (s *snapshotter) Walk(context.Context, snapshots.WalkFunc, ...string) error {
398
-	return errors.Errorf("not-implemented")
398
+	return nil
399 399
 }
400 400
 
401 401
 func (s *snapshotter) Update(ctx context.Context, info snapshots.Info, fieldpaths ...string) (snapshots.Info, error) {
... ...
@@ -86,7 +86,11 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
86 86
 		return nil, err
87 87
 	}
88 88
 
89
-	md, err := metadata.NewStore(filepath.Join(root, "metadata.db"))
89
+	if err := cache.MigrateV2(context.Background(), filepath.Join(root, "metadata.db"), filepath.Join(root, "metadata_v2.db"), store, snapshotter, lm); err != nil {
90
+		return nil, err
91
+	}
92
+
93
+	md, err := metadata.NewStore(filepath.Join(root, "metadata_v2.db"))
90 94
 	if err != nil {
91 95
 		return nil, err
92 96
 	}
... ...
@@ -194,7 +194,8 @@ func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*buil
194 194
 
195 195
 	stages, metaArgs, err := instructions.Parse(dockerfile.AST)
196 196
 	if err != nil {
197
-		if instructions.IsUnknownInstruction(err) {
197
+		var uiErr *instructions.UnknownInstruction
198
+		if errors.As(err, &uiErr) {
198 199
 			buildsFailed.WithValues(metricsUnknownInstructionError).Inc()
199 200
 		}
200 201
 		return nil, errdefs.InvalidParameter(err)
... ...
@@ -205,7 +205,8 @@ func dispatchTriggeredOnBuild(d dispatchRequest, triggers []string) error {
205 205
 		}
206 206
 		cmd, err := instructions.ParseCommand(ast.AST.Children[0])
207 207
 		if err != nil {
208
-			if instructions.IsUnknownInstruction(err) {
208
+			var uiErr *instructions.UnknownInstruction
209
+			if errors.As(err, &uiErr) {
209 210
 				buildsFailed.WithValues(metricsUnknownInstructionError).Inc()
210 211
 			}
211 212
 			return err
... ...
@@ -6103,7 +6103,7 @@ func (s *DockerSuite) TestBuildLineErrorOnBuild(c *testing.T) {
6103 6103
   ONBUILD
6104 6104
   `)).Assert(c, icmd.Expected{
6105 6105
 		ExitCode: 1,
6106
-		Err:      "Dockerfile parse error line 2: ONBUILD requires at least one argument",
6106
+		Err:      "parse error line 2: ONBUILD requires at least one argument",
6107 6107
 	})
6108 6108
 }
6109 6109
 
... ...
@@ -6117,7 +6117,7 @@ func (s *DockerSuite) TestBuildLineErrorUnknownInstruction(c *testing.T) {
6117 6117
   ERROR
6118 6118
   `)).Assert(c, icmd.Expected{
6119 6119
 		ExitCode: 1,
6120
-		Err:      "Dockerfile parse error line 3: unknown instruction: NOINSTRUCTION",
6120
+		Err:      "parse error line 3: unknown instruction: NOINSTRUCTION",
6121 6121
 	})
6122 6122
 }
6123 6123
 
... ...
@@ -6134,7 +6134,7 @@ func (s *DockerSuite) TestBuildLineErrorWithEmptyLines(c *testing.T) {
6134 6134
   CMD ["/bin/init"]
6135 6135
   `)).Assert(c, icmd.Expected{
6136 6136
 		ExitCode: 1,
6137
-		Err:      "Dockerfile parse error line 6: unknown instruction: NOINSTRUCTION",
6137
+		Err:      "parse error line 6: unknown instruction: NOINSTRUCTION",
6138 6138
 	})
6139 6139
 }
6140 6140
 
... ...
@@ -6148,7 +6148,7 @@ func (s *DockerSuite) TestBuildLineErrorWithComments(c *testing.T) {
6148 6148
   NOINSTRUCTION echo ba
6149 6149
   `)).Assert(c, icmd.Expected{
6150 6150
 		ExitCode: 1,
6151
-		Err:      "Dockerfile parse error line 5: unknown instruction: NOINSTRUCTION",
6151
+		Err:      "parse error line 5: unknown instruction: NOINSTRUCTION",
6152 6152
 	})
6153 6153
 }
6154 6154
 
... ...
@@ -28,7 +28,7 @@ github.com/imdario/mergo                            1afb36080aec31e0d1528973ebe6
28 28
 golang.org/x/sync                                   cd5d95a43a6e21273425c7ae415d3df9ea832eeb
29 29
 
30 30
 # buildkit
31
-github.com/moby/buildkit                            ae7ff7174f73bcb4df89b97e1623b3fb0bfb0a0c
31
+github.com/moby/buildkit                            df35e9818d1f9066e616e03f4b8d727c97562e5b
32 32
 github.com/tonistiigi/fsutil                        c2c7d7b0e1441705cd802e5699c0a10b1dfe39fd
33 33
 github.com/grpc-ecosystem/grpc-opentracing          8e809c8a86450a29b90dcc9efbf062d0fe6d9746
34 34
 github.com/opentracing/opentracing-go               1361b9cd60be79c4c3a7fa9841b3c132e40066a7
... ...
@@ -36,6 +36,7 @@ github.com/google/shlex                             e7afc7fbc51079733e9468cdfd1e
36 36
 github.com/opentracing-contrib/go-stdlib            b1a47cfbdd7543e70e9ef3e73d0802ad306cc1cc
37 37
 github.com/mitchellh/hashstructure                  2bca23e0e452137f789efbc8610126fd8b94f73b
38 38
 github.com/gofrs/flock                              392e7fae8f1b0bdbd67dad7237d23f618feb6dbb # v0.7.1
39
+github.com/grpc-ecosystem/go-grpc-middleware        3c51f7f332123e8be5a157c0802a228ac85bf9db # v1.2.0
39 40
 
40 41
 # libnetwork
41 42
 
42 43
new file mode 100644
... ...
@@ -0,0 +1,201 @@
0
+                 Apache License
1
+                           Version 2.0, January 2004
2
+                        http://www.apache.org/licenses/
3
+
4
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
5
+
6
+   1. Definitions.
7
+
8
+      "License" shall mean the terms and conditions for use, reproduction,
9
+      and distribution as defined by Sections 1 through 9 of this document.
10
+
11
+      "Licensor" shall mean the copyright owner or entity authorized by
12
+      the copyright owner that is granting the License.
13
+
14
+      "Legal Entity" shall mean the union of the acting entity and all
15
+      other entities that control, are controlled by, or are under common
16
+      control with that entity. For the purposes of this definition,
17
+      "control" means (i) the power, direct or indirect, to cause the
18
+      direction or management of such entity, whether by contract or
19
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
20
+      outstanding shares, or (iii) beneficial ownership of such entity.
21
+
22
+      "You" (or "Your") shall mean an individual or Legal Entity
23
+      exercising permissions granted by this License.
24
+
25
+      "Source" form shall mean the preferred form for making modifications,
26
+      including but not limited to software source code, documentation
27
+      source, and configuration files.
28
+
29
+      "Object" form shall mean any form resulting from mechanical
30
+      transformation or translation of a Source form, including but
31
+      not limited to compiled object code, generated documentation,
32
+      and conversions to other media types.
33
+
34
+      "Work" shall mean the work of authorship, whether in Source or
35
+      Object form, made available under the License, as indicated by a
36
+      copyright notice that is included in or attached to the work
37
+      (an example is provided in the Appendix below).
38
+
39
+      "Derivative Works" shall mean any work, whether in Source or Object
40
+      form, that is based on (or derived from) the Work and for which the
41
+      editorial revisions, annotations, elaborations, or other modifications
42
+      represent, as a whole, an original work of authorship. For the purposes
43
+      of this License, Derivative Works shall not include works that remain
44
+      separable from, or merely link (or bind by name) to the interfaces of,
45
+      the Work and Derivative Works thereof.
46
+
47
+      "Contribution" shall mean any work of authorship, including
48
+      the original version of the Work and any modifications or additions
49
+      to that Work or Derivative Works thereof, that is intentionally
50
+      submitted to Licensor for inclusion in the Work by the copyright owner
51
+      or by an individual or Legal Entity authorized to submit on behalf of
52
+      the copyright owner. For the purposes of this definition, "submitted"
53
+      means any form of electronic, verbal, or written communication sent
54
+      to the Licensor or its representatives, including but not limited to
55
+      communication on electronic mailing lists, source code control systems,
56
+      and issue tracking systems that are managed by, or on behalf of, the
57
+      Licensor for the purpose of discussing and improving the Work, but
58
+      excluding communication that is conspicuously marked or otherwise
59
+      designated in writing by the copyright owner as "Not a Contribution."
60
+
61
+      "Contributor" shall mean Licensor and any individual or Legal Entity
62
+      on behalf of whom a Contribution has been received by Licensor and
63
+      subsequently incorporated within the Work.
64
+
65
+   2. Grant of Copyright License. Subject to the terms and conditions of
66
+      this License, each Contributor hereby grants to You a perpetual,
67
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
68
+      copyright license to reproduce, prepare Derivative Works of,
69
+      publicly display, publicly perform, sublicense, and distribute the
70
+      Work and such Derivative Works in Source or Object form.
71
+
72
+   3. Grant of Patent License. Subject to the terms and conditions of
73
+      this License, each Contributor hereby grants to You a perpetual,
74
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
75
+      (except as stated in this section) patent license to make, have made,
76
+      use, offer to sell, sell, import, and otherwise transfer the Work,
77
+      where such license applies only to those patent claims licensable
78
+      by such Contributor that are necessarily infringed by their
79
+      Contribution(s) alone or by combination of their Contribution(s)
80
+      with the Work to which such Contribution(s) was submitted. If You
81
+      institute patent litigation against any entity (including a
82
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
83
+      or a Contribution incorporated within the Work constitutes direct
84
+      or contributory patent infringement, then any patent licenses
85
+      granted to You under this License for that Work shall terminate
86
+      as of the date such litigation is filed.
87
+
88
+   4. Redistribution. You may reproduce and distribute copies of the
89
+      Work or Derivative Works thereof in any medium, with or without
90
+      modifications, and in Source or Object form, provided that You
91
+      meet the following conditions:
92
+
93
+      (a) You must give any other recipients of the Work or
94
+          Derivative Works a copy of this License; and
95
+
96
+      (b) You must cause any modified files to carry prominent notices
97
+          stating that You changed the files; and
98
+
99
+      (c) You must retain, in the Source form of any Derivative Works
100
+          that You distribute, all copyright, patent, trademark, and
101
+          attribution notices from the Source form of the Work,
102
+          excluding those notices that do not pertain to any part of
103
+          the Derivative Works; and
104
+
105
+      (d) If the Work includes a "NOTICE" text file as part of its
106
+          distribution, then any Derivative Works that You distribute must
107
+          include a readable copy of the attribution notices contained
108
+          within such NOTICE file, excluding those notices that do not
109
+          pertain to any part of the Derivative Works, in at least one
110
+          of the following places: within a NOTICE text file distributed
111
+          as part of the Derivative Works; within the Source form or
112
+          documentation, if provided along with the Derivative Works; or,
113
+          within a display generated by the Derivative Works, if and
114
+          wherever such third-party notices normally appear. The contents
115
+          of the NOTICE file are for informational purposes only and
116
+          do not modify the License. You may add Your own attribution
117
+          notices within Derivative Works that You distribute, alongside
118
+          or as an addendum to the NOTICE text from the Work, provided
119
+          that such additional attribution notices cannot be construed
120
+          as modifying the License.
121
+
122
+      You may add Your own copyright statement to Your modifications and
123
+      may provide additional or different license terms and conditions
124
+      for use, reproduction, or distribution of Your modifications, or
125
+      for any such Derivative Works as a whole, provided Your use,
126
+      reproduction, and distribution of the Work otherwise complies with
127
+      the conditions stated in this License.
128
+
129
+   5. Submission of Contributions. Unless You explicitly state otherwise,
130
+      any Contribution intentionally submitted for inclusion in the Work
131
+      by You to the Licensor shall be under the terms and conditions of
132
+      this License, without any additional terms or conditions.
133
+      Notwithstanding the above, nothing herein shall supersede or modify
134
+      the terms of any separate license agreement you may have executed
135
+      with Licensor regarding such Contributions.
136
+
137
+   6. Trademarks. This License does not grant permission to use the trade
138
+      names, trademarks, service marks, or product names of the Licensor,
139
+      except as required for reasonable and customary use in describing the
140
+      origin of the Work and reproducing the content of the NOTICE file.
141
+
142
+   7. Disclaimer of Warranty. Unless required by applicable law or
143
+      agreed to in writing, Licensor provides the Work (and each
144
+      Contributor provides its Contributions) on an "AS IS" BASIS,
145
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
146
+      implied, including, without limitation, any warranties or conditions
147
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
148
+      PARTICULAR PURPOSE. You are solely responsible for determining the
149
+      appropriateness of using or redistributing the Work and assume any
150
+      risks associated with Your exercise of permissions under this License.
151
+
152
+   8. Limitation of Liability. In no event and under no legal theory,
153
+      whether in tort (including negligence), contract, or otherwise,
154
+      unless required by applicable law (such as deliberate and grossly
155
+      negligent acts) or agreed to in writing, shall any Contributor be
156
+      liable to You for damages, including any direct, indirect, special,
157
+      incidental, or consequential damages of any character arising as a
158
+      result of this License or out of the use or inability to use the
159
+      Work (including but not limited to damages for loss of goodwill,
160
+      work stoppage, computer failure or malfunction, or any and all
161
+      other commercial damages or losses), even if such Contributor
162
+      has been advised of the possibility of such damages.
163
+
164
+   9. Accepting Warranty or Additional Liability. While redistributing
165
+      the Work or Derivative Works thereof, You may choose to offer,
166
+      and charge a fee for, acceptance of support, warranty, indemnity,
167
+      or other liability obligations and/or rights consistent with this
168
+      License. However, in accepting such obligations, You may act only
169
+      on Your own behalf and on Your sole responsibility, not on behalf
170
+      of any other Contributor, and only if You agree to indemnify,
171
+      defend, and hold each Contributor harmless for any liability
172
+      incurred by, or claims asserted against, such Contributor by reason
173
+      of your accepting any such warranty or additional liability.
174
+
175
+   END OF TERMS AND CONDITIONS
176
+
177
+   APPENDIX: How to apply the Apache License to your work.
178
+
179
+      To apply the Apache License to your work, attach the following
180
+      boilerplate notice, with the fields enclosed by brackets "[]"
181
+      replaced with your own identifying information. (Don't include
182
+      the brackets!)  The text should be enclosed in the appropriate
183
+      comment syntax for the file format. We also recommend that a
184
+      file or class name and description of purpose be included on the
185
+      same "printed page" as the copyright notice for easier
186
+      identification within third-party archives.
187
+
188
+   Copyright [yyyy] [name of copyright owner]
189
+
190
+   Licensed under the Apache License, Version 2.0 (the "License");
191
+   you may not use this file except in compliance with the License.
192
+   You may obtain a copy of the License at
193
+
194
+       http://www.apache.org/licenses/LICENSE-2.0
195
+
196
+   Unless required by applicable law or agreed to in writing, software
197
+   distributed under the License is distributed on an "AS IS" BASIS,
198
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
199
+   See the License for the specific language governing permissions and
200
+   limitations under the License.
0 201
\ No newline at end of file
1 202
new file mode 100644
... ...
@@ -0,0 +1,85 @@
0
+# Go gRPC Middleware
1
+
2
+[![Travis Build](https://travis-ci.org/grpc-ecosystem/go-grpc-middleware.svg?branch=master)](https://travis-ci.org/grpc-ecosystem/go-grpc-middleware)
3
+[![Go Report Card](https://goreportcard.com/badge/github.com/grpc-ecosystem/go-grpc-middleware)](https://goreportcard.com/report/github.com/grpc-ecosystem/go-grpc-middleware)
4
+[![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/grpc-ecosystem/go-grpc-middleware)
5
+[![SourceGraph](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-middleware/-/badge.svg)](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-middleware/?badge)
6
+[![codecov](https://codecov.io/gh/grpc-ecosystem/go-grpc-middleware/branch/master/graph/badge.svg)](https://codecov.io/gh/grpc-ecosystem/go-grpc-middleware)
7
+[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
8
+[![quality: production](https://img.shields.io/badge/quality-production-orange.svg)](#status)
9
+[![Slack](https://img.shields.io/badge/slack-%23grpc--middleware-brightgreen)](https://slack.com/share/IRUQCFC23/9Tm7hxRFVKKNoajQfMOcUiIk/enQtODc4ODI4NTIyMDcxLWM5NDA0ZTE4Njg5YjRjYWZkMTI5MzQwNDY3YzBjMzE1YzdjOGM5ZjI1NDNiM2JmNzI2YjM5ODE5OTRiNTEyOWE)
10
+
11
+[gRPC Go](https://github.com/grpc/grpc-go) Middleware: interceptors, helpers, utilities.
12
+
13
+## Middleware
14
+
15
+[gRPC Go](https://github.com/grpc/grpc-go) recently acquired support for
16
+Interceptors, i.e. [middleware](https://medium.com/@matryer/writing-middleware-in-golang-and-how-go-makes-it-so-much-fun-4375c1246e81#.gv7tdlghs) 
17
+that is executed either on the gRPC Server before the request is passed onto the user's application logic, or on the gRPC client either around the user call. It is a perfect way to implement
18
+common patterns: auth, logging, message, validation, retries or monitoring.
19
+
20
+These are generic building blocks that make it easy to build multiple microservices easily.
21
+The purpose of this repository is to act as a go-to point for such reusable functionality. It contains
22
+some of them itself, but also will link to useful external repos.
23
+
24
+`grpc_middleware` itself provides support for chaining interceptors, here's an example:
25
+
26
+```go
27
+import "github.com/grpc-ecosystem/go-grpc-middleware"
28
+
29
+myServer := grpc.NewServer(
30
+    grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
31
+        grpc_ctxtags.StreamServerInterceptor(),
32
+        grpc_opentracing.StreamServerInterceptor(),
33
+        grpc_prometheus.StreamServerInterceptor,
34
+        grpc_zap.StreamServerInterceptor(zapLogger),
35
+        grpc_auth.StreamServerInterceptor(myAuthFunction),
36
+        grpc_recovery.StreamServerInterceptor(),
37
+    )),
38
+    grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
39
+        grpc_ctxtags.UnaryServerInterceptor(),
40
+        grpc_opentracing.UnaryServerInterceptor(),
41
+        grpc_prometheus.UnaryServerInterceptor,
42
+        grpc_zap.UnaryServerInterceptor(zapLogger),
43
+        grpc_auth.UnaryServerInterceptor(myAuthFunction),
44
+        grpc_recovery.UnaryServerInterceptor(),
45
+    )),
46
+)
47
+```
48
+
49
+## Interceptors
50
+
51
+*Please send a PR to add new interceptors or middleware to this list*
52
+
53
+#### Auth
54
+   * [`grpc_auth`](auth) - a customizable (via `AuthFunc`) piece of auth middleware 
55
+
56
+#### Logging
57
+   * [`grpc_ctxtags`](tags/) - a library that adds a `Tag` map to context, with data populated from request body
58
+   * [`grpc_zap`](logging/zap/) - integration of [zap](https://github.com/uber-go/zap) logging library into gRPC handlers.
59
+   * [`grpc_logrus`](logging/logrus/) - integration of [logrus](https://github.com/sirupsen/logrus) logging library into gRPC handlers.
60
+   * [`grpc_kit`](logging/kit/) - integration of [go-kit](https://github.com/go-kit/kit/tree/master/log) logging library into gRPC handlers.
61
+
62
+#### Monitoring
63
+   * [`grpc_prometheus`âš¡](https://github.com/grpc-ecosystem/go-grpc-prometheus) - Prometheus client-side and server-side monitoring middleware
64
+   * [`otgrpc`âš¡](https://github.com/grpc-ecosystem/grpc-opentracing/tree/master/go/otgrpc) - [OpenTracing](http://opentracing.io/) client-side and server-side interceptors
65
+   * [`grpc_opentracing`](tracing/opentracing) - [OpenTracing](http://opentracing.io/) client-side and server-side interceptors with support for streaming and handler-returned tags
66
+
67
+#### Client
68
+   * [`grpc_retry`](retry/) - a generic gRPC response code retry mechanism, client-side middleware
69
+
70
+#### Server
71
+   * [`grpc_validator`](validator/) - codegen inbound message validation from `.proto` options
72
+   * [`grpc_recovery`](recovery/) - turn panics into gRPC errors
73
+   * [`ratelimit`](ratelimit/) - grpc rate limiting by your own limiter
74
+
75
+
76
+## Status
77
+
78
+This code has been running in *production* since May 2016 as the basis of the gRPC micro services stack at [Improbable](https://improbable.io).
79
+
80
+Additional tooling will be added, and contributions are welcome.
81
+
82
+## License
83
+
84
+`go-grpc-middleware` is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.
0 85
new file mode 100644
... ...
@@ -0,0 +1,120 @@
0
+// Copyright 2016 Michal Witkowski. All Rights Reserved.
1
+// See LICENSE for licensing terms.
2
+
3
+// gRPC Server Interceptor chaining middleware.
4
+
5
+package grpc_middleware
6
+
7
+import (
8
+	"context"
9
+
10
+	"google.golang.org/grpc"
11
+)
12
+
13
+// ChainUnaryServer creates a single interceptor out of a chain of many interceptors.
14
+//
15
+// Execution is done in left-to-right order, including passing of context.
16
+// For example ChainUnaryServer(one, two, three) will execute one before two before three, and three
17
+// will see context changes of one and two.
18
+func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor {
19
+	n := len(interceptors)
20
+
21
+	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
22
+		chainer := func(currentInter grpc.UnaryServerInterceptor, currentHandler grpc.UnaryHandler) grpc.UnaryHandler {
23
+			return func(currentCtx context.Context, currentReq interface{}) (interface{}, error) {
24
+				return currentInter(currentCtx, currentReq, info, currentHandler)
25
+			}
26
+		}
27
+
28
+		chainedHandler := handler
29
+		for i := n - 1; i >= 0; i-- {
30
+			chainedHandler = chainer(interceptors[i], chainedHandler)
31
+		}
32
+
33
+		return chainedHandler(ctx, req)
34
+	}
35
+}
36
+
37
+// ChainStreamServer creates a single interceptor out of a chain of many interceptors.
38
+//
39
+// Execution is done in left-to-right order, including passing of context.
40
+// For example ChainUnaryServer(one, two, three) will execute one before two before three.
41
+// If you want to pass context between interceptors, use WrapServerStream.
42
+func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor {
43
+	n := len(interceptors)
44
+
45
+	return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
46
+		chainer := func(currentInter grpc.StreamServerInterceptor, currentHandler grpc.StreamHandler) grpc.StreamHandler {
47
+			return func(currentSrv interface{}, currentStream grpc.ServerStream) error {
48
+				return currentInter(currentSrv, currentStream, info, currentHandler)
49
+			}
50
+		}
51
+
52
+		chainedHandler := handler
53
+		for i := n - 1; i >= 0; i-- {
54
+			chainedHandler = chainer(interceptors[i], chainedHandler)
55
+		}
56
+
57
+		return chainedHandler(srv, ss)
58
+	}
59
+}
60
+
61
+// ChainUnaryClient creates a single interceptor out of a chain of many interceptors.
62
+//
63
+// Execution is done in left-to-right order, including passing of context.
64
+// For example ChainUnaryClient(one, two, three) will execute one before two before three.
65
+func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor {
66
+	n := len(interceptors)
67
+
68
+	return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
69
+		chainer := func(currentInter grpc.UnaryClientInterceptor, currentInvoker grpc.UnaryInvoker) grpc.UnaryInvoker {
70
+			return func(currentCtx context.Context, currentMethod string, currentReq, currentRepl interface{}, currentConn *grpc.ClientConn, currentOpts ...grpc.CallOption) error {
71
+				return currentInter(currentCtx, currentMethod, currentReq, currentRepl, currentConn, currentInvoker, currentOpts...)
72
+			}
73
+		}
74
+
75
+		chainedInvoker := invoker
76
+		for i := n - 1; i >= 0; i-- {
77
+			chainedInvoker = chainer(interceptors[i], chainedInvoker)
78
+		}
79
+
80
+		return chainedInvoker(ctx, method, req, reply, cc, opts...)
81
+	}
82
+}
83
+
84
+// ChainStreamClient creates a single interceptor out of a chain of many interceptors.
85
+//
86
+// Execution is done in left-to-right order, including passing of context.
87
+// For example ChainStreamClient(one, two, three) will execute one before two before three.
88
+func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor {
89
+	n := len(interceptors)
90
+
91
+	return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
92
+		chainer := func(currentInter grpc.StreamClientInterceptor, currentStreamer grpc.Streamer) grpc.Streamer {
93
+			return func(currentCtx context.Context, currentDesc *grpc.StreamDesc, currentConn *grpc.ClientConn, currentMethod string, currentOpts ...grpc.CallOption) (grpc.ClientStream, error) {
94
+				return currentInter(currentCtx, currentDesc, currentConn, currentMethod, currentStreamer, currentOpts...)
95
+			}
96
+		}
97
+
98
+		chainedStreamer := streamer
99
+		for i := n - 1; i >= 0; i-- {
100
+			chainedStreamer = chainer(interceptors[i], chainedStreamer)
101
+		}
102
+
103
+		return chainedStreamer(ctx, desc, cc, method, opts...)
104
+	}
105
+}
106
+
107
+// Chain creates a single interceptor out of a chain of many interceptors.
108
+//
109
+// WithUnaryServerChain is a grpc.Server config option that accepts multiple unary interceptors.
110
+// Basically syntactic sugar.
111
+func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption {
112
+	return grpc.UnaryInterceptor(ChainUnaryServer(interceptors...))
113
+}
114
+
115
+// WithStreamServerChain is a grpc.Server config option that accepts multiple stream interceptors.
116
+// Basically syntactic sugar.
117
+func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption {
118
+	return grpc.StreamInterceptor(ChainStreamServer(interceptors...))
119
+}
0 120
new file mode 100644
... ...
@@ -0,0 +1,69 @@
0
+// Copyright 2016 Michal Witkowski. All Rights Reserved.
1
+// See LICENSE for licensing terms.
2
+
3
+/*
4
+`grpc_middleware` is a collection of gRPC middleware packages: interceptors, helpers and tools.
5
+
6
+Middleware
7
+
8
+gRPC is a fantastic RPC middleware, which sees a lot of adoption in the Golang world. However, the
9
+upstream gRPC codebase is relatively bare bones.
10
+
11
+This package, and most of its child packages provides commonly needed middleware for gRPC:
12
+client-side interceptors for retires, server-side interceptors for input validation and auth,
13
+functions for chaining said interceptors, metadata convenience methods and more.
14
+
15
+Chaining
16
+
17
+By default, gRPC doesn't allow one to have more than one interceptor either on the client nor on
18
+the server side. `grpc_middleware` provides convenient chaining methods
19
+
20
+Simple way of turning a multiple interceptors into a single interceptor. Here's an example for
21
+server chaining:
22
+
23
+	myServer := grpc.NewServer(
24
+	    grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(loggingStream, monitoringStream, authStream)),
25
+	    grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(loggingUnary, monitoringUnary, authUnary),
26
+	)
27
+
28
+These interceptors will be executed from left to right: logging, monitoring and auth.
29
+
30
+Here's an example for client side chaining:
31
+
32
+	clientConn, err = grpc.Dial(
33
+	    address,
34
+	        grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(monitoringClientUnary, retryUnary)),
35
+	        grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(monitoringClientStream, retryStream)),
36
+	)
37
+	client = pb_testproto.NewTestServiceClient(clientConn)
38
+	resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"})
39
+
40
+These interceptors will be executed from left to right: monitoring and then retry logic.
41
+
42
+The retry interceptor will call every interceptor that follows it whenever when a retry happens.
43
+
44
+Writing Your Own
45
+
46
+Implementing your own interceptor is pretty trivial: there are interfaces for that. But the interesting
47
+bit exposing common data to handlers (and other middleware), similarly to HTTP Middleware design.
48
+For example, you may want to pass the identity of the caller from the auth interceptor all the way
49
+to the handling function.
50
+
51
+For example, a client side interceptor example for auth looks like:
52
+
53
+	func FakeAuthUnaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
54
+	   newCtx := context.WithValue(ctx, "user_id", "john@example.com")
55
+	   return handler(newCtx, req)
56
+	}
57
+
58
+Unfortunately, it's not as easy for streaming RPCs. These have the `context.Context` embedded within
59
+the `grpc.ServerStream` object. To pass values through context, a wrapper (`WrappedServerStream`) is
60
+needed. For example:
61
+
62
+	func FakeAuthStreamingInterceptor(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
63
+	   newStream := grpc_middleware.WrapServerStream(stream)
64
+	   newStream.WrappedContext = context.WithValue(ctx, "user_id", "john@example.com")
65
+	   return handler(srv, stream)
66
+	}
67
+*/
68
+package grpc_middleware
0 69
new file mode 100644
... ...
@@ -0,0 +1,22 @@
0
+module github.com/grpc-ecosystem/go-grpc-middleware
1
+
2
+require (
3
+	github.com/go-kit/kit v0.9.0
4
+	github.com/go-logfmt/logfmt v0.4.0 // indirect
5
+	github.com/go-stack/stack v1.8.0 // indirect
6
+	github.com/gogo/protobuf v1.2.1
7
+	github.com/golang/protobuf v1.3.2
8
+	github.com/opentracing/opentracing-go v1.1.0
9
+	github.com/pkg/errors v0.8.1 // indirect
10
+	github.com/sirupsen/logrus v1.4.2
11
+	github.com/stretchr/testify v1.4.0
12
+	go.uber.org/atomic v1.4.0 // indirect
13
+	go.uber.org/multierr v1.1.0 // indirect
14
+	go.uber.org/zap v1.10.0
15
+	golang.org/x/net v0.0.0-20190311183353-d8887717615a
16
+	golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
17
+	google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 // indirect
18
+	google.golang.org/grpc v1.19.0
19
+)
20
+
21
+go 1.13
0 22
new file mode 100644
... ...
@@ -0,0 +1,30 @@
0
+// Copyright 2016 Michal Witkowski. All Rights Reserved.
1
+// See LICENSE for licensing terms.
2
+
3
+package grpc_middleware
4
+
5
+import (
6
+	"context"
7
+
8
+	"google.golang.org/grpc"
9
+)
10
+
11
+// WrappedServerStream is a thin wrapper around grpc.ServerStream that allows modifying context.
12
+type WrappedServerStream struct {
13
+	grpc.ServerStream
14
+	// WrappedContext is the wrapper's own Context. You can assign it.
15
+	WrappedContext context.Context
16
+}
17
+
18
+// Context returns the wrapper's WrappedContext, overwriting the nested grpc.ServerStream.Context()
19
+func (w *WrappedServerStream) Context() context.Context {
20
+	return w.WrappedContext
21
+}
22
+
23
+// WrapServerStream returns a ServerStream that has the ability to overwrite context.
24
+func WrapServerStream(stream grpc.ServerStream) *WrappedServerStream {
25
+	if existing, ok := stream.(*WrappedServerStream); ok {
26
+		return existing
27
+	}
28
+	return &WrappedServerStream{ServerStream: stream, WrappedContext: stream.Context()}
29
+}
... ...
@@ -86,6 +86,7 @@ BuildKit is used by the following projects:
86 86
 -   [PouchContainer](https://github.com/alibaba/pouch)
87 87
 -   [Docker buildx](https://github.com/docker/buildx)
88 88
 -   [Okteto Cloud](https://okteto.com/)
89
+-   [Earthly earthfiles](https://github.com/vladaionescu/earthly)
89 90
 
90 91
 ## Quick start
91 92
 
... ...
@@ -148,6 +149,7 @@ Currently, the following high-level languages has been implemented for LLB:
148 148
 -   [Buildpacks](https://github.com/tonistiigi/buildkit-pack)
149 149
 -   [Mockerfile](https://matt-rickard.com/building-a-new-dockerfile-frontend/)
150 150
 -   [Gockerfile](https://github.com/po3rin/gockerfile)
151
+-   [bldr (Pkgfile)](https://github.com/talos-systems/bldr/)
151 152
 -   (open a PR to add your own language)
152 153
 
153 154
 ### Exploring Dockerfiles
... ...
@@ -1,9 +1,10 @@
1 1
 package contenthash
2 2
 
3 3
 import (
4
-	"errors"
5 4
 	"os"
6 5
 	"path/filepath"
6
+
7
+	"github.com/pkg/errors"
7 8
 )
8 9
 
9 10
 var (
... ...
@@ -52,7 +53,7 @@ func walkLink(root, path string, linksWalked *int, cb onSymlinkFunc) (newpath st
52 52
 	fi, err := os.Lstat(realPath)
53 53
 	if err != nil {
54 54
 		// If path does not yet exist, treat as non-symlink
55
-		if os.IsNotExist(err) {
55
+		if errors.Is(err, os.ErrNotExist) {
56 56
 			return path, false, nil
57 57
 		}
58 58
 		return "", false, err
... ...
@@ -39,7 +39,7 @@ func v1TarHeaderSelect(h *tar.Header) (orderedHeaders [][2]string) {
39 39
 	// Get extended attributes.
40 40
 	xAttrKeys := make([]string, len(h.Xattrs))
41 41
 	for k := range h.Xattrs {
42
-		if !strings.HasPrefix(k, "security.") && !strings.HasPrefix(k, "system.") {
42
+		if k == "security.capability" || !strings.HasPrefix(k, "security.") && !strings.HasPrefix(k, "system.") {
43 43
 			xAttrKeys = append(xAttrKeys, k)
44 44
 		}
45 45
 	}
... ...
@@ -16,7 +16,7 @@ import (
16 16
 	"github.com/moby/buildkit/client"
17 17
 	"github.com/moby/buildkit/identity"
18 18
 	"github.com/moby/buildkit/snapshot"
19
-	"github.com/opencontainers/go-digest"
19
+	digest "github.com/opencontainers/go-digest"
20 20
 	imagespecidentity "github.com/opencontainers/image-spec/identity"
21 21
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
22 22
 	"github.com/pkg/errors"
... ...
@@ -143,7 +143,7 @@ func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor,
143 143
 
144 144
 	for _, si := range sis {
145 145
 		ref, err := cm.get(ctx, si.ID(), opts...)
146
-		if err != nil && errors.Cause(err) != errNotFound {
146
+		if err != nil && !IsNotFound(err) {
147 147
 			return nil, errors.Wrapf(err, "failed to get record %s by blobchainid", si.ID())
148 148
 		}
149 149
 		if p != nil {
... ...
@@ -160,7 +160,7 @@ func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor,
160 160
 	var link ImmutableRef
161 161
 	for _, si := range sis {
162 162
 		ref, err := cm.get(ctx, si.ID(), opts...)
163
-		if err != nil && errors.Cause(err) != errNotFound {
163
+		if err != nil && !IsNotFound(err) {
164 164
 			return nil, errors.Wrapf(err, "failed to get record %s by chainid", si.ID())
165 165
 		}
166 166
 		link = ref
... ...
@@ -338,7 +338,7 @@ func (cm *cacheManager) getRecord(ctx context.Context, id string, opts ...RefOpt
338 338
 		mutable, err := cm.getRecord(ctx, mutableID)
339 339
 		if err != nil {
340 340
 			// check loading mutable deleted record from disk
341
-			if errors.Cause(err) == errNotFound {
341
+			if IsNotFound(err) {
342 342
 				cm.md.Clear(id)
343 343
 			}
344 344
 			return nil, err
... ...
@@ -906,12 +906,8 @@ func (cm *cacheManager) DiskUsage(ctx context.Context, opt client.DiskUsageInfo)
906 906
 	return du, nil
907 907
 }
908 908
 
909
-func IsLocked(err error) bool {
910
-	return errors.Cause(err) == ErrLocked
911
-}
912
-
913 909
 func IsNotFound(err error) bool {
914
-	return errors.Cause(err) == errNotFound
910
+	return errors.Is(err, errNotFound)
915 911
 }
916 912
 
917 913
 type RefOption interface{}
... ...
@@ -13,7 +13,7 @@ import (
13 13
 	"github.com/containerd/containerd/snapshots"
14 14
 	"github.com/moby/buildkit/cache/metadata"
15 15
 	"github.com/moby/buildkit/snapshot"
16
-	"github.com/opencontainers/go-digest"
16
+	digest "github.com/opencontainers/go-digest"
17 17
 	"github.com/pkg/errors"
18 18
 	"github.com/sirupsen/logrus"
19 19
 )
... ...
@@ -56,7 +56,7 @@ func migrateChainID(si *metadata.StorageItem, all map[string]*metadata.StorageIt
56 56
 func MigrateV2(ctx context.Context, from, to string, cs content.Store, s snapshot.Snapshotter, lm leases.Manager) error {
57 57
 	_, err := os.Stat(to)
58 58
 	if err != nil {
59
-		if !os.IsNotExist(errors.Cause(err)) {
59
+		if !errors.Is(err, os.ErrNotExist) {
60 60
 			return errors.WithStack(err)
61 61
 		}
62 62
 	} else {
... ...
@@ -65,7 +65,7 @@ func MigrateV2(ctx context.Context, from, to string, cs content.Store, s snapsho
65 65
 
66 66
 	_, err = os.Stat(from)
67 67
 	if err != nil {
68
-		if !os.IsNotExist(errors.Cause(err)) {
68
+		if !errors.Is(err, os.ErrNotExist) {
69 69
 			return errors.WithStack(err)
70 70
 		}
71 71
 		return nil
... ...
@@ -180,7 +180,7 @@ func MigrateV2(ctx context.Context, from, to string, cs content.Store, s snapsho
180 180
 		})
181 181
 		if err != nil {
182 182
 			// if we are running the migration twice
183
-			if errdefs.IsAlreadyExists(err) {
183
+			if errors.Is(err, errdefs.ErrAlreadyExists) {
184 184
 				continue
185 185
 			}
186 186
 			return errors.Wrap(err, "failed to create lease")
... ...
@@ -205,19 +205,22 @@ func MigrateV2(ctx context.Context, from, to string, cs content.Store, s snapsho
205 205
 
206 206
 	// remove old root labels
207 207
 	for _, item := range byID {
208
-		if _, err := s.Update(ctx, snapshots.Info{
209
-			Name: getSnapshotID(item),
210
-		}, "labels.containerd.io/gc.root"); err != nil {
211
-			if !errdefs.IsNotFound(errors.Cause(err)) {
212
-				return err
208
+		em := getEqualMutable(item)
209
+		if em == "" {
210
+			if _, err := s.Update(ctx, snapshots.Info{
211
+				Name: getSnapshotID(item),
212
+			}, "labels.containerd.io/gc.root"); err != nil {
213
+				if !errors.Is(err, errdefs.ErrNotFound) {
214
+					return err
215
+				}
213 216
 			}
214
-		}
215 217
 
216
-		if blob := getBlob(item); blob != "" {
217
-			if _, err := cs.Update(ctx, content.Info{
218
-				Digest: digest.Digest(blob),
219
-			}, "labels.containerd.io/gc.root"); err != nil {
220
-				return err
218
+			if blob := getBlob(item); blob != "" {
219
+				if _, err := cs.Update(ctx, content.Info{
220
+					Digest: digest.Digest(blob),
221
+				}, "labels.containerd.io/gc.root"); err != nil {
222
+					return err
223
+				}
221 224
 			}
222 225
 		}
223 226
 	}
... ...
@@ -228,7 +231,7 @@ func MigrateV2(ctx context.Context, from, to string, cs content.Store, s snapsho
228 228
 			if _, err := s.Update(ctx, snapshots.Info{
229 229
 				Name: info.Name,
230 230
 			}, "labels.containerd.io/gc.root"); err != nil {
231
-				if !errdefs.IsNotFound(errors.Cause(err)) {
231
+				if !errors.Is(err, errdefs.ErrNotFound) {
232 232
 					return err
233 233
 				}
234 234
 			}
... ...
@@ -17,7 +17,7 @@ import (
17 17
 	"github.com/moby/buildkit/snapshot"
18 18
 	"github.com/moby/buildkit/util/flightcontrol"
19 19
 	"github.com/moby/buildkit/util/leaseutil"
20
-	"github.com/opencontainers/go-digest"
20
+	digest "github.com/opencontainers/go-digest"
21 21
 	imagespecidentity "github.com/opencontainers/image-spec/identity"
22 22
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
23 23
 	"github.com/pkg/errors"
... ...
@@ -160,7 +160,7 @@ func (cr *cacheRecord) Size(ctx context.Context) (int64, error) {
160 160
 				if isDead {
161 161
 					return int64(0), nil
162 162
 				}
163
-				if !errdefs.IsNotFound(err) {
163
+				if !errors.Is(err, errdefs.ErrNotFound) {
164 164
 					return s, errors.Wrapf(err, "failed to get usage for %s", cr.ID())
165 165
 				}
166 166
 			}
... ...
@@ -180,7 +180,10 @@ func (cr *cacheRecord) Size(ctx context.Context) (int64, error) {
180 180
 		cr.mu.Unlock()
181 181
 		return usage.Size, nil
182 182
 	})
183
-	return s.(int64), err
183
+	if err != nil {
184
+		return 0, err
185
+	}
186
+	return s.(int64), nil
184 187
 }
185 188
 
186 189
 func (cr *cacheRecord) Parent() ImmutableRef {
... ...
@@ -349,7 +352,7 @@ func (sr *immutableRef) Extract(ctx context.Context) error {
349 349
 			return nil, err
350 350
 		}
351 351
 		if err := sr.cm.Snapshotter.Commit(ctx, getSnapshotID(sr.md), key); err != nil {
352
-			if !errdefs.IsAlreadyExists(err) {
352
+			if !errors.Is(err, errdefs.ErrAlreadyExists) {
353 353
 				return nil, err
354 354
 			}
355 355
 		}
... ...
@@ -506,7 +509,7 @@ func (cr *cacheRecord) finalize(ctx context.Context, commit bool) error {
506 506
 		return nil
507 507
 	})
508 508
 	if err != nil {
509
-		if !errdefs.IsAlreadyExists(err) { // migrator adds leases for everything
509
+		if !errors.Is(err, errdefs.ErrAlreadyExists) { // migrator adds leases for everything
510 510
 			return errors.Wrap(err, "failed to create lease")
511 511
 		}
512 512
 	}
... ...
@@ -10,7 +10,7 @@ import (
10 10
 	"github.com/moby/buildkit/session"
11 11
 	"github.com/moby/buildkit/util/contentutil"
12 12
 	"github.com/moby/buildkit/util/resolver"
13
-	"github.com/opencontainers/go-digest"
13
+	digest "github.com/opencontainers/go-digest"
14 14
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
15 15
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
16 16
 	"github.com/pkg/errors"
... ...
@@ -8,12 +8,14 @@ import (
8 8
 	"net"
9 9
 	"time"
10 10
 
11
+	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
11 12
 	"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
12 13
 	controlapi "github.com/moby/buildkit/api/services/control"
13 14
 	"github.com/moby/buildkit/client/connhelper"
14 15
 	"github.com/moby/buildkit/session"
15 16
 	"github.com/moby/buildkit/session/grpchijack"
16 17
 	"github.com/moby/buildkit/util/appdefaults"
18
+	"github.com/moby/buildkit/util/grpcerrors"
17 19
 	opentracing "github.com/opentracing/opentracing-go"
18 20
 	"github.com/pkg/errors"
19 21
 	"google.golang.org/grpc"
... ...
@@ -31,6 +33,10 @@ func New(ctx context.Context, address string, opts ...ClientOpt) (*Client, error
31 31
 	gopts := []grpc.DialOption{}
32 32
 	needDialer := true
33 33
 	needWithInsecure := true
34
+
35
+	var unary []grpc.UnaryClientInterceptor
36
+	var stream []grpc.StreamClientInterceptor
37
+
34 38
 	for _, o := range opts {
35 39
 		if _, ok := o.(*withFailFast); ok {
36 40
 			gopts = append(gopts, grpc.FailOnNonTempDialError(true))
... ...
@@ -44,9 +50,8 @@ func New(ctx context.Context, address string, opts ...ClientOpt) (*Client, error
44 44
 			needWithInsecure = false
45 45
 		}
46 46
 		if wt, ok := o.(*withTracer); ok {
47
-			gopts = append(gopts,
48
-				grpc.WithUnaryInterceptor(otgrpc.OpenTracingClientInterceptor(wt.tracer, otgrpc.LogPayloads())),
49
-				grpc.WithStreamInterceptor(otgrpc.OpenTracingStreamClientInterceptor(wt.tracer)))
47
+			unary = append(unary, otgrpc.OpenTracingClientInterceptor(wt.tracer, otgrpc.LogPayloads()))
48
+			stream = append(stream, otgrpc.OpenTracingStreamClientInterceptor(wt.tracer))
50 49
 		}
51 50
 		if wd, ok := o.(*withDialer); ok {
52 51
 			gopts = append(gopts, grpc.WithDialer(wd.dialer))
... ...
@@ -68,6 +73,22 @@ func New(ctx context.Context, address string, opts ...ClientOpt) (*Client, error
68 68
 	if address == "" {
69 69
 		address = appdefaults.Address
70 70
 	}
71
+
72
+	unary = append(unary, grpcerrors.UnaryClientInterceptor)
73
+	stream = append(stream, grpcerrors.StreamClientInterceptor)
74
+
75
+	if len(unary) == 1 {
76
+		gopts = append(gopts, grpc.WithUnaryInterceptor(unary[0]))
77
+	} else if len(unary) > 1 {
78
+		gopts = append(gopts, grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(unary...)))
79
+	}
80
+
81
+	if len(stream) == 1 {
82
+		gopts = append(gopts, grpc.WithStreamInterceptor(stream[0]))
83
+	} else if len(stream) > 1 {
84
+		gopts = append(gopts, grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(stream...)))
85
+	}
86
+
71 87
 	conn, err := grpc.DialContext(ctx, address, gopts...)
72 88
 	if err != nil {
73 89
 		return nil, errors.Wrapf(err, "failed to dial %q . make sure buildkitd is running", address)
... ...
@@ -1,4 +1,5 @@
1
-// Package connhelper provides helpers for connecting to a remote daemon host with custom logic.
1
+// Package connhelper provides helpers for connecting to a remote daemon host
2
+// with custom logic.
2 3
 package connhelper
3 4
 
4 5
 import (
... ...
@@ -61,7 +61,7 @@ func (as *asyncState) Do(ctx context.Context) error {
61 61
 		if err != nil {
62 62
 			select {
63 63
 			case <-ctx.Done():
64
-				if errors.Cause(err) == ctx.Err() {
64
+				if errors.Is(err, ctx.Err()) {
65 65
 					return res, err
66 66
 				}
67 67
 			default:
... ...
@@ -85,8 +85,8 @@ type errVertex struct {
85 85
 func (v *errVertex) Validate(context.Context) error {
86 86
 	return v.err
87 87
 }
88
-func (v *errVertex) Marshal(context.Context, *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
89
-	return "", nil, nil, v.err
88
+func (v *errVertex) Marshal(context.Context, *Constraints) (digest.Digest, []byte, *pb.OpMetadata, []*SourceLocation, error) {
89
+	return "", nil, nil, nil, v.err
90 90
 }
91 91
 func (v *errVertex) Output() Output {
92 92
 	return nil
... ...
@@ -20,6 +20,7 @@ type DefinitionOp struct {
20 20
 	ops       map[digest.Digest]*pb.Op
21 21
 	defs      map[digest.Digest][]byte
22 22
 	metas     map[digest.Digest]pb.OpMetadata
23
+	sources   map[digest.Digest][]*SourceLocation
23 24
 	platforms map[digest.Digest]*specs.Platform
24 25
 	dgst      digest.Digest
25 26
 	index     pb.OutputIndex
... ...
@@ -49,6 +50,38 @@ func NewDefinitionOp(def *pb.Definition) (*DefinitionOp, error) {
49 49
 		platforms[dgst] = platform
50 50
 	}
51 51
 
52
+	srcs := map[digest.Digest][]*SourceLocation{}
53
+
54
+	if def.Source != nil {
55
+		sourceMaps := make([]*SourceMap, len(def.Source.Infos))
56
+		for i, info := range def.Source.Infos {
57
+			var st *State
58
+			sdef := info.Definition
59
+			if sdef != nil {
60
+				op, err := NewDefinitionOp(sdef)
61
+				if err != nil {
62
+					return nil, err
63
+				}
64
+				state := NewState(op)
65
+				st = &state
66
+			}
67
+			sourceMaps[i] = NewSourceMap(st, info.Filename, info.Data)
68
+		}
69
+
70
+		for dgst, locs := range def.Source.Locations {
71
+			for _, loc := range locs.Locations {
72
+				if loc.SourceIndex < 0 || int(loc.SourceIndex) >= len(sourceMaps) {
73
+					return nil, errors.Errorf("failed to find source map with index %d", loc.SourceIndex)
74
+				}
75
+
76
+				srcs[digest.Digest(dgst)] = append(srcs[digest.Digest(dgst)], &SourceLocation{
77
+					SourceMap: sourceMaps[int(loc.SourceIndex)],
78
+					Ranges:    loc.Ranges,
79
+				})
80
+			}
81
+		}
82
+	}
83
+
52 84
 	var index pb.OutputIndex
53 85
 	if dgst != "" {
54 86
 		index = ops[dgst].Inputs[0].Index
... ...
@@ -59,6 +92,7 @@ func NewDefinitionOp(def *pb.Definition) (*DefinitionOp, error) {
59 59
 		ops:       ops,
60 60
 		defs:      defs,
61 61
 		metas:     def.Metadata,
62
+		sources:   srcs,
62 63
 		platforms: platforms,
63 64
 		dgst:      dgst,
64 65
 		index:     index,
... ...
@@ -110,20 +144,20 @@ func (d *DefinitionOp) Validate(context.Context) error {
110 110
 	return nil
111 111
 }
112 112
 
113
-func (d *DefinitionOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
113
+func (d *DefinitionOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, []*SourceLocation, error) {
114 114
 	if d.dgst == "" {
115
-		return "", nil, nil, errors.Errorf("cannot marshal empty definition op")
115
+		return "", nil, nil, nil, errors.Errorf("cannot marshal empty definition op")
116 116
 	}
117 117
 
118 118
 	if err := d.Validate(ctx); err != nil {
119
-		return "", nil, nil, err
119
+		return "", nil, nil, nil, err
120 120
 	}
121 121
 
122 122
 	d.mu.Lock()
123 123
 	defer d.mu.Unlock()
124 124
 
125 125
 	meta := d.metas[d.dgst]
126
-	return d.dgst, d.defs[d.dgst], &meta, nil
126
+	return d.dgst, d.defs[d.dgst], &meta, d.sources[d.dgst], nil
127 127
 
128 128
 }
129 129
 
... ...
@@ -81,7 +81,7 @@ func (e *ExecOp) AddMount(target string, source Output, opt ...MountOption) Outp
81 81
 		}
82 82
 		m.output = o
83 83
 	}
84
-	e.Store(nil, nil, nil)
84
+	e.Store(nil, nil, nil, nil)
85 85
 	e.isValidated = false
86 86
 	return m.output
87 87
 }
... ...
@@ -124,12 +124,12 @@ func (e *ExecOp) Validate(ctx context.Context) error {
124 124
 	return nil
125 125
 }
126 126
 
127
-func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
127
+func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, []*SourceLocation, error) {
128 128
 	if e.Cached(c) {
129 129
 		return e.Load()
130 130
 	}
131 131
 	if err := e.Validate(ctx); err != nil {
132
-		return "", nil, nil, err
132
+		return "", nil, nil, nil, err
133 133
 	}
134 134
 	// make sure mounts are sorted
135 135
 	sort.Slice(e.mounts, func(i, j int) bool {
... ...
@@ -138,7 +138,7 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
138 138
 
139 139
 	env, err := getEnv(e.base)(ctx)
140 140
 	if err != nil {
141
-		return "", nil, nil, err
141
+		return "", nil, nil, nil, err
142 142
 	}
143 143
 
144 144
 	if len(e.ssh) > 0 {
... ...
@@ -161,17 +161,17 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
161 161
 
162 162
 	args, err := getArgs(e.base)(ctx)
163 163
 	if err != nil {
164
-		return "", nil, nil, err
164
+		return "", nil, nil, nil, err
165 165
 	}
166 166
 
167 167
 	cwd, err := getDir(e.base)(ctx)
168 168
 	if err != nil {
169
-		return "", nil, nil, err
169
+		return "", nil, nil, nil, err
170 170
 	}
171 171
 
172 172
 	user, err := getUser(e.base)(ctx)
173 173
 	if err != nil {
174
-		return "", nil, nil, err
174
+		return "", nil, nil, nil, err
175 175
 	}
176 176
 
177 177
 	meta := &pb.Meta{
... ...
@@ -182,7 +182,7 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
182 182
 	}
183 183
 	extraHosts, err := getExtraHosts(e.base)(ctx)
184 184
 	if err != nil {
185
-		return "", nil, nil, err
185
+		return "", nil, nil, nil, err
186 186
 	}
187 187
 	if len(extraHosts) > 0 {
188 188
 		hosts := make([]*pb.HostIP, len(extraHosts))
... ...
@@ -194,12 +194,12 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
194 194
 
195 195
 	network, err := getNetwork(e.base)(ctx)
196 196
 	if err != nil {
197
-		return "", nil, nil, err
197
+		return "", nil, nil, nil, err
198 198
 	}
199 199
 
200 200
 	security, err := getSecurity(e.base)(ctx)
201 201
 	if err != nil {
202
-		return "", nil, nil, err
202
+		return "", nil, nil, nil, err
203 203
 	}
204 204
 
205 205
 	peo := &pb.ExecOp{
... ...
@@ -252,7 +252,7 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
252 252
 	if e.constraints.Platform == nil {
253 253
 		p, err := getPlatform(e.base)(ctx)
254 254
 		if err != nil {
255
-			return "", nil, nil, err
255
+			return "", nil, nil, nil, err
256 256
 		}
257 257
 		e.constraints.Platform = p
258 258
 	}
... ...
@@ -267,11 +267,11 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
267 267
 		inputIndex := pb.InputIndex(len(pop.Inputs))
268 268
 		if m.source != nil {
269 269
 			if m.tmpfs {
270
-				return "", nil, nil, errors.Errorf("tmpfs mounts must use scratch")
270
+				return "", nil, nil, nil, errors.Errorf("tmpfs mounts must use scratch")
271 271
 			}
272 272
 			inp, err := m.source.ToInput(ctx, c)
273 273
 			if err != nil {
274
-				return "", nil, nil, err
274
+				return "", nil, nil, nil, err
275 275
 			}
276 276
 
277 277
 			newInput := true
... ...
@@ -356,9 +356,9 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
356 356
 
357 357
 	dt, err := pop.Marshal()
358 358
 	if err != nil {
359
-		return "", nil, nil, err
359
+		return "", nil, nil, nil, err
360 360
 	}
361
-	e.Store(dt, md, c)
361
+	e.Store(dt, md, e.constraints.SourceLocations, c)
362 362
 	return e.Load()
363 363
 }
364 364
 
... ...
@@ -388,7 +388,7 @@ func (e *ExecOp) getMountIndexFn(m *mount) func() (pb.OutputIndex, error) {
388 388
 
389 389
 		i := 0
390 390
 		for _, m2 := range e.mounts {
391
-			if m2.noOutput || m2.readonly || m2.cacheID != "" {
391
+			if m2.noOutput || m2.readonly || m2.tmpfs || m2.cacheID != "" {
392 392
 				continue
393 393
 			}
394 394
 			if m == m2 {
... ...
@@ -649,12 +649,12 @@ func (ms *marshalState) add(fa *FileAction, c *Constraints) (*fileActionState, e
649 649
 	return st, nil
650 650
 }
651 651
 
652
-func (f *FileOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
652
+func (f *FileOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, []*SourceLocation, error) {
653 653
 	if f.Cached(c) {
654 654
 		return f.Load()
655 655
 	}
656 656
 	if err := f.Validate(ctx); err != nil {
657
-		return "", nil, nil, err
657
+		return "", nil, nil, nil, err
658 658
 	}
659 659
 
660 660
 	addCap(&f.constraints, pb.CapFileBase)
... ...
@@ -669,7 +669,7 @@ func (f *FileOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
669 669
 	state := newMarshalState(ctx)
670 670
 	_, err := state.add(f.action, c)
671 671
 	if err != nil {
672
-		return "", nil, nil, err
672
+		return "", nil, nil, nil, err
673 673
 	}
674 674
 	pop.Inputs = state.inputs
675 675
 
... ...
@@ -683,13 +683,13 @@ func (f *FileOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
683 683
 		if st.fa.state != nil {
684 684
 			parent, err = st.fa.state.GetDir(ctx)
685 685
 			if err != nil {
686
-				return "", nil, nil, err
686
+				return "", nil, nil, nil, err
687 687
 			}
688 688
 		}
689 689
 
690 690
 		action, err := st.action.toProtoAction(ctx, parent, st.base)
691 691
 		if err != nil {
692
-			return "", nil, nil, err
692
+			return "", nil, nil, nil, err
693 693
 		}
694 694
 
695 695
 		pfo.Actions = append(pfo.Actions, &pb.FileAction{
... ...
@@ -702,9 +702,9 @@ func (f *FileOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
702 702
 
703 703
 	dt, err := pop.Marshal()
704 704
 	if err != nil {
705
-		return "", nil, nil, err
705
+		return "", nil, nil, nil, err
706 706
 	}
707
-	f.Store(dt, md, c)
707
+	f.Store(dt, md, f.constraints.SourceLocations, c)
708 708
 	return f.Load()
709 709
 }
710 710
 
... ...
@@ -14,21 +14,24 @@ import (
14 14
 type Definition struct {
15 15
 	Def      [][]byte
16 16
 	Metadata map[digest.Digest]pb.OpMetadata
17
+	Source   *pb.Source
17 18
 }
18 19
 
19 20
 func (def *Definition) ToPB() *pb.Definition {
20
-	md := make(map[digest.Digest]pb.OpMetadata)
21
+	md := make(map[digest.Digest]pb.OpMetadata, len(def.Metadata))
21 22
 	for k, v := range def.Metadata {
22 23
 		md[k] = v
23 24
 	}
24 25
 	return &pb.Definition{
25 26
 		Def:      def.Def,
27
+		Source:   def.Source,
26 28
 		Metadata: md,
27 29
 	}
28 30
 }
29 31
 
30 32
 func (def *Definition) FromPB(x *pb.Definition) {
31 33
 	def.Def = x.Def
34
+	def.Source = x.Source
32 35
 	def.Metadata = make(map[digest.Digest]pb.OpMetadata)
33 36
 	for k, v := range x.Metadata {
34 37
 		def.Metadata[k] = v
... ...
@@ -95,18 +98,20 @@ type MarshalCache struct {
95 95
 	digest      digest.Digest
96 96
 	dt          []byte
97 97
 	md          *pb.OpMetadata
98
+	srcs        []*SourceLocation
98 99
 	constraints *Constraints
99 100
 }
100 101
 
101 102
 func (mc *MarshalCache) Cached(c *Constraints) bool {
102 103
 	return mc.dt != nil && mc.constraints == c
103 104
 }
104
-func (mc *MarshalCache) Load() (digest.Digest, []byte, *pb.OpMetadata, error) {
105
-	return mc.digest, mc.dt, mc.md, nil
105
+func (mc *MarshalCache) Load() (digest.Digest, []byte, *pb.OpMetadata, []*SourceLocation, error) {
106
+	return mc.digest, mc.dt, mc.md, mc.srcs, nil
106 107
 }
107
-func (mc *MarshalCache) Store(dt []byte, md *pb.OpMetadata, c *Constraints) {
108
+func (mc *MarshalCache) Store(dt []byte, md *pb.OpMetadata, srcs []*SourceLocation, c *Constraints) {
108 109
 	mc.digest = digest.FromBytes(dt)
109 110
 	mc.dt = dt
110 111
 	mc.md = md
111 112
 	mc.constraints = c
113
+	mc.srcs = srcs
112 114
 }
... ...
@@ -44,12 +44,12 @@ func (s *SourceOp) Validate(ctx context.Context) error {
44 44
 	return nil
45 45
 }
46 46
 
47
-func (s *SourceOp) Marshal(ctx context.Context, constraints *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
47
+func (s *SourceOp) Marshal(ctx context.Context, constraints *Constraints) (digest.Digest, []byte, *pb.OpMetadata, []*SourceLocation, error) {
48 48
 	if s.Cached(constraints) {
49 49
 		return s.Load()
50 50
 	}
51 51
 	if err := s.Validate(ctx); err != nil {
52
-		return "", nil, nil, err
52
+		return "", nil, nil, nil, err
53 53
 	}
54 54
 
55 55
 	if strings.HasPrefix(s.id, "local://") {
... ...
@@ -74,10 +74,10 @@ func (s *SourceOp) Marshal(ctx context.Context, constraints *Constraints) (diges
74 74
 
75 75
 	dt, err := proto.Marshal()
76 76
 	if err != nil {
77
-		return "", nil, nil, err
77
+		return "", nil, nil, nil, err
78 78
 	}
79 79
 
80
-	s.Store(dt, md, constraints)
80
+	s.Store(dt, md, s.constraints.SourceLocations, constraints)
81 81
 	return s.Load()
82 82
 }
83 83
 
84 84
new file mode 100644
... ...
@@ -0,0 +1,111 @@
0
+package llb
1
+
2
+import (
3
+	"context"
4
+
5
+	"github.com/moby/buildkit/solver/pb"
6
+	"github.com/opencontainers/go-digest"
7
+)
8
+
9
+type SourceMap struct {
10
+	State      *State
11
+	Definition *Definition
12
+	Filename   string
13
+	Data       []byte
14
+}
15
+
16
+func NewSourceMap(st *State, filename string, dt []byte) *SourceMap {
17
+	return &SourceMap{
18
+		State:    st,
19
+		Filename: filename,
20
+		Data:     dt,
21
+	}
22
+}
23
+
24
+func (s *SourceMap) Location(r []*pb.Range) ConstraintsOpt {
25
+	return constraintsOptFunc(func(c *Constraints) {
26
+		if s == nil {
27
+			return
28
+		}
29
+		c.SourceLocations = append(c.SourceLocations, &SourceLocation{
30
+			SourceMap: s,
31
+			Ranges:    r,
32
+		})
33
+	})
34
+}
35
+
36
+type SourceLocation struct {
37
+	SourceMap *SourceMap
38
+	Ranges    []*pb.Range
39
+}
40
+
41
+type sourceMapCollector struct {
42
+	maps      []*SourceMap
43
+	index     map[*SourceMap]int
44
+	locations map[digest.Digest][]*SourceLocation
45
+}
46
+
47
+func newSourceMapCollector() *sourceMapCollector {
48
+	return &sourceMapCollector{
49
+		index:     map[*SourceMap]int{},
50
+		locations: map[digest.Digest][]*SourceLocation{},
51
+	}
52
+}
53
+
54
+func (smc *sourceMapCollector) Add(dgst digest.Digest, ls []*SourceLocation) {
55
+	for _, l := range ls {
56
+		idx, ok := smc.index[l.SourceMap]
57
+		if !ok {
58
+			idx = len(smc.maps)
59
+			smc.maps = append(smc.maps, l.SourceMap)
60
+		}
61
+		smc.index[l.SourceMap] = idx
62
+	}
63
+	smc.locations[dgst] = ls
64
+}
65
+
66
+func (smc *sourceMapCollector) Marshal(ctx context.Context, co ...ConstraintsOpt) (*pb.Source, error) {
67
+	s := &pb.Source{
68
+		Locations: make(map[string]*pb.Locations),
69
+	}
70
+	for _, m := range smc.maps {
71
+		def := m.Definition
72
+		if def == nil && m.State != nil {
73
+			var err error
74
+			def, err = m.State.Marshal(ctx, co...)
75
+			if err != nil {
76
+				return nil, err
77
+			}
78
+			m.Definition = def
79
+		}
80
+
81
+		info := &pb.SourceInfo{
82
+			Data:     m.Data,
83
+			Filename: m.Filename,
84
+		}
85
+
86
+		if def != nil {
87
+			info.Definition = def.ToPB()
88
+		}
89
+
90
+		s.Infos = append(s.Infos, info)
91
+	}
92
+
93
+	for dgst, locs := range smc.locations {
94
+		pbLocs, ok := s.Locations[dgst.String()]
95
+		if !ok {
96
+			pbLocs = &pb.Locations{}
97
+		}
98
+
99
+		for _, loc := range locs {
100
+			pbLocs.Locations = append(pbLocs.Locations, &pb.Location{
101
+				SourceIndex: int32(smc.index[loc.SourceMap]),
102
+				Ranges:      loc.Ranges,
103
+			})
104
+		}
105
+
106
+		s.Locations[dgst.String()] = pbLocs
107
+	}
108
+
109
+	return s, nil
110
+}
... ...
@@ -24,7 +24,7 @@ type Output interface {
24 24
 
25 25
 type Vertex interface {
26 26
 	Validate(context.Context) error
27
-	Marshal(context.Context, *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error)
27
+	Marshal(context.Context, *Constraints) (digest.Digest, []byte, *pb.OpMetadata, []*SourceLocation, error)
28 28
 	Output() Output
29 29
 	Inputs() []Output
30 30
 }
... ...
@@ -124,7 +124,9 @@ func (s State) Marshal(ctx context.Context, co ...ConstraintsOpt) (*Definition,
124 124
 		o.SetConstraintsOption(c)
125 125
 	}
126 126
 
127
-	def, err := marshal(ctx, s.Output().Vertex(ctx), def, map[digest.Digest]struct{}{}, map[Vertex]struct{}{}, c)
127
+	smc := newSourceMapCollector()
128
+
129
+	def, err := marshal(ctx, s.Output().Vertex(ctx), def, smc, map[digest.Digest]struct{}{}, map[Vertex]struct{}{}, c)
128 130
 	if err != nil {
129 131
 		return def, err
130 132
 	}
... ...
@@ -159,23 +161,28 @@ func (s State) Marshal(ctx context.Context, co ...ConstraintsOpt) (*Definition,
159 159
 	}
160 160
 
161 161
 	def.Metadata[dgst] = md
162
+	sm, err := smc.Marshal(ctx, co...)
163
+	if err != nil {
164
+		return nil, err
165
+	}
166
+	def.Source = sm
162 167
 
163 168
 	return def, nil
164 169
 }
165 170
 
166
-func marshal(ctx context.Context, v Vertex, def *Definition, cache map[digest.Digest]struct{}, vertexCache map[Vertex]struct{}, c *Constraints) (*Definition, error) {
171
+func marshal(ctx context.Context, v Vertex, def *Definition, s *sourceMapCollector, cache map[digest.Digest]struct{}, vertexCache map[Vertex]struct{}, c *Constraints) (*Definition, error) {
167 172
 	if _, ok := vertexCache[v]; ok {
168 173
 		return def, nil
169 174
 	}
170 175
 	for _, inp := range v.Inputs() {
171 176
 		var err error
172
-		def, err = marshal(ctx, inp.Vertex(ctx), def, cache, vertexCache, c)
177
+		def, err = marshal(ctx, inp.Vertex(ctx), def, s, cache, vertexCache, c)
173 178
 		if err != nil {
174 179
 			return def, err
175 180
 		}
176 181
 	}
177 182
 
178
-	dgst, dt, opMeta, err := v.Marshal(ctx, c)
183
+	dgst, dt, opMeta, sls, err := v.Marshal(ctx, c)
179 184
 	if err != nil {
180 185
 		return def, err
181 186
 	}
... ...
@@ -186,6 +193,7 @@ func marshal(ctx context.Context, v Vertex, def *Definition, cache map[digest.Di
186 186
 	if _, ok := cache[dgst]; ok {
187 187
 		return def, nil
188 188
 	}
189
+	s.Add(dgst, sls)
189 190
 	def.Def = append(def.Def, dt)
190 191
 	cache[dgst] = struct{}{}
191 192
 	return def, nil
... ...
@@ -367,7 +375,7 @@ func (o *output) ToInput(ctx context.Context, c *Constraints) (*pb.Input, error)
367 367
 			return nil, err
368 368
 		}
369 369
 	}
370
-	dgst, _, _, err := o.vertex.Marshal(ctx, c)
370
+	dgst, _, _, _, err := o.vertex.Marshal(ctx, c)
371 371
 	if err != nil {
372 372
 		return nil, err
373 373
 	}
... ...
@@ -514,6 +522,7 @@ type Constraints struct {
514 514
 	Metadata          pb.OpMetadata
515 515
 	LocalUniqueID     string
516 516
 	Caps              *apicaps.CapSet
517
+	SourceLocations   []*SourceLocation
517 518
 }
518 519
 
519 520
 func Platform(p specs.Platform) ConstraintsOpt {
... ...
@@ -11,6 +11,7 @@ import (
11 11
 	"github.com/docker/docker/pkg/idtools"
12 12
 	"github.com/moby/buildkit/executor"
13 13
 	"github.com/moby/buildkit/identity"
14
+	"github.com/pkg/errors"
14 15
 )
15 16
 
16 17
 const hostsContent = `
... ...
@@ -41,7 +42,7 @@ func makeHostsFile(stateDir string, extraHosts []executor.HostIP, idmap *idtools
41 41
 	if err == nil {
42 42
 		return "", func() {}, nil
43 43
 	}
44
-	if !os.IsNotExist(err) {
44
+	if !errors.Is(err, os.ErrNotExist) {
45 45
 		return "", nil, err
46 46
 	}
47 47
 
... ...
@@ -68,7 +68,7 @@ func withROBind(src, dest string) func(m []specs.Mount) ([]specs.Mount, error) {
68 68
 			Destination: dest,
69 69
 			Type:        "bind",
70 70
 			Source:      src,
71
-			Options:     []string{"rbind", "ro"},
71
+			Options:     []string{"nosuid", "noexec", "nodev", "rbind", "ro"},
72 72
 		})
73 73
 		return m, nil
74 74
 	}
... ...
@@ -10,6 +10,7 @@ import (
10 10
 	"github.com/docker/libnetwork/resolvconf"
11 11
 	"github.com/docker/libnetwork/types"
12 12
 	"github.com/moby/buildkit/util/flightcontrol"
13
+	"github.com/pkg/errors"
13 14
 )
14 15
 
15 16
 var g flightcontrol.Group
... ...
@@ -34,7 +35,7 @@ func GetResolvConf(ctx context.Context, stateDir string, idmap *idtools.Identity
34 34
 		if !generate {
35 35
 			fi, err := os.Stat(p)
36 36
 			if err != nil {
37
-				if !os.IsNotExist(err) {
37
+				if !errors.Is(err, os.ErrNotExist) {
38 38
 					return "", err
39 39
 				}
40 40
 				generate = true
... ...
@@ -42,7 +43,7 @@ func GetResolvConf(ctx context.Context, stateDir string, idmap *idtools.Identity
42 42
 			if !generate {
43 43
 				fiMain, err := os.Stat(resolvconf.Path())
44 44
 				if err != nil {
45
-					if !os.IsNotExist(err) {
45
+					if !errors.Is(err, os.ErrNotExist) {
46 46
 						return nil, err
47 47
 					}
48 48
 					if lastNotEmpty {
... ...
@@ -64,7 +65,7 @@ func GetResolvConf(ctx context.Context, stateDir string, idmap *idtools.Identity
64 64
 		var dt []byte
65 65
 		f, err := resolvconfGet()
66 66
 		if err != nil {
67
-			if !os.IsNotExist(err) {
67
+			if !errors.Is(err, os.ErrNotExist) {
68 68
 				return "", err
69 69
 			}
70 70
 		} else {
... ...
@@ -2,7 +2,6 @@ package oci
2 2
 
3 3
 import (
4 4
 	"context"
5
-	"errors"
6 5
 	"os"
7 6
 	"strconv"
8 7
 	"strings"
... ...
@@ -11,7 +10,8 @@ import (
11 11
 	containerdoci "github.com/containerd/containerd/oci"
12 12
 	"github.com/containerd/continuity/fs"
13 13
 	"github.com/opencontainers/runc/libcontainer/user"
14
-	"github.com/opencontainers/runtime-spec/specs-go"
14
+	specs "github.com/opencontainers/runtime-spec/specs-go"
15
+	"github.com/pkg/errors"
15 16
 )
16 17
 
17 18
 func GetUser(ctx context.Context, root, username string) (uint32, uint32, []uint32, error) {
... ...
@@ -23,6 +23,7 @@ import (
23 23
 	"github.com/moby/buildkit/solver/pb"
24 24
 	"github.com/moby/buildkit/util/network"
25 25
 	rootlessspecconv "github.com/moby/buildkit/util/rootless/specconv"
26
+	"github.com/moby/buildkit/util/stack"
26 27
 	"github.com/pkg/errors"
27 28
 	"github.com/sirupsen/logrus"
28 29
 )
... ...
@@ -302,7 +303,7 @@ func (w *runcExecutor) Exec(ctx context.Context, meta executor.Meta, root cache.
302 302
 		case <-ctx.Done():
303 303
 			return errors.Wrapf(ctx.Err(), err.Error())
304 304
 		default:
305
-			return err
305
+			return stack.Enable(err)
306 306
 		}
307 307
 	}
308 308
 
... ...
@@ -19,8 +19,10 @@ import (
19 19
 	"github.com/moby/buildkit/client/llb"
20 20
 	"github.com/moby/buildkit/exporter/containerimage/exptypes"
21 21
 	"github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb"
22
+	"github.com/moby/buildkit/frontend/dockerfile/parser"
22 23
 	"github.com/moby/buildkit/frontend/gateway/client"
23 24
 	gwpb "github.com/moby/buildkit/frontend/gateway/pb"
25
+	"github.com/moby/buildkit/solver/errdefs"
24 26
 	"github.com/moby/buildkit/solver/pb"
25 27
 	"github.com/moby/buildkit/util/apicaps"
26 28
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
... ...
@@ -226,6 +228,8 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
226 226
 		return nil, errors.Wrapf(err, "failed to marshal local source")
227 227
 	}
228 228
 
229
+	var sourceMap *llb.SourceMap
230
+
229 231
 	eg, ctx2 := errgroup.WithContext(ctx)
230 232
 	var dtDockerfile []byte
231 233
 	var dtDockerignore []byte
... ...
@@ -250,6 +254,9 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
250 250
 			return errors.Wrapf(err, "failed to read dockerfile")
251 251
 		}
252 252
 
253
+		sourceMap = llb.NewSourceMap(&src, filename, dtDockerfile)
254
+		sourceMap.Definition = def
255
+
253 256
 		dt, err := ref.ReadFile(ctx2, client.ReadRequest{
254 257
 			Filename: filename + ".dockerignore",
255 258
 		})
... ...
@@ -310,9 +317,13 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
310 310
 	}
311 311
 
312 312
 	if _, ok := opts["cmdline"]; !ok {
313
-		ref, cmdline, ok := dockerfile2llb.DetectSyntax(bytes.NewBuffer(dtDockerfile))
313
+		ref, cmdline, loc, ok := dockerfile2llb.DetectSyntax(bytes.NewBuffer(dtDockerfile))
314 314
 		if ok {
315
-			return forwardGateway(ctx, c, ref, cmdline)
315
+			res, err := forwardGateway(ctx, c, ref, cmdline)
316
+			if err != nil && len(errdefs.Sources(err)) == 0 {
317
+				return nil, wrapSource(err, sourceMap, loc)
318
+			}
319
+			return res, err
316 320
 		}
317 321
 	}
318 322
 
... ...
@@ -338,7 +349,13 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
338 338
 
339 339
 	for i, tp := range targetPlatforms {
340 340
 		func(i int, tp *specs.Platform) {
341
-			eg.Go(func() error {
341
+			eg.Go(func() (err error) {
342
+				defer func() {
343
+					var el *parser.ErrorLocation
344
+					if errors.As(err, &el) {
345
+						err = wrapSource(err, sourceMap, el.Location)
346
+					}
347
+				}()
342 348
 				st, img, err := dockerfile2llb.Dockerfile2LLB(ctx, dtDockerfile, dockerfile2llb.ConvertOpt{
343 349
 					Target:            opts[keyTarget],
344 350
 					MetaResolver:      c,
... ...
@@ -357,6 +374,7 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
357 357
 					ForceNetMode:      defaultNetMode,
358 358
 					OverrideCopyImage: opts[keyOverrideCopyImage],
359 359
 					LLBCaps:           &caps,
360
+					SourceMap:         sourceMap,
360 361
 				})
361 362
 
362 363
 				if err != nil {
... ...
@@ -639,3 +657,30 @@ func scopeToSubDir(c *llb.State, fileop bool, dir string) *llb.State {
639 639
 	bc := unpack.AddMount("/out", llb.Scratch())
640 640
 	return &bc
641 641
 }
642
+
643
+func wrapSource(err error, sm *llb.SourceMap, ranges []parser.Range) error {
644
+	if sm == nil {
645
+		return err
646
+	}
647
+	s := errdefs.Source{
648
+		Info: &pb.SourceInfo{
649
+			Data:       sm.Data,
650
+			Filename:   sm.Filename,
651
+			Definition: sm.Definition.ToPB(),
652
+		},
653
+		Ranges: make([]*pb.Range, 0, len(ranges)),
654
+	}
655
+	for _, r := range ranges {
656
+		s.Ranges = append(s.Ranges, &pb.Range{
657
+			Start: pb.Position{
658
+				Line:      int32(r.Start.Line),
659
+				Character: int32(r.Start.Character),
660
+			},
661
+			End: pb.Position{
662
+				Line:      int32(r.End.Line),
663
+				Character: int32(r.End.Character),
664
+			},
665
+		})
666
+	}
667
+	return errdefs.WithSource(err, s)
668
+}
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"fmt"
8 8
 	"math"
9 9
 	"net/url"
10
+	"os"
10 11
 	"path"
11 12
 	"path/filepath"
12 13
 	"sort"
... ...
@@ -60,6 +61,7 @@ type ConvertOpt struct {
60 60
 	OverrideCopyImage string
61 61
 	LLBCaps           *apicaps.CapSet
62 62
 	ContextLocalName  string
63
+	SourceMap         *llb.SourceMap
63 64
 }
64 65
 
65 66
 func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, *Image, error) {
... ...
@@ -110,10 +112,10 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
110 110
 	for i, st := range stages {
111 111
 		name, err := shlex.ProcessWordWithMap(st.BaseName, metaArgsToMap(optMetaArgs))
112 112
 		if err != nil {
113
-			return nil, nil, err
113
+			return nil, nil, parser.WithLocation(err, st.Location)
114 114
 		}
115 115
 		if name == "" {
116
-			return nil, nil, errors.Errorf("base name (%s) should not be blank", st.BaseName)
116
+			return nil, nil, parser.WithLocation(errors.Errorf("base name (%s) should not be blank", st.BaseName), st.Location)
117 117
 		}
118 118
 		st.BaseName = name
119 119
 
... ...
@@ -132,12 +134,12 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
132 132
 		if v := st.Platform; v != "" {
133 133
 			v, err := shlex.ProcessWordWithMap(v, metaArgsToMap(optMetaArgs))
134 134
 			if err != nil {
135
-				return nil, nil, errors.Wrapf(err, "failed to process arguments for platform %s", v)
135
+				return nil, nil, parser.WithLocation(errors.Wrapf(err, "failed to process arguments for platform %s", v), st.Location)
136 136
 			}
137 137
 
138 138
 			p, err := platforms.Parse(v)
139 139
 			if err != nil {
140
-				return nil, nil, errors.Wrapf(err, "failed to parse platform %s", v)
140
+				return nil, nil, parser.WithLocation(errors.Wrapf(err, "failed to parse platform %s", v), st.Location)
141 141
 			}
142 142
 			ds.platform = &p
143 143
 		}
... ...
@@ -204,7 +206,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
204 204
 	}
205 205
 
206 206
 	if has, state := hasCircularDependency(allDispatchStates.states); has {
207
-		return nil, nil, fmt.Errorf("circular dependency detected on stage: %s", state.stageName)
207
+		return nil, nil, errors.Errorf("circular dependency detected on stage: %s", state.stageName)
208 208
 	}
209 209
 
210 210
 	if len(allDispatchStates.states) == 1 {
... ...
@@ -225,7 +227,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
225 225
 				eg.Go(func() error {
226 226
 					ref, err := reference.ParseNormalizedNamed(d.stage.BaseName)
227 227
 					if err != nil {
228
-						return errors.Wrapf(err, "failed to parse stage name %q", d.stage.BaseName)
228
+						return parser.WithLocation(errors.Wrapf(err, "failed to parse stage name %q", d.stage.BaseName), d.stage.Location)
229 229
 					}
230 230
 					platform := d.platform
231 231
 					if platform == nil {
... ...
@@ -278,7 +280,13 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
278 278
 					if isScratch {
279 279
 						d.state = llb.Scratch()
280 280
 					} else {
281
-						d.state = llb.Image(d.stage.BaseName, dfCmd(d.stage.SourceCode), llb.Platform(*platform), opt.ImageResolveMode, llb.WithCustomName(prefixCommand(d, "FROM "+d.stage.BaseName, opt.PrefixPlatform, platform)))
281
+						d.state = llb.Image(d.stage.BaseName,
282
+							dfCmd(d.stage.SourceCode),
283
+							llb.Platform(*platform),
284
+							opt.ImageResolveMode,
285
+							llb.WithCustomName(prefixCommand(d, "FROM "+d.stage.BaseName, opt.PrefixPlatform, platform)),
286
+							location(opt.SourceMap, d.stage.Location),
287
+						)
282 288
 					}
283 289
 					d.platform = platform
284 290
 					return nil
... ...
@@ -316,12 +324,12 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
316 316
 		}
317 317
 		if d.image.Config.WorkingDir != "" {
318 318
 			if err = dispatchWorkdir(d, &instructions.WorkdirCommand{Path: d.image.Config.WorkingDir}, false, nil); err != nil {
319
-				return nil, nil, err
319
+				return nil, nil, parser.WithLocation(err, d.stage.Location)
320 320
 			}
321 321
 		}
322 322
 		if d.image.Config.User != "" {
323 323
 			if err = dispatchUser(d, &instructions.UserCommand{User: d.image.Config.User}, false); err != nil {
324
-				return nil, nil, err
324
+				return nil, nil, parser.WithLocation(err, d.stage.Location)
325 325
 			}
326 326
 		}
327 327
 		d.state = d.state.Network(opt.ForceNetMode)
... ...
@@ -340,19 +348,20 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
340 340
 			extraHosts:        opt.ExtraHosts,
341 341
 			copyImage:         opt.OverrideCopyImage,
342 342
 			llbCaps:           opt.LLBCaps,
343
+			sourceMap:         opt.SourceMap,
343 344
 		}
344 345
 		if opt.copyImage == "" {
345 346
 			opt.copyImage = DefaultCopyImage
346 347
 		}
347 348
 
348 349
 		if err = dispatchOnBuildTriggers(d, d.image.Config.OnBuild, opt); err != nil {
349
-			return nil, nil, err
350
+			return nil, nil, parser.WithLocation(err, d.stage.Location)
350 351
 		}
351 352
 		d.image.Config.OnBuild = nil
352 353
 
353 354
 		for _, cmd := range d.commands {
354 355
 			if err := dispatch(d, cmd, opt); err != nil {
355
-				return nil, nil, err
356
+				return nil, nil, parser.WithLocation(err, cmd.Location())
356 357
 			}
357 358
 		}
358 359
 
... ...
@@ -421,7 +430,7 @@ func toCommand(ic instructions.Command, allDispatchStates *dispatchStates) (comm
421 421
 				stn, ok = allDispatchStates.findStateByName(c.From)
422 422
 				if !ok {
423 423
 					stn = &dispatchState{
424
-						stage:        instructions.Stage{BaseName: c.From},
424
+						stage:        instructions.Stage{BaseName: c.From, Location: ic.Location()},
425 425
 						deps:         make(map[*dispatchState]struct{}),
426 426
 						unregistered: true,
427 427
 					}
... ...
@@ -457,6 +466,7 @@ type dispatchOpt struct {
457 457
 	extraHosts        []llb.HostIP
458 458
 	copyImage         string
459 459
 	llbCaps           *apicaps.CapSet
460
+	sourceMap         *llb.SourceMap
460 461
 }
461 462
 
462 463
 func dispatch(d *dispatchState, cmd command, opt dispatchOpt) error {
... ...
@@ -484,7 +494,7 @@ func dispatch(d *dispatchState, cmd command, opt dispatchOpt) error {
484 484
 	case *instructions.WorkdirCommand:
485 485
 		err = dispatchWorkdir(d, c, true, &opt)
486 486
 	case *instructions.AddCommand:
487
-		err = dispatchCopy(d, c.SourcesAndDest, opt.buildContext, true, c, c.Chown, opt)
487
+		err = dispatchCopy(d, c.SourcesAndDest, opt.buildContext, true, c, c.Chown, c.Chmod, c.Location(), opt)
488 488
 		if err == nil {
489 489
 			for _, src := range c.Sources() {
490 490
 				if !strings.HasPrefix(src, "http://") && !strings.HasPrefix(src, "https://") {
... ...
@@ -519,7 +529,7 @@ func dispatch(d *dispatchState, cmd command, opt dispatchOpt) error {
519 519
 		if len(cmd.sources) != 0 {
520 520
 			l = cmd.sources[0].state
521 521
 		}
522
-		err = dispatchCopy(d, c.SourcesAndDest, l, false, c, c.Chown, opt)
522
+		err = dispatchCopy(d, c.SourcesAndDest, l, false, c, c.Chown, c.Chmod, c.Location(), opt)
523 523
 		if err == nil && len(cmd.sources) == 0 {
524 524
 			for _, src := range c.Sources() {
525 525
 				d.ctxPaths[path.Join("/", filepath.ToSlash(src))] = struct{}{}
... ...
@@ -634,7 +644,7 @@ func dispatchRun(d *dispatchState, c *instructions.RunCommand, proxy *llb.ProxyE
634 634
 	if err != nil {
635 635
 		return err
636 636
 	}
637
-	opt := []llb.RunOption{llb.Args(args), dfCmd(c)}
637
+	opt := []llb.RunOption{llb.Args(args), dfCmd(c), location(dopt.sourceMap, c.Location())}
638 638
 	if d.ignoreCache {
639 639
 		opt = append(opt, llb.IgnoreCache)
640 640
 	}
... ...
@@ -702,7 +712,10 @@ func dispatchWorkdir(d *dispatchState, c *instructions.WorkdirCommand, commit bo
702 702
 			if err != nil {
703 703
 				return err
704 704
 			}
705
-			d.state = d.state.File(llb.Mkdir(wd, 0755, mkdirOpt...), llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, c.String(), env)), d.prefixPlatform, &platform)))
705
+			d.state = d.state.File(llb.Mkdir(wd, 0755, mkdirOpt...),
706
+				llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, c.String(), env)), d.prefixPlatform, &platform)),
707
+				location(opt.sourceMap, c.Location()),
708
+			)
706 709
 			withLayer = true
707 710
 		}
708 711
 		return commitToHistory(&d.image, "WORKDIR "+wd, withLayer, nil)
... ...
@@ -710,7 +723,7 @@ func dispatchWorkdir(d *dispatchState, c *instructions.WorkdirCommand, commit bo
710 710
 	return nil
711 711
 }
712 712
 
713
-func dispatchCopyFileOp(d *dispatchState, c instructions.SourcesAndDest, sourceState llb.State, isAddCommand bool, cmdToPrint fmt.Stringer, chown string, opt dispatchOpt) error {
713
+func dispatchCopyFileOp(d *dispatchState, c instructions.SourcesAndDest, sourceState llb.State, isAddCommand bool, cmdToPrint fmt.Stringer, chown string, chmod string, loc []parser.Range, opt dispatchOpt) error {
714 714
 	pp, err := pathRelativeToWorkingDir(d.state, c.Dest())
715 715
 	if err != nil {
716 716
 		return err
... ...
@@ -726,6 +739,15 @@ func dispatchCopyFileOp(d *dispatchState, c instructions.SourcesAndDest, sourceS
726 726
 		copyOpt = append(copyOpt, llb.WithUser(chown))
727 727
 	}
728 728
 
729
+	var mode *os.FileMode
730
+	if chmod != "" {
731
+		p, err := strconv.ParseUint(chmod, 8, 32)
732
+		if err == nil {
733
+			perm := os.FileMode(p)
734
+			mode = &perm
735
+		}
736
+	}
737
+
729 738
 	commitMessage := bytes.NewBufferString("")
730 739
 	if isAddCommand {
731 740
 		commitMessage.WriteString("ADD")
... ...
@@ -768,6 +790,7 @@ func dispatchCopyFileOp(d *dispatchState, c instructions.SourcesAndDest, sourceS
768 768
 			}
769 769
 		} else {
770 770
 			opts := append([]llb.CopyOption{&llb.CopyInfo{
771
+				Mode:                mode,
771 772
 				FollowSymlinks:      true,
772 773
 				CopyDirContentsOnly: true,
773 774
 				AttemptUnpack:       isAddCommand,
... ...
@@ -796,7 +819,10 @@ func dispatchCopyFileOp(d *dispatchState, c instructions.SourcesAndDest, sourceS
796 796
 		return err
797 797
 	}
798 798
 
799
-	fileOpt := []llb.ConstraintsOpt{llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, cmdToPrint.String(), env)), d.prefixPlatform, &platform))}
799
+	fileOpt := []llb.ConstraintsOpt{
800
+		llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, cmdToPrint.String(), env)), d.prefixPlatform, &platform)),
801
+		location(opt.sourceMap, loc),
802
+	}
800 803
 	if d.ignoreCache {
801 804
 		fileOpt = append(fileOpt, llb.IgnoreCache)
802 805
 	}
... ...
@@ -805,9 +831,16 @@ func dispatchCopyFileOp(d *dispatchState, c instructions.SourcesAndDest, sourceS
805 805
 	return commitToHistory(&d.image, commitMessage.String(), true, &d.state)
806 806
 }
807 807
 
808
-func dispatchCopy(d *dispatchState, c instructions.SourcesAndDest, sourceState llb.State, isAddCommand bool, cmdToPrint fmt.Stringer, chown string, opt dispatchOpt) error {
808
+func dispatchCopy(d *dispatchState, c instructions.SourcesAndDest, sourceState llb.State, isAddCommand bool, cmdToPrint fmt.Stringer, chown string, chmod string, loc []parser.Range, opt dispatchOpt) error {
809 809
 	if useFileOp(opt.buildArgValues, opt.llbCaps) {
810
-		return dispatchCopyFileOp(d, c, sourceState, isAddCommand, cmdToPrint, chown, opt)
810
+		return dispatchCopyFileOp(d, c, sourceState, isAddCommand, cmdToPrint, chown, chmod, loc, opt)
811
+	}
812
+
813
+	if chmod != "" {
814
+		if opt.llbCaps != nil && opt.llbCaps.Supports(pb.CapFileBase) != nil {
815
+			return errors.Wrap(opt.llbCaps.Supports(pb.CapFileBase), "chmod is not supported")
816
+		}
817
+		return errors.New("chmod is not supported")
811 818
 	}
812 819
 
813 820
 	img := llb.Image(opt.copyImage, llb.MarkImageInternal, llb.Platform(opt.buildPlatforms[0]), WithInternalName("helper image for file operations"))
... ...
@@ -893,7 +926,14 @@ func dispatchCopy(d *dispatchState, c instructions.SourcesAndDest, sourceState l
893 893
 		return err
894 894
 	}
895 895
 
896
-	runOpt := []llb.RunOption{llb.Args(args), llb.Dir("/dest"), llb.ReadonlyRootFS(), dfCmd(cmdToPrint), llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, cmdToPrint.String(), env)), d.prefixPlatform, &platform))}
896
+	runOpt := []llb.RunOption{
897
+		llb.Args(args),
898
+		llb.Dir("/dest"),
899
+		llb.ReadonlyRootFS(),
900
+		dfCmd(cmdToPrint),
901
+		llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, cmdToPrint.String(), env)), d.prefixPlatform, &platform)),
902
+		location(opt.sourceMap, loc),
903
+	}
897 904
 	if d.ignoreCache {
898 905
 		runOpt = append(runOpt, llb.IgnoreCache)
899 906
 	}
... ...
@@ -1361,3 +1401,20 @@ func useFileOp(args map[string]string, caps *apicaps.CapSet) bool {
1361 1361
 	}
1362 1362
 	return enabled && caps != nil && caps.Supports(pb.CapFileBase) == nil
1363 1363
 }
1364
+
1365
+func location(sm *llb.SourceMap, locations []parser.Range) llb.ConstraintsOpt {
1366
+	loc := make([]*pb.Range, 0, len(locations))
1367
+	for _, l := range locations {
1368
+		loc = append(loc, &pb.Range{
1369
+			Start: pb.Position{
1370
+				Line:      int32(l.Start.Line),
1371
+				Character: int32(l.Start.Character),
1372
+			},
1373
+			End: pb.Position{
1374
+				Line:      int32(l.End.Line),
1375
+				Character: int32(l.End.Character),
1376
+			},
1377
+		})
1378
+	}
1379
+	return sm.Location(loc)
1380
+}
... ...
@@ -5,34 +5,51 @@ import (
5 5
 	"io"
6 6
 	"regexp"
7 7
 	"strings"
8
+
9
+	"github.com/moby/buildkit/frontend/dockerfile/parser"
8 10
 )
9 11
 
10 12
 const keySyntax = "syntax"
11 13
 
12 14
 var reDirective = regexp.MustCompile(`^#\s*([a-zA-Z][a-zA-Z0-9]*)\s*=\s*(.+?)\s*$`)
13 15
 
14
-func DetectSyntax(r io.Reader) (string, string, bool) {
16
+type Directive struct {
17
+	Name     string
18
+	Value    string
19
+	Location []parser.Range
20
+}
21
+
22
+func DetectSyntax(r io.Reader) (string, string, []parser.Range, bool) {
15 23
 	directives := ParseDirectives(r)
16 24
 	if len(directives) == 0 {
17
-		return "", "", false
25
+		return "", "", nil, false
18 26
 	}
19 27
 	v, ok := directives[keySyntax]
20 28
 	if !ok {
21
-		return "", "", false
29
+		return "", "", nil, false
22 30
 	}
23
-	p := strings.SplitN(v, " ", 2)
24
-	return p[0], v, true
31
+	p := strings.SplitN(v.Value, " ", 2)
32
+	return p[0], v.Value, v.Location, true
25 33
 }
26 34
 
27
-func ParseDirectives(r io.Reader) map[string]string {
28
-	m := map[string]string{}
35
+func ParseDirectives(r io.Reader) map[string]Directive {
36
+	m := map[string]Directive{}
29 37
 	s := bufio.NewScanner(r)
38
+	var l int
30 39
 	for s.Scan() {
40
+		l++
31 41
 		match := reDirective.FindStringSubmatch(s.Text())
32 42
 		if len(match) == 0 {
33 43
 			return m
34 44
 		}
35
-		m[strings.ToLower(match[1])] = match[2]
45
+		m[strings.ToLower(match[1])] = Directive{
46
+			Name:  match[1],
47
+			Value: match[2],
48
+			Location: []parser.Range{{
49
+				Start: parser.Position{Line: l},
50
+				End:   parser.Position{Line: l},
51
+			}},
52
+		}
36 53
 	}
37 54
 	return m
38 55
 }
... ...
@@ -1,11 +1,12 @@
1 1
 package instructions
2 2
 
3 3
 import (
4
-	"errors"
5 4
 	"strings"
6 5
 
7 6
 	"github.com/docker/docker/api/types/container"
8 7
 	"github.com/docker/docker/api/types/strslice"
8
+	"github.com/moby/buildkit/frontend/dockerfile/parser"
9
+	"github.com/pkg/errors"
9 10
 )
10 11
 
11 12
 // KeyValuePair represent an arbitrary named value (useful in slice instead of map[string] string to preserve ordering)
... ...
@@ -35,6 +36,7 @@ func (kvpo *KeyValuePairOptional) ValueString() string {
35 35
 // Command is implemented by every command present in a dockerfile
36 36
 type Command interface {
37 37
 	Name() string
38
+	Location() []parser.Range
38 39
 }
39 40
 
40 41
 // KeyValuePairs is a slice of KeyValuePair
... ...
@@ -42,8 +44,9 @@ type KeyValuePairs []KeyValuePair
42 42
 
43 43
 // withNameAndCode is the base of every command in a Dockerfile (String() returns its source code)
44 44
 type withNameAndCode struct {
45
-	code string
46
-	name string
45
+	code     string
46
+	name     string
47
+	location []parser.Range
47 48
 }
48 49
 
49 50
 func (c *withNameAndCode) String() string {
... ...
@@ -55,8 +58,13 @@ func (c *withNameAndCode) Name() string {
55 55
 	return c.name
56 56
 }
57 57
 
58
+// Location of the command in source
59
+func (c *withNameAndCode) Location() []parser.Range {
60
+	return c.location
61
+}
62
+
58 63
 func newWithNameAndCode(req parseRequest) withNameAndCode {
59
-	return withNameAndCode{code: strings.TrimSpace(req.original), name: req.command}
64
+	return withNameAndCode{code: strings.TrimSpace(req.original), name: req.command, location: req.location}
60 65
 }
61 66
 
62 67
 // SingleWordExpander is a provider for variable expansion where 1 word => 1 output
... ...
@@ -180,10 +188,16 @@ type AddCommand struct {
180 180
 	withNameAndCode
181 181
 	SourcesAndDest
182 182
 	Chown string
183
+	Chmod string
183 184
 }
184 185
 
185 186
 // Expand variables
186 187
 func (c *AddCommand) Expand(expander SingleWordExpander) error {
188
+	expandedChown, err := expander(c.Chown)
189
+	if err != nil {
190
+		return err
191
+	}
192
+	c.Chown = expandedChown
187 193
 	return expandSliceInPlace(c.SourcesAndDest, expander)
188 194
 }
189 195
 
... ...
@@ -196,6 +210,7 @@ type CopyCommand struct {
196 196
 	SourcesAndDest
197 197
 	From  string
198 198
 	Chown string
199
+	Chmod string
199 200
 }
200 201
 
201 202
 // Expand variables
... ...
@@ -400,6 +415,7 @@ type Stage struct {
400 400
 	BaseName   string
401 401
 	SourceCode string
402 402
 	Platform   string
403
+	Location   []parser.Range
403 404
 }
404 405
 
405 406
 // AddCommand to the stage
... ...
@@ -419,7 +435,7 @@ func IsCurrentStage(s []Stage, name string) bool {
419 419
 // CurrentStage return the last stage in a slice
420 420
 func CurrentStage(s []Stage) (*Stage, error) {
421 421
 	if len(s) == 0 {
422
-		return nil, errors.New("No build stage in current context")
422
+		return nil, errors.New("no build stage in current context")
423 423
 	}
424 424
 	return &s[len(s)-1], nil
425 425
 }
... ...
@@ -21,6 +21,7 @@ type parseRequest struct {
21 21
 	attributes map[string]bool
22 22
 	flags      *BFlags
23 23
 	original   string
24
+	location   []parser.Range
24 25
 }
25 26
 
26 27
 var parseRunPreHooks []func(*RunCommand, parseRequest) error
... ...
@@ -48,11 +49,15 @@ func newParseRequestFromNode(node *parser.Node) parseRequest {
48 48
 		attributes: node.Attributes,
49 49
 		original:   node.Original,
50 50
 		flags:      NewBFlagsWithArgs(node.Flags),
51
+		location:   node.Location(),
51 52
 	}
52 53
 }
53 54
 
54 55
 // ParseInstruction converts an AST to a typed instruction (either a command or a build stage beginning when encountering a `FROM` statement)
55
-func ParseInstruction(node *parser.Node) (interface{}, error) {
56
+func ParseInstruction(node *parser.Node) (v interface{}, err error) {
57
+	defer func() {
58
+		err = parser.WithLocation(err, node.Location())
59
+	}()
56 60
 	req := newParseRequestFromNode(node)
57 61
 	switch node.Value {
58 62
 	case command.Env:
... ...
@@ -105,7 +110,7 @@ func ParseCommand(node *parser.Node) (Command, error) {
105 105
 	if c, ok := s.(Command); ok {
106 106
 		return c, nil
107 107
 	}
108
-	return nil, errors.Errorf("%T is not a command type", s)
108
+	return nil, parser.WithLocation(errors.Errorf("%T is not a command type", s), node.Location())
109 109
 }
110 110
 
111 111
 // UnknownInstruction represents an error occurring when a command is unresolvable
... ...
@@ -118,25 +123,17 @@ func (e *UnknownInstruction) Error() string {
118 118
 	return fmt.Sprintf("unknown instruction: %s", strings.ToUpper(e.Instruction))
119 119
 }
120 120
 
121
-// IsUnknownInstruction checks if the error is an UnknownInstruction or a parseError containing an UnknownInstruction
122
-func IsUnknownInstruction(err error) bool {
123
-	_, ok := err.(*UnknownInstruction)
124
-	if !ok {
125
-		var pe *parseError
126
-		if pe, ok = err.(*parseError); ok {
127
-			_, ok = pe.inner.(*UnknownInstruction)
128
-		}
129
-	}
130
-	return ok
131
-}
132
-
133 121
 type parseError struct {
134 122
 	inner error
135 123
 	node  *parser.Node
136 124
 }
137 125
 
138 126
 func (e *parseError) Error() string {
139
-	return fmt.Sprintf("Dockerfile parse error line %d: %v", e.node.StartLine, e.inner.Error())
127
+	return fmt.Sprintf("dockerfile parse error line %d: %v", e.node.StartLine, e.inner.Error())
128
+}
129
+
130
+func (e *parseError) Unwrap() error {
131
+	return e.inner
140 132
 }
141 133
 
142 134
 // Parse a Dockerfile into a collection of buildable stages.
... ...
@@ -160,11 +157,11 @@ func Parse(ast *parser.Node) (stages []Stage, metaArgs []ArgCommand, err error)
160 160
 		case Command:
161 161
 			stage, err := CurrentStage(stages)
162 162
 			if err != nil {
163
-				return nil, nil, err
163
+				return nil, nil, parser.WithLocation(err, n.Location())
164 164
 			}
165 165
 			stage.AddCommand(c)
166 166
 		default:
167
-			return nil, nil, errors.Errorf("%T is not a command type", cmd)
167
+			return nil, nil, parser.WithLocation(errors.Errorf("%T is not a command type", cmd), n.Location())
168 168
 		}
169 169
 
170 170
 	}
... ...
@@ -242,6 +239,7 @@ func parseAdd(req parseRequest) (*AddCommand, error) {
242 242
 		return nil, errNoDestinationArgument("ADD")
243 243
 	}
244 244
 	flChown := req.flags.AddString("chown", "")
245
+	flChmod := req.flags.AddString("chmod", "")
245 246
 	if err := req.flags.Parse(); err != nil {
246 247
 		return nil, err
247 248
 	}
... ...
@@ -249,6 +247,7 @@ func parseAdd(req parseRequest) (*AddCommand, error) {
249 249
 		SourcesAndDest:  SourcesAndDest(req.args),
250 250
 		withNameAndCode: newWithNameAndCode(req),
251 251
 		Chown:           flChown.Value,
252
+		Chmod:           flChmod.Value,
252 253
 	}, nil
253 254
 }
254 255
 
... ...
@@ -258,6 +257,7 @@ func parseCopy(req parseRequest) (*CopyCommand, error) {
258 258
 	}
259 259
 	flChown := req.flags.AddString("chown", "")
260 260
 	flFrom := req.flags.AddString("from", "")
261
+	flChmod := req.flags.AddString("chmod", "")
261 262
 	if err := req.flags.Parse(); err != nil {
262 263
 		return nil, err
263 264
 	}
... ...
@@ -266,6 +266,7 @@ func parseCopy(req parseRequest) (*CopyCommand, error) {
266 266
 		From:            flFrom.Value,
267 267
 		withNameAndCode: newWithNameAndCode(req),
268 268
 		Chown:           flChown.Value,
269
+		Chmod:           flChmod.Value,
269 270
 	}, nil
270 271
 }
271 272
 
... ...
@@ -287,6 +288,7 @@ func parseFrom(req parseRequest) (*Stage, error) {
287 287
 		SourceCode: code,
288 288
 		Commands:   []Command{},
289 289
 		Platform:   flPlatform.Value,
290
+		Location:   req.location,
290 291
 	}, nil
291 292
 
292 293
 }
293 294
new file mode 100644
... ...
@@ -0,0 +1,58 @@
0
+package parser
1
+
2
+import (
3
+	"github.com/moby/buildkit/util/stack"
4
+	"github.com/pkg/errors"
5
+)
6
+
7
+// ErrorLocation gives a location in source code that caused the error
8
+type ErrorLocation struct {
9
+	Location []Range
10
+	error
11
+}
12
+
13
+// Unwrap unwraps to the next error
14
+func (e *ErrorLocation) Unwrap() error {
15
+	return e.error
16
+}
17
+
18
+// Range is a code section between two positions
19
+type Range struct {
20
+	Start Position
21
+	End   Position
22
+}
23
+
24
+// Position is a point in source code
25
+type Position struct {
26
+	Line      int
27
+	Character int
28
+}
29
+
30
+func withLocation(err error, start, end int) error {
31
+	return WithLocation(err, toRanges(start, end))
32
+}
33
+
34
+// WithLocation extends an error with a source code location
35
+func WithLocation(err error, location []Range) error {
36
+	if err == nil {
37
+		return nil
38
+	}
39
+	var el *ErrorLocation
40
+	if errors.As(err, &el) {
41
+		return err
42
+	}
43
+	return stack.Enable(&ErrorLocation{
44
+		error:    err,
45
+		Location: location,
46
+	})
47
+}
48
+
49
+func toRanges(start, end int) (r []Range) {
50
+	if end <= start {
51
+		end = start
52
+	}
53
+	for i := start; i <= end; i++ {
54
+		r = append(r, Range{Start: Position{Line: i}, End: Position{Line: i}})
55
+	}
56
+	return
57
+}
... ...
@@ -8,11 +8,12 @@ package parser
8 8
 
9 9
 import (
10 10
 	"encoding/json"
11
-	"errors"
12 11
 	"fmt"
13 12
 	"strings"
14 13
 	"unicode"
15 14
 	"unicode/utf8"
15
+
16
+	"github.com/pkg/errors"
16 17
 )
17 18
 
18 19
 var (
... ...
@@ -25,7 +26,7 @@ const (
25 25
 
26 26
 // ignore the current argument. This will still leave a command parsed, but
27 27
 // will not incorporate the arguments into the ast.
28
-func parseIgnore(rest string, d *Directive) (*Node, map[string]bool, error) {
28
+func parseIgnore(rest string, d *directives) (*Node, map[string]bool, error) {
29 29
 	return &Node{}, nil, nil
30 30
 }
31 31
 
... ...
@@ -34,7 +35,7 @@ func parseIgnore(rest string, d *Directive) (*Node, map[string]bool, error) {
34 34
 //
35 35
 // ONBUILD RUN foo bar -> (onbuild (run foo bar))
36 36
 //
37
-func parseSubCommand(rest string, d *Directive) (*Node, map[string]bool, error) {
37
+func parseSubCommand(rest string, d *directives) (*Node, map[string]bool, error) {
38 38
 	if rest == "" {
39 39
 		return nil, nil, nil
40 40
 	}
... ...
@@ -50,7 +51,7 @@ func parseSubCommand(rest string, d *Directive) (*Node, map[string]bool, error)
50 50
 // helper to parse words (i.e space delimited or quoted strings) in a statement.
51 51
 // The quotes are preserved as part of this function and they are stripped later
52 52
 // as part of processWords().
53
-func parseWords(rest string, d *Directive) []string {
53
+func parseWords(rest string, d *directives) []string {
54 54
 	const (
55 55
 		inSpaces = iota // looking for start of a word
56 56
 		inWord
... ...
@@ -137,7 +138,7 @@ func parseWords(rest string, d *Directive) []string {
137 137
 
138 138
 // parse environment like statements. Note that this does *not* handle
139 139
 // variable interpolation, which will be handled in the evaluator.
140
-func parseNameVal(rest string, key string, d *Directive) (*Node, error) {
140
+func parseNameVal(rest string, key string, d *directives) (*Node, error) {
141 141
 	// This is kind of tricky because we need to support the old
142 142
 	// variant:   KEY name value
143 143
 	// as well as the new one:    KEY name=value ...
... ...
@@ -151,7 +152,7 @@ func parseNameVal(rest string, key string, d *Directive) (*Node, error) {
151 151
 
152 152
 	// Old format (KEY name value)
153 153
 	if !strings.Contains(words[0], "=") {
154
-		parts := tokenWhitespace.Split(rest, 2)
154
+		parts := reWhitespace.Split(rest, 2)
155 155
 		if len(parts) < 2 {
156 156
 			return nil, fmt.Errorf(key + " must have two arguments")
157 157
 		}
... ...
@@ -192,12 +193,12 @@ func appendKeyValueNode(node, rootNode, prevNode *Node) (*Node, *Node) {
192 192
 	return rootNode, prevNode
193 193
 }
194 194
 
195
-func parseEnv(rest string, d *Directive) (*Node, map[string]bool, error) {
195
+func parseEnv(rest string, d *directives) (*Node, map[string]bool, error) {
196 196
 	node, err := parseNameVal(rest, "ENV", d)
197 197
 	return node, nil, err
198 198
 }
199 199
 
200
-func parseLabel(rest string, d *Directive) (*Node, map[string]bool, error) {
200
+func parseLabel(rest string, d *directives) (*Node, map[string]bool, error) {
201 201
 	node, err := parseNameVal(rest, commandLabel, d)
202 202
 	return node, nil, err
203 203
 }
... ...
@@ -210,7 +211,7 @@ func parseLabel(rest string, d *Directive) (*Node, map[string]bool, error) {
210 210
 // In addition, a keyword definition alone is of the form `keyword` like `name1`
211 211
 // above. And the assignments `name2=` and `name3=""` are equivalent and
212 212
 // assign an empty value to the respective keywords.
213
-func parseNameOrNameVal(rest string, d *Directive) (*Node, map[string]bool, error) {
213
+func parseNameOrNameVal(rest string, d *directives) (*Node, map[string]bool, error) {
214 214
 	words := parseWords(rest, d)
215 215
 	if len(words) == 0 {
216 216
 		return nil, nil, nil
... ...
@@ -236,7 +237,7 @@ func parseNameOrNameVal(rest string, d *Directive) (*Node, map[string]bool, erro
236 236
 
237 237
 // parses a whitespace-delimited set of arguments. The result is effectively a
238 238
 // linked list of string arguments.
239
-func parseStringsWhitespaceDelimited(rest string, d *Directive) (*Node, map[string]bool, error) {
239
+func parseStringsWhitespaceDelimited(rest string, d *directives) (*Node, map[string]bool, error) {
240 240
 	if rest == "" {
241 241
 		return nil, nil, nil
242 242
 	}
... ...
@@ -244,7 +245,7 @@ func parseStringsWhitespaceDelimited(rest string, d *Directive) (*Node, map[stri
244 244
 	node := &Node{}
245 245
 	rootnode := node
246 246
 	prevnode := node
247
-	for _, str := range tokenWhitespace.Split(rest, -1) { // use regexp
247
+	for _, str := range reWhitespace.Split(rest, -1) { // use regexp
248 248
 		prevnode = node
249 249
 		node.Value = str
250 250
 		node.Next = &Node{}
... ...
@@ -260,7 +261,7 @@ func parseStringsWhitespaceDelimited(rest string, d *Directive) (*Node, map[stri
260 260
 }
261 261
 
262 262
 // parseString just wraps the string in quotes and returns a working node.
263
-func parseString(rest string, d *Directive) (*Node, map[string]bool, error) {
263
+func parseString(rest string, d *directives) (*Node, map[string]bool, error) {
264 264
 	if rest == "" {
265 265
 		return nil, nil, nil
266 266
 	}
... ...
@@ -270,7 +271,7 @@ func parseString(rest string, d *Directive) (*Node, map[string]bool, error) {
270 270
 }
271 271
 
272 272
 // parseJSON converts JSON arrays to an AST.
273
-func parseJSON(rest string, d *Directive) (*Node, map[string]bool, error) {
273
+func parseJSON(rest string, d *directives) (*Node, map[string]bool, error) {
274 274
 	rest = strings.TrimLeftFunc(rest, unicode.IsSpace)
275 275
 	if !strings.HasPrefix(rest, "[") {
276 276
 		return nil, nil, fmt.Errorf(`Error parsing "%s" as a JSON array`, rest)
... ...
@@ -303,7 +304,7 @@ func parseJSON(rest string, d *Directive) (*Node, map[string]bool, error) {
303 303
 // parseMaybeJSON determines if the argument appears to be a JSON array. If
304 304
 // so, passes to parseJSON; if not, quotes the result and returns a single
305 305
 // node.
306
-func parseMaybeJSON(rest string, d *Directive) (*Node, map[string]bool, error) {
306
+func parseMaybeJSON(rest string, d *directives) (*Node, map[string]bool, error) {
307 307
 	if rest == "" {
308 308
 		return nil, nil, nil
309 309
 	}
... ...
@@ -325,7 +326,7 @@ func parseMaybeJSON(rest string, d *Directive) (*Node, map[string]bool, error) {
325 325
 // parseMaybeJSONToList determines if the argument appears to be a JSON array. If
326 326
 // so, passes to parseJSON; if not, attempts to parse it as a whitespace
327 327
 // delimited string.
328
-func parseMaybeJSONToList(rest string, d *Directive) (*Node, map[string]bool, error) {
328
+func parseMaybeJSONToList(rest string, d *directives) (*Node, map[string]bool, error) {
329 329
 	node, attrs, err := parseJSON(rest, d)
330 330
 
331 331
 	if err == nil {
... ...
@@ -339,7 +340,7 @@ func parseMaybeJSONToList(rest string, d *Directive) (*Node, map[string]bool, er
339 339
 }
340 340
 
341 341
 // The HEALTHCHECK command is like parseMaybeJSON, but has an extra type argument.
342
-func parseHealthConfig(rest string, d *Directive) (*Node, map[string]bool, error) {
342
+func parseHealthConfig(rest string, d *directives) (*Node, map[string]bool, error) {
343 343
 	// Find end of first argument
344 344
 	var sep int
345 345
 	for ; sep < len(rest); sep++ {
... ...
@@ -38,6 +38,11 @@ type Node struct {
38 38
 	EndLine    int             // the line in the original dockerfile where the node ends
39 39
 }
40 40
 
41
+// Location return the location of node in source code
42
+func (node *Node) Location() []Range {
43
+	return toRanges(node.StartLine, node.EndLine)
44
+}
45
+
41 46
 // Dump dumps the AST defined by `node` as a list of sexps.
42 47
 // Returns a string suitable for printing.
43 48
 func (node *Node) Dump() string {
... ...
@@ -79,28 +84,33 @@ func (node *Node) AddChild(child *Node, startLine, endLine int) {
79 79
 }
80 80
 
81 81
 var (
82
-	dispatch           map[string]func(string, *Directive) (*Node, map[string]bool, error)
83
-	tokenWhitespace    = regexp.MustCompile(`[\t\v\f\r ]+`)
84
-	tokenEscapeCommand = regexp.MustCompile(`^#[ \t]*escape[ \t]*=[ \t]*(?P<escapechar>.).*$`)
85
-	tokenComment       = regexp.MustCompile(`^#.*$`)
82
+	dispatch     map[string]func(string, *directives) (*Node, map[string]bool, error)
83
+	reWhitespace = regexp.MustCompile(`[\t\v\f\r ]+`)
84
+	reDirectives = regexp.MustCompile(`^#\s*([a-zA-Z][a-zA-Z0-9]*)\s*=\s*(.+?)\s*$`)
85
+	reComment    = regexp.MustCompile(`^#.*$`)
86 86
 )
87 87
 
88 88
 // DefaultEscapeToken is the default escape token
89 89
 const DefaultEscapeToken = '\\'
90 90
 
91
-// Directive is the structure used during a build run to hold the state of
91
+var validDirectives = map[string]struct{}{
92
+	"escape": {},
93
+	"syntax": {},
94
+}
95
+
96
+// directive is the structure used during a build run to hold the state of
92 97
 // parsing directives.
93
-type Directive struct {
94
-	escapeToken           rune           // Current escape token
95
-	lineContinuationRegex *regexp.Regexp // Current line continuation regex
96
-	processingComplete    bool           // Whether we are done looking for directives
97
-	escapeSeen            bool           // Whether the escape directive has been seen
98
+type directives struct {
99
+	escapeToken           rune                // Current escape token
100
+	lineContinuationRegex *regexp.Regexp      // Current line continuation regex
101
+	done                  bool                // Whether we are done looking for directives
102
+	seen                  map[string]struct{} // Whether the escape directive has been seen
98 103
 }
99 104
 
100 105
 // setEscapeToken sets the default token for escaping characters in a Dockerfile.
101
-func (d *Directive) setEscapeToken(s string) error {
106
+func (d *directives) setEscapeToken(s string) error {
102 107
 	if s != "`" && s != "\\" {
103
-		return fmt.Errorf("invalid ESCAPE '%s'. Must be ` or \\", s)
108
+		return errors.Errorf("invalid escape token '%s' does not match ` or \\", s)
104 109
 	}
105 110
 	d.escapeToken = rune(s[0])
106 111
 	d.lineContinuationRegex = regexp.MustCompile(`\` + s + `[ \t]*$`)
... ...
@@ -110,33 +120,43 @@ func (d *Directive) setEscapeToken(s string) error {
110 110
 // possibleParserDirective looks for parser directives, eg '# escapeToken=<char>'.
111 111
 // Parser directives must precede any builder instruction or other comments,
112 112
 // and cannot be repeated.
113
-func (d *Directive) possibleParserDirective(line string) error {
114
-	if d.processingComplete {
113
+func (d *directives) possibleParserDirective(line string) error {
114
+	if d.done {
115 115
 		return nil
116 116
 	}
117 117
 
118
-	tecMatch := tokenEscapeCommand.FindStringSubmatch(strings.ToLower(line))
119
-	if len(tecMatch) != 0 {
120
-		for i, n := range tokenEscapeCommand.SubexpNames() {
121
-			if n == "escapechar" {
122
-				if d.escapeSeen {
123
-					return errors.New("only one escape parser directive can be used")
124
-				}
125
-				d.escapeSeen = true
126
-				return d.setEscapeToken(tecMatch[i])
127
-			}
128
-		}
118
+	match := reDirectives.FindStringSubmatch(line)
119
+	if len(match) == 0 {
120
+		d.done = true
121
+		return nil
122
+	}
123
+
124
+	k := strings.ToLower(match[1])
125
+	_, ok := validDirectives[k]
126
+	if !ok {
127
+		d.done = true
128
+		return nil
129
+	}
130
+
131
+	if _, ok := d.seen[k]; ok {
132
+		return errors.Errorf("only one %s parser directive can be used", k)
133
+	}
134
+	d.seen[k] = struct{}{}
135
+
136
+	if k == "escape" {
137
+		return d.setEscapeToken(match[2])
129 138
 	}
130 139
 
131
-	d.processingComplete = true
132 140
 	return nil
133 141
 }
134 142
 
135
-// NewDefaultDirective returns a new Directive with the default escapeToken token
136
-func NewDefaultDirective() *Directive {
137
-	directive := Directive{}
138
-	directive.setEscapeToken(string(DefaultEscapeToken))
139
-	return &directive
143
+// newDefaultDirectives returns a new directives structure with the default escapeToken token
144
+func newDefaultDirectives() *directives {
145
+	d := &directives{
146
+		seen: map[string]struct{}{},
147
+	}
148
+	d.setEscapeToken(string(DefaultEscapeToken))
149
+	return d
140 150
 }
141 151
 
142 152
 func init() {
... ...
@@ -146,7 +166,7 @@ func init() {
146 146
 	// reformulating the arguments according to the rules in the parser
147 147
 	// functions. Errors are propagated up by Parse() and the resulting AST can
148 148
 	// be incorporated directly into the existing AST as a next.
149
-	dispatch = map[string]func(string, *Directive) (*Node, map[string]bool, error){
149
+	dispatch = map[string]func(string, *directives) (*Node, map[string]bool, error){
150 150
 		command.Add:         parseMaybeJSONToList,
151 151
 		command.Arg:         parseNameOrNameVal,
152 152
 		command.Cmd:         parseMaybeJSON,
... ...
@@ -171,7 +191,7 @@ func init() {
171 171
 // newNodeFromLine splits the line into parts, and dispatches to a function
172 172
 // based on the command and command arguments. A Node is created from the
173 173
 // result of the dispatch.
174
-func newNodeFromLine(line string, directive *Directive) (*Node, error) {
174
+func newNodeFromLine(line string, d *directives) (*Node, error) {
175 175
 	cmd, flags, args, err := splitCommand(line)
176 176
 	if err != nil {
177 177
 		return nil, err
... ...
@@ -182,7 +202,7 @@ func newNodeFromLine(line string, directive *Directive) (*Node, error) {
182 182
 	if fn == nil {
183 183
 		fn = parseIgnore
184 184
 	}
185
-	next, attrs, err := fn(args, directive)
185
+	next, attrs, err := fn(args, d)
186 186
 	if err != nil {
187 187
 		return nil, err
188 188
 	}
... ...
@@ -214,7 +234,7 @@ func (r *Result) PrintWarnings(out io.Writer) {
214 214
 // Parse reads lines from a Reader, parses the lines into an AST and returns
215 215
 // the AST and escape token
216 216
 func Parse(rwc io.Reader) (*Result, error) {
217
-	d := NewDefaultDirective()
217
+	d := newDefaultDirectives()
218 218
 	currentLine := 0
219 219
 	root := &Node{StartLine: -1}
220 220
 	scanner := bufio.NewScanner(rwc)
... ...
@@ -229,7 +249,7 @@ func Parse(rwc io.Reader) (*Result, error) {
229 229
 		}
230 230
 		bytesRead, err = processLine(d, bytesRead, true)
231 231
 		if err != nil {
232
-			return nil, err
232
+			return nil, withLocation(err, currentLine, 0)
233 233
 		}
234 234
 		currentLine++
235 235
 
... ...
@@ -243,7 +263,7 @@ func Parse(rwc io.Reader) (*Result, error) {
243 243
 		for !isEndOfLine && scanner.Scan() {
244 244
 			bytesRead, err := processLine(d, scanner.Bytes(), false)
245 245
 			if err != nil {
246
-				return nil, err
246
+				return nil, withLocation(err, currentLine, 0)
247 247
 			}
248 248
 			currentLine++
249 249
 
... ...
@@ -267,7 +287,7 @@ func Parse(rwc io.Reader) (*Result, error) {
267 267
 
268 268
 		child, err := newNodeFromLine(line, d)
269 269
 		if err != nil {
270
-			return nil, err
270
+			return nil, withLocation(err, startLine, currentLine)
271 271
 		}
272 272
 		root.AddChild(child, startLine, currentLine)
273 273
 	}
... ...
@@ -277,18 +297,18 @@ func Parse(rwc io.Reader) (*Result, error) {
277 277
 	}
278 278
 
279 279
 	if root.StartLine < 0 {
280
-		return nil, errors.New("file with no instructions.")
280
+		return nil, withLocation(errors.New("file with no instructions"), currentLine, 0)
281 281
 	}
282 282
 
283 283
 	return &Result{
284 284
 		AST:         root,
285 285
 		Warnings:    warnings,
286 286
 		EscapeToken: d.escapeToken,
287
-	}, handleScannerError(scanner.Err())
287
+	}, withLocation(handleScannerError(scanner.Err()), currentLine, 0)
288 288
 }
289 289
 
290 290
 func trimComments(src []byte) []byte {
291
-	return tokenComment.ReplaceAll(src, []byte{})
291
+	return reComment.ReplaceAll(src, []byte{})
292 292
 }
293 293
 
294 294
 func trimWhitespace(src []byte) []byte {
... ...
@@ -296,7 +316,7 @@ func trimWhitespace(src []byte) []byte {
296 296
 }
297 297
 
298 298
 func isComment(line []byte) bool {
299
-	return tokenComment.Match(trimWhitespace(line))
299
+	return reComment.Match(trimWhitespace(line))
300 300
 }
301 301
 
302 302
 func isEmptyContinuationLine(line []byte) bool {
... ...
@@ -305,7 +325,7 @@ func isEmptyContinuationLine(line []byte) bool {
305 305
 
306 306
 var utf8bom = []byte{0xEF, 0xBB, 0xBF}
307 307
 
308
-func trimContinuationCharacter(line string, d *Directive) (string, bool) {
308
+func trimContinuationCharacter(line string, d *directives) (string, bool) {
309 309
 	if d.lineContinuationRegex.MatchString(line) {
310 310
 		line = d.lineContinuationRegex.ReplaceAllString(line, "")
311 311
 		return line, false
... ...
@@ -315,7 +335,7 @@ func trimContinuationCharacter(line string, d *Directive) (string, bool) {
315 315
 
316 316
 // TODO: remove stripLeftWhitespace after deprecation period. It seems silly
317 317
 // to preserve whitespace on continuation lines. Why is that done?
318
-func processLine(d *Directive, token []byte, stripLeftWhitespace bool) ([]byte, error) {
318
+func processLine(d *directives, token []byte, stripLeftWhitespace bool) ([]byte, error) {
319 319
 	if stripLeftWhitespace {
320 320
 		token = trimWhitespace(token)
321 321
 	}
... ...
@@ -12,7 +12,7 @@ func splitCommand(line string) (string, []string, string, error) {
12 12
 	var flags []string
13 13
 
14 14
 	// Make sure we get the same results irrespective of leading/trailing spaces
15
-	cmdline := tokenWhitespace.Split(strings.TrimSpace(line), 2)
15
+	cmdline := reWhitespace.Split(strings.TrimSpace(line), 2)
16 16
 	cmd := strings.ToLower(cmdline[0])
17 17
 
18 18
 	if len(cmdline) == 2 {
... ...
@@ -13,6 +13,8 @@ import (
13 13
 	"time"
14 14
 
15 15
 	"github.com/docker/distribution/reference"
16
+	gogotypes "github.com/gogo/protobuf/types"
17
+	"github.com/golang/protobuf/ptypes/any"
16 18
 	apitypes "github.com/moby/buildkit/api/types"
17 19
 	"github.com/moby/buildkit/cache"
18 20
 	cacheutil "github.com/moby/buildkit/cache/util"
... ...
@@ -27,6 +29,7 @@ import (
27 27
 	"github.com/moby/buildkit/solver"
28 28
 	opspb "github.com/moby/buildkit/solver/pb"
29 29
 	"github.com/moby/buildkit/util/apicaps"
30
+	"github.com/moby/buildkit/util/grpcerrors"
30 31
 	"github.com/moby/buildkit/util/tracing"
31 32
 	"github.com/moby/buildkit/worker"
32 33
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
... ...
@@ -218,7 +221,7 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
218 218
 	err = llbBridge.Exec(ctx, meta, rootFS, lbf.Stdin, lbf.Stdout, os.Stderr)
219 219
 
220 220
 	if err != nil {
221
-		if errors.Cause(err) == context.Canceled && lbf.isErrServerClosed {
221
+		if errors.Is(err, context.Canceled) && lbf.isErrServerClosed {
222 222
 			err = errors.Errorf("frontend grpc server closed unexpectedly")
223 223
 		}
224 224
 		// An existing error (set via Return rpc) takes
... ...
@@ -309,7 +312,7 @@ func NewBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridg
309 309
 func newLLBBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers frontend.WorkerInfos, inputs map[string]*opspb.Definition) (*llbBridgeForwarder, context.Context, error) {
310 310
 	ctx, cancel := context.WithCancel(ctx)
311 311
 	lbf := NewBridgeForwarder(ctx, llbBridge, workers, inputs)
312
-	server := grpc.NewServer()
312
+	server := grpc.NewServer(grpc.UnaryInterceptor(grpcerrors.UnaryServerInterceptor), grpc.StreamInterceptor(grpcerrors.StreamServerInterceptor))
313 313
 	grpc_health_v1.RegisterHealthServer(server, health.NewServer())
314 314
 	pb.RegisterLLBBridgeServer(server, lbf)
315 315
 
... ...
@@ -472,7 +475,9 @@ func (lbf *llbBridgeForwarder) Solve(ctx context.Context, req *pb.SolveRequest)
472 472
 		return nil, errors.Errorf("solve did not return default result")
473 473
 	}
474 474
 
475
-	pbRes := &pb.Result{}
475
+	pbRes := &pb.Result{
476
+		Metadata: res.Metadata,
477
+	}
476 478
 	var defaultID string
477 479
 
478 480
 	lbf.mu.Lock()
... ...
@@ -668,11 +673,11 @@ func (lbf *llbBridgeForwarder) Ping(context.Context, *pb.PingRequest) (*pb.PongR
668 668
 
669 669
 func (lbf *llbBridgeForwarder) Return(ctx context.Context, in *pb.ReturnRequest) (*pb.ReturnResponse, error) {
670 670
 	if in.Error != nil {
671
-		return lbf.setResult(nil, status.ErrorProto(&spb.Status{
671
+		return lbf.setResult(nil, grpcerrors.FromGRPC(status.ErrorProto(&spb.Status{
672 672
 			Code:    in.Error.Code,
673 673
 			Message: in.Error.Message,
674
-			// Details: in.Error.Details,
675
-		}))
674
+			Details: convertGogoAny(in.Error.Details),
675
+		})))
676 676
 	} else {
677 677
 		r := &frontend.Result{
678 678
 			Metadata: in.Result.Metadata,
... ...
@@ -752,3 +757,11 @@ type markTypeFrontend struct{}
752 752
 func (*markTypeFrontend) SetImageOption(ii *llb.ImageInfo) {
753 753
 	ii.RecordType = string(client.UsageRecordTypeFrontend)
754 754
 }
755
+
756
+func convertGogoAny(in []*gogotypes.Any) []*any.Any {
757
+	out := make([]*any.Any, len(in))
758
+	for i := range in {
759
+		out[i] = &any.Any{TypeUrl: in[i].TypeUrl, Value: in[i].Value}
760
+	}
761
+	return out
762
+}
... ...
@@ -10,11 +10,14 @@ import (
10 10
 	"time"
11 11
 
12 12
 	"github.com/gogo/googleapis/google/rpc"
13
+	gogotypes "github.com/gogo/protobuf/types"
14
+	"github.com/golang/protobuf/ptypes/any"
13 15
 	"github.com/moby/buildkit/client/llb"
14 16
 	"github.com/moby/buildkit/frontend/gateway/client"
15 17
 	pb "github.com/moby/buildkit/frontend/gateway/pb"
16 18
 	opspb "github.com/moby/buildkit/solver/pb"
17 19
 	"github.com/moby/buildkit/util/apicaps"
20
+	"github.com/moby/buildkit/util/grpcerrors"
18 21
 	digest "github.com/opencontainers/go-digest"
19 22
 	"github.com/pkg/errors"
20 23
 	fstypes "github.com/tonistiigi/fsutil/types"
... ...
@@ -29,7 +32,7 @@ type GrpcClient interface {
29 29
 }
30 30
 
31 31
 func New(ctx context.Context, opts map[string]string, session, product string, c pb.LLBBridgeClient, w []client.WorkerInfo) (GrpcClient, error) {
32
-	ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
32
+	ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
33 33
 	defer cancel()
34 34
 	resp, err := c.Ping(ctx, &pb.PingRequest{})
35 35
 	if err != nil {
... ...
@@ -150,12 +153,12 @@ func (c *grpcClient) Run(ctx context.Context, f client.BuildFunc) (retError erro
150 150
 				}
151 151
 			}
152 152
 			if retError != nil {
153
-				st, _ := status.FromError(errors.Cause(retError))
153
+				st, _ := status.FromError(grpcerrors.ToGRPC(retError))
154 154
 				stp := st.Proto()
155 155
 				req.Error = &rpc.Status{
156 156
 					Code:    stp.Code,
157 157
 					Message: stp.Message,
158
-					// Details: stp.Details,
158
+					Details: convertToGogoAny(stp.Details),
159 159
 				}
160 160
 			}
161 161
 			if _, err := c.client.Return(ctx, req); err != nil && retError == nil {
... ...
@@ -503,7 +506,7 @@ func grpcClientConn(ctx context.Context) (context.Context, *grpc.ClientConn, err
503 503
 		return stdioConn(), nil
504 504
 	})
505 505
 
506
-	cc, err := grpc.DialContext(ctx, "", dialOpt, grpc.WithInsecure())
506
+	cc, err := grpc.DialContext(ctx, "", dialOpt, grpc.WithInsecure(), grpc.WithUnaryInterceptor(grpcerrors.UnaryClientInterceptor), grpc.WithStreamInterceptor(grpcerrors.StreamClientInterceptor))
507 507
 	if err != nil {
508 508
 		return nil, nil, errors.Wrap(err, "failed to create grpc client")
509 509
 	}
... ...
@@ -589,3 +592,11 @@ func workers() []client.WorkerInfo {
589 589
 func product() string {
590 590
 	return os.Getenv("BUILDKIT_EXPORTEDPRODUCT")
591 591
 }
592
+
593
+func convertToGogoAny(in []*any.Any) []*gogotypes.Any {
594
+	out := make([]*gogotypes.Any, len(in))
595
+	for i := range in {
596
+		out[i] = &gogotypes.Any{TypeUrl: in[i].TypeUrl, Value: in[i].Value}
597
+	}
598
+	return out
599
+}
... ...
@@ -32,6 +32,9 @@ const (
32 32
 	// CapFrontendInputs is a capability to request frontend inputs from the
33 33
 	// LLBBridge GRPC server.
34 34
 	CapFrontendInputs apicaps.CapID = "frontend.inputs"
35
+
36
+	// CapGatewaySolveMetadata can be used to check if solve calls from gateway reliably return metadata
37
+	CapGatewaySolveMetadata apicaps.CapID = "gateway.solve.metadata"
35 38
 )
36 39
 
37 40
 func init() {
... ...
@@ -126,4 +129,11 @@ func init() {
126 126
 		Enabled: true,
127 127
 		Status:  apicaps.CapStatusExperimental,
128 128
 	})
129
+
130
+	Caps.Init(apicaps.Cap{
131
+		ID:      CapGatewaySolveMetadata,
132
+		Name:    "gateway metadata",
133
+		Enabled: true,
134
+		Status:  apicaps.CapStatusExperimental,
135
+	})
129 136
 }
... ...
@@ -32,7 +32,7 @@ service LLBBridge {
32 32
 
33 33
 message Result {
34 34
 	oneof result {
35
-    		// Deprecated non-array refs.
35
+		// Deprecated non-array refs.
36 36
 		string refDeprecated = 1;
37 37
 		RefMapDeprecated refsDeprecated = 2;
38 38
 
... ...
@@ -67,7 +67,7 @@ message InputsRequest {
67 67
 }
68 68
 
69 69
 message InputsResponse {
70
-    map<string, pb.Definition> Definitions = 1;
70
+	map<string, pb.Definition> Definitions = 1;
71 71
 }
72 72
 
73 73
 message ResolveImageConfigRequest {
... ...
@@ -87,9 +87,9 @@ message SolveRequest {
87 87
 	string Frontend = 2;
88 88
 	map<string, string> FrontendOpt = 3;
89 89
 	// ImportCacheRefsDeprecated is deprecated in favor or the new Imports since BuildKit v0.4.0.
90
-        // When ImportCacheRefsDeprecated is set, the solver appends
91
-        // {.Type = "registry", .Attrs = {"ref": importCacheRef}}
92
-        // for each of the ImportCacheRefs entry to CacheImports for compatibility. (planned to be removed)
90
+	// When ImportCacheRefsDeprecated is set, the solver appends
91
+	// {.Type = "registry", .Attrs = {"ref": importCacheRef}}
92
+	// for each of the ImportCacheRefs entry to CacheImports for compatibility. (planned to be removed)
93 93
 	repeated string ImportCacheRefsDeprecated = 4;
94 94
 	bool allowResultReturn = 5;
95 95
 	bool allowResultArrayRef = 6;
... ...
@@ -3,24 +3,22 @@ module github.com/moby/buildkit
3 3
 go 1.13
4 4
 
5 5
 require (
6
-	github.com/AkihiroSuda/containerd-fuse-overlayfs v0.0.0-20200220082720-bb896865146c
6
+	github.com/AkihiroSuda/containerd-fuse-overlayfs v0.0.0-20200512015515-32086ef23a5a
7
+	github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
7 8
 	github.com/BurntSushi/toml v0.3.1
8 9
 	github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5
9
-	github.com/Microsoft/hcsshim v0.8.7 // indirect
10 10
 	github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7 // indirect
11 11
 	github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58 // indirect
12
-	github.com/containerd/cgroups v0.0.0-20200217135630-d732e370d46d // indirect
13
-	github.com/containerd/console v0.0.0-20191219165238-8375c3424e4d
12
+	github.com/containerd/cgroups v0.0.0-20200327175542-b44481373989 // indirect
13
+	github.com/containerd/console v1.0.0
14 14
 	github.com/containerd/containerd v1.4.0-0
15
-	github.com/containerd/continuity v0.0.0-20200107194136-26c1120b8d41
16
-	github.com/containerd/fifo v0.0.0-20191213151349-ff969a566b00 // indirect
15
+	github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb
16
+	github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b // indirect
17 17
 	github.com/containerd/go-cni v0.0.0-20200107172653-c154a49e2c75
18 18
 	github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328
19
-	github.com/containerd/ttrpc v0.0.0-20200121165050-0be804eadb15 // indirect
20
-	github.com/containerd/typeurl v0.0.0-20200205145503-b45ef1f1f737 // indirect
21 19
 	github.com/coreos/go-systemd/v22 v22.0.0
22 20
 	github.com/docker/cli v0.0.0-20200227165822-2298e6a3fe24
23
-	github.com/docker/distribution v0.0.0-20200223014041-6b972e50feee
21
+	github.com/docker/distribution v2.7.1+incompatible
24 22
 	github.com/docker/docker v0.0.0
25 23
 	github.com/docker/docker-credential-helpers v0.6.0 // indirect
26 24
 	github.com/docker/go-connections v0.3.0
... ...
@@ -29,55 +27,52 @@ require (
29 29
 	github.com/gogo/googleapis v1.3.2
30 30
 	github.com/gogo/protobuf v1.3.1
31 31
 	github.com/golang/protobuf v1.3.3
32
-	github.com/google/go-cmp v0.3.1
32
+	github.com/google/go-cmp v0.4.0
33 33
 	github.com/google/shlex v0.0.0-20150127133951-6f45313302b9
34 34
 	github.com/google/uuid v1.1.1 // indirect
35
+	github.com/gorilla/mux v1.7.4 // indirect
36
+	github.com/grpc-ecosystem/go-grpc-middleware v1.2.0
35 37
 	github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645
36 38
 	github.com/hashicorp/go-immutable-radix v1.0.0
37 39
 	github.com/hashicorp/golang-lru v0.5.1
38 40
 	github.com/hashicorp/uuid v0.0.0-20160311170451-ebb0a03e909c // indirect
39
-	github.com/imdario/mergo v0.3.7 // indirect
41
+	github.com/imdario/mergo v0.3.9 // indirect
40 42
 	github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07 // indirect
41 43
 	github.com/jaguilar/vt100 v0.0.0-20150826170717-2703a27b14ea
42
-	github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452
44
+	github.com/mitchellh/hashstructure v1.0.0
43 45
 	github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c
44
-	github.com/opencontainers/go-digest v1.0.0-rc1
46
+	github.com/opencontainers/go-digest v1.0.0
45 47
 	github.com/opencontainers/image-spec v1.0.1
46
-	github.com/opencontainers/runc v1.0.0-rc9.0.20200221051241-688cf6d43cc4
47
-	github.com/opencontainers/runtime-spec v1.0.1
48
-	github.com/opencontainers/selinux v1.3.2 // indirect
48
+	github.com/opencontainers/runc v1.0.0-rc10
49
+	github.com/opencontainers/runtime-spec v1.0.2
50
+	github.com/opencontainers/selinux v1.5.1 // indirect
49 51
 	github.com/opentracing-contrib/go-stdlib v0.0.0-20171029140428-b1a47cfbdd75
50
-	github.com/opentracing/opentracing-go v0.0.0-20171003133519-1361b9cd60be
52
+	github.com/opentracing/opentracing-go v1.1.0
51 53
 	github.com/pkg/errors v0.9.1
52 54
 	github.com/pkg/profile v1.2.1
53 55
 	github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002
54 56
 	github.com/sirupsen/logrus v1.4.2
55
-	github.com/stretchr/testify v1.4.0
57
+	github.com/stretchr/testify v1.5.1
56 58
 	github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 // indirect
57
-	github.com/tonistiigi/fsutil v0.0.0-20200326231323-c2c7d7b0e144
59
+	github.com/tonistiigi/fsutil v0.0.0-20200512175118-ae3a8d753069
58 60
 	github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea
59
-	github.com/uber/jaeger-client-go v0.0.0-20180103221425-e02c85f9069e
61
+	github.com/uber/jaeger-client-go v2.11.2+incompatible
60 62
 	github.com/uber/jaeger-lib v1.2.1 // indirect
61 63
 	github.com/urfave/cli v1.22.2
62
-	github.com/vishvananda/netlink v1.0.0 // indirect
63
-	github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect
64
+	github.com/vishvananda/netlink v1.1.0 // indirect
64 65
 	go.etcd.io/bbolt v1.3.3
65 66
 	golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d
66 67
 	golang.org/x/net v0.0.0-20200226121028-0de0cce0169b
67 68
 	golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
68
-	golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae
69
+	golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527
69 70
 	golang.org/x/time v0.0.0-20191024005414-555d28b269f0
70 71
 	google.golang.org/genproto v0.0.0-20200227132054-3f1135a288c9
71 72
 	google.golang.org/grpc v1.27.1
72
-	gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
73
-	gotest.tools v2.2.0+incompatible
74
-	gotest.tools/v3 v3.0.2 // indirect
75 73
 )
76 74
 
77
-replace github.com/hashicorp/go-immutable-radix => github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe
78
-
79
-replace github.com/jaguilar/vt100 => github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305
80
-
81
-replace github.com/containerd/containerd => github.com/containerd/containerd v1.3.1-0.20200227195959-4d242818bf55
82
-
83
-replace github.com/docker/docker => github.com/docker/docker v1.4.2-0.20200227233006-38f52c9fec82
75
+replace (
76
+	github.com/containerd/containerd => github.com/containerd/containerd v1.3.1-0.20200512144102-f13ba8f2f2fd
77
+	github.com/docker/docker => github.com/docker/docker v17.12.0-ce-rc1.0.20200310163718-4634ce647cf2+incompatible
78
+	github.com/hashicorp/go-immutable-radix => github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe
79
+	github.com/jaguilar/vt100 => github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305
80
+)
... ...
@@ -4,9 +4,8 @@ import (
4 4
 	"context"
5 5
 
6 6
 	"github.com/moby/buildkit/session"
7
-	"github.com/pkg/errors"
7
+	"github.com/moby/buildkit/util/grpcerrors"
8 8
 	"google.golang.org/grpc/codes"
9
-	"google.golang.org/grpc/status"
10 9
 )
11 10
 
12 11
 func CredentialsFunc(ctx context.Context, c session.Caller) func(string) (string, string, error) {
... ...
@@ -17,10 +16,10 @@ func CredentialsFunc(ctx context.Context, c session.Caller) func(string) (string
17 17
 			Host: host,
18 18
 		})
19 19
 		if err != nil {
20
-			if st, ok := status.FromError(errors.Cause(err)); ok && st.Code() == codes.Unimplemented {
20
+			if grpcerrors.Code(err) == codes.Unimplemented {
21 21
 				return "", "", nil
22 22
 			}
23
-			return "", "", errors.WithStack(err)
23
+			return "", "", err
24 24
 		}
25 25
 		return resp.Username, resp.Secret, nil
26 26
 	}
... ...
@@ -41,7 +41,7 @@ type streamWriterCloser struct {
41 41
 func (wc *streamWriterCloser) Write(dt []byte) (int, error) {
42 42
 	if err := wc.ClientStream.SendMsg(&BytesMessage{Data: dt}); err != nil {
43 43
 		// SendMsg return EOF on remote errors
44
-		if errors.Cause(err) == io.EOF {
44
+		if errors.Is(err, io.EOF) {
45 45
 			if err := errors.WithStack(wc.ClientStream.RecvMsg(struct{}{})); err != nil {
46 46
 				return 0, err
47 47
 			}
... ...
@@ -105,7 +105,7 @@ func writeTargetFile(ds grpc.Stream, wc io.WriteCloser) error {
105 105
 	for {
106 106
 		bm := BytesMessage{}
107 107
 		if err := ds.RecvMsg(&bm); err != nil {
108
-			if errors.Cause(err) == io.EOF {
108
+			if errors.Is(err, io.EOF) {
109 109
 				return nil
110 110
 			}
111 111
 			return errors.WithStack(err)
... ...
@@ -255,7 +255,7 @@ func (sp *fsSyncTarget) Register(server *grpc.Server) {
255 255
 	RegisterFileSendServer(server, sp)
256 256
 }
257 257
 
258
-func (sp *fsSyncTarget) DiffCopy(stream FileSend_DiffCopyServer) error {
258
+func (sp *fsSyncTarget) DiffCopy(stream FileSend_DiffCopyServer) (err error) {
259 259
 	if sp.outdir != "" {
260 260
 		return syncTargetDiffCopy(stream, sp.outdir)
261 261
 	}
... ...
@@ -277,7 +277,12 @@ func (sp *fsSyncTarget) DiffCopy(stream FileSend_DiffCopyServer) error {
277 277
 	if wc == nil {
278 278
 		return status.Errorf(codes.AlreadyExists, "target already exists")
279 279
 	}
280
-	defer wc.Close()
280
+	defer func() {
281
+		err1 := wc.Close()
282
+		if err != nil {
283
+			err = err1
284
+		}
285
+	}()
281 286
 	return writeTargetFile(stream, wc)
282 287
 }
283 288
 
... ...
@@ -6,7 +6,9 @@ import (
6 6
 	"sync/atomic"
7 7
 	"time"
8 8
 
9
+	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
9 10
 	"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
11
+	"github.com/moby/buildkit/util/grpcerrors"
10 12
 	opentracing "github.com/opentracing/opentracing-go"
11 13
 	"github.com/pkg/errors"
12 14
 	"github.com/sirupsen/logrus"
... ...
@@ -25,6 +27,9 @@ func serve(ctx context.Context, grpcServer *grpc.Server, conn net.Conn) {
25 25
 }
26 26
 
27 27
 func grpcClientConn(ctx context.Context, conn net.Conn) (context.Context, *grpc.ClientConn, error) {
28
+	var unary []grpc.UnaryClientInterceptor
29
+	var stream []grpc.StreamClientInterceptor
30
+
28 31
 	var dialCount int64
29 32
 	dialer := grpc.WithDialer(func(addr string, d time.Duration) (net.Conn, error) {
30 33
 		if c := atomic.AddInt64(&dialCount, 1); c > 1 {
... ...
@@ -40,10 +45,23 @@ func grpcClientConn(ctx context.Context, conn net.Conn) (context.Context, *grpc.
40 40
 
41 41
 	if span := opentracing.SpanFromContext(ctx); span != nil {
42 42
 		tracer := span.Tracer()
43
-		dialOpts = append(dialOpts,
44
-			grpc.WithUnaryInterceptor(otgrpc.OpenTracingClientInterceptor(tracer, traceFilter())),
45
-			grpc.WithStreamInterceptor(otgrpc.OpenTracingStreamClientInterceptor(tracer, traceFilter())),
46
-		)
43
+		unary = append(unary, otgrpc.OpenTracingClientInterceptor(tracer, traceFilter()))
44
+		stream = append(stream, otgrpc.OpenTracingStreamClientInterceptor(tracer, traceFilter()))
45
+	}
46
+
47
+	unary = append(unary, grpcerrors.UnaryClientInterceptor)
48
+	stream = append(stream, grpcerrors.StreamClientInterceptor)
49
+
50
+	if len(unary) == 1 {
51
+		dialOpts = append(dialOpts, grpc.WithUnaryInterceptor(unary[0]))
52
+	} else if len(unary) > 1 {
53
+		dialOpts = append(dialOpts, grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(unary...)))
54
+	}
55
+
56
+	if len(stream) == 1 {
57
+		dialOpts = append(dialOpts, grpc.WithStreamInterceptor(stream[0]))
58
+	} else if len(stream) > 1 {
59
+		dialOpts = append(dialOpts, grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(stream...)))
47 60
 	}
48 61
 
49 62
 	cc, err := grpc.DialContext(ctx, "", dialOpts...)
... ...
@@ -4,9 +4,9 @@ import (
4 4
 	"context"
5 5
 
6 6
 	"github.com/moby/buildkit/session"
7
+	"github.com/moby/buildkit/util/grpcerrors"
7 8
 	"github.com/pkg/errors"
8 9
 	"google.golang.org/grpc/codes"
9
-	"google.golang.org/grpc/status"
10 10
 )
11 11
 
12 12
 type SecretStore interface {
... ...
@@ -21,10 +21,10 @@ func GetSecret(ctx context.Context, c session.Caller, id string) ([]byte, error)
21 21
 		ID: id,
22 22
 	})
23 23
 	if err != nil {
24
-		if st, ok := status.FromError(errors.Cause(err)); ok && (st.Code() == codes.Unimplemented || st.Code() == codes.NotFound) {
24
+		if code := grpcerrors.Code(err); code == codes.Unimplemented || code == codes.NotFound {
25 25
 			return nil, errors.Wrapf(ErrNotFound, "secret %s not found", id)
26 26
 		}
27
-		return nil, errors.WithStack(err)
27
+		return nil, err
28 28
 	}
29 29
 	return resp.Data, nil
30 30
 }
... ...
@@ -5,8 +5,10 @@ import (
5 5
 	"net"
6 6
 	"strings"
7 7
 
8
+	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
8 9
 	"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
9 10
 	"github.com/moby/buildkit/identity"
11
+	"github.com/moby/buildkit/util/grpcerrors"
10 12
 	opentracing "github.com/opentracing/opentracing-go"
11 13
 	"github.com/pkg/errors"
12 14
 	"google.golang.org/grpc"
... ...
@@ -45,13 +47,29 @@ type Session struct {
45 45
 func NewSession(ctx context.Context, name, sharedKey string) (*Session, error) {
46 46
 	id := identity.NewID()
47 47
 
48
+	var unary []grpc.UnaryServerInterceptor
49
+	var stream []grpc.StreamServerInterceptor
50
+
48 51
 	serverOpts := []grpc.ServerOption{}
49 52
 	if span := opentracing.SpanFromContext(ctx); span != nil {
50 53
 		tracer := span.Tracer()
51
-		serverOpts = []grpc.ServerOption{
52
-			grpc.StreamInterceptor(otgrpc.OpenTracingStreamServerInterceptor(span.Tracer(), traceFilter())),
53
-			grpc.UnaryInterceptor(otgrpc.OpenTracingServerInterceptor(tracer, traceFilter())),
54
-		}
54
+		unary = append(unary, otgrpc.OpenTracingServerInterceptor(tracer, traceFilter()))
55
+		stream = append(stream, otgrpc.OpenTracingStreamServerInterceptor(span.Tracer(), traceFilter()))
56
+	}
57
+
58
+	unary = append(unary, grpcerrors.UnaryServerInterceptor)
59
+	stream = append(stream, grpcerrors.StreamServerInterceptor)
60
+
61
+	if len(unary) == 1 {
62
+		serverOpts = append(serverOpts, grpc.UnaryInterceptor(unary[0]))
63
+	} else if len(unary) > 1 {
64
+		serverOpts = append(serverOpts, grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(unary...)))
65
+	}
66
+
67
+	if len(stream) == 1 {
68
+		serverOpts = append(serverOpts, grpc.StreamInterceptor(stream[0]))
69
+	} else if len(stream) > 1 {
70
+		serverOpts = append(serverOpts, grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(stream...)))
55 71
 	}
56 72
 
57 73
 	s := &Session{
... ...
@@ -5,7 +5,7 @@ import (
5 5
 
6 6
 	"github.com/containerd/containerd/content"
7 7
 	"github.com/containerd/containerd/namespaces"
8
-	"github.com/opencontainers/go-digest"
8
+	digest "github.com/opencontainers/go-digest"
9 9
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
10 10
 	"github.com/pkg/errors"
11 11
 )
... ...
@@ -26,12 +26,13 @@ func (t edgeStatusType) String() string {
26 26
 
27 27
 func newEdge(ed Edge, op activeOp, index *edgeIndex) *edge {
28 28
 	e := &edge{
29
-		edge:         ed,
30
-		op:           op,
31
-		depRequests:  map[pipe.Receiver]*dep{},
32
-		keyMap:       map[string]struct{}{},
33
-		cacheRecords: map[string]*CacheRecord{},
34
-		index:        index,
29
+		edge:               ed,
30
+		op:                 op,
31
+		depRequests:        map[pipe.Receiver]*dep{},
32
+		keyMap:             map[string]struct{}{},
33
+		cacheRecords:       map[string]*CacheRecord{},
34
+		cacheRecordsLoaded: map[string]struct{}{},
35
+		index:              index,
35 36
 	}
36 37
 	return e
37 38
 }
... ...
@@ -44,14 +45,16 @@ type edge struct {
44 44
 	depRequests map[pipe.Receiver]*dep
45 45
 	deps        []*dep
46 46
 
47
-	cacheMapReq     pipe.Receiver
48
-	cacheMapDone    bool
49
-	cacheMapIndex   int
50
-	cacheMapDigests []digest.Digest
51
-	execReq         pipe.Receiver
52
-	err             error
53
-	cacheRecords    map[string]*CacheRecord
54
-	keyMap          map[string]struct{}
47
+	cacheMapReq        pipe.Receiver
48
+	cacheMapDone       bool
49
+	cacheMapIndex      int
50
+	cacheMapDigests    []digest.Digest
51
+	execReq            pipe.Receiver
52
+	execCacheLoad      bool
53
+	err                error
54
+	cacheRecords       map[string]*CacheRecord
55
+	cacheRecordsLoaded map[string]struct{}
56
+	keyMap             map[string]struct{}
55 57
 
56 58
 	noCacheMatchPossible      bool
57 59
 	allDepsCompletedCacheFast bool
... ...
@@ -425,7 +428,11 @@ func (e *edge) processUpdate(upt pipe.Receiver) (depChanged bool) {
425 425
 	if upt == e.execReq && upt.Status().Completed {
426 426
 		if err := upt.Status().Err; err != nil {
427 427
 			e.execReq = nil
428
-			if !upt.Status().Canceled && e.err == nil {
428
+			if e.execCacheLoad {
429
+				for k := range e.cacheRecordsLoaded {
430
+					delete(e.cacheRecords, k)
431
+				}
432
+			} else if !upt.Status().Canceled && e.err == nil {
429 433
 				e.err = err
430 434
 			}
431 435
 		} else {
... ...
@@ -561,7 +568,9 @@ func (e *edge) recalcCurrentState() {
561 561
 		}
562 562
 
563 563
 		for _, r := range records {
564
-			e.cacheRecords[r.ID] = r
564
+			if _, ok := e.cacheRecordsLoaded[r.ID]; !ok {
565
+				e.cacheRecords[r.ID] = r
566
+			}
565 567
 		}
566 568
 
567 569
 		e.keys = append(e.keys, e.makeExportable(mergedKey, records))
... ...
@@ -821,6 +830,7 @@ func (e *edge) execIfPossible(f *pipeFactory) bool {
821 821
 			return true
822 822
 		}
823 823
 		e.execReq = f.NewFuncRequest(e.loadCache)
824
+		e.execCacheLoad = true
824 825
 		for req := range e.depRequests {
825 826
 			req.Cancel()
826 827
 		}
... ...
@@ -831,6 +841,7 @@ func (e *edge) execIfPossible(f *pipeFactory) bool {
831 831
 			return true
832 832
 		}
833 833
 		e.execReq = f.NewFuncRequest(e.execOp)
834
+		e.execCacheLoad = false
834 835
 		return true
835 836
 	}
836 837
 	return false
... ...
@@ -851,6 +862,7 @@ func (e *edge) loadCache(ctx context.Context) (interface{}, error) {
851 851
 	}
852 852
 
853 853
 	rec := getBestResult(recs)
854
+	e.cacheRecordsLoaded[rec.ID] = struct{}{}
854 855
 
855 856
 	logrus.Debugf("load cache for %s with %s", e.edge.Vertex.Name(), rec.ID)
856 857
 	res, err := e.op.LoadCache(ctx, rec)
857 858
new file mode 100644
... ...
@@ -0,0 +1,129 @@
0
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
1
+// source: errdefs.proto
2
+
3
+package errdefs
4
+
5
+import (
6
+	fmt "fmt"
7
+	proto "github.com/gogo/protobuf/proto"
8
+	pb "github.com/moby/buildkit/solver/pb"
9
+	math "math"
10
+)
11
+
12
+// Reference imports to suppress errors if they are not otherwise used.
13
+var _ = proto.Marshal
14
+var _ = fmt.Errorf
15
+var _ = math.Inf
16
+
17
+// This is a compile-time assertion to ensure that this generated file
18
+// is compatible with the proto package it is being compiled against.
19
+// A compilation error at this line likely means your copy of the
20
+// proto package needs to be updated.
21
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
22
+
23
+type Vertex struct {
24
+	Digest               string   `protobuf:"bytes,1,opt,name=digest,proto3" json:"digest,omitempty"`
25
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
26
+	XXX_unrecognized     []byte   `json:"-"`
27
+	XXX_sizecache        int32    `json:"-"`
28
+}
29
+
30
+func (m *Vertex) Reset()         { *m = Vertex{} }
31
+func (m *Vertex) String() string { return proto.CompactTextString(m) }
32
+func (*Vertex) ProtoMessage()    {}
33
+func (*Vertex) Descriptor() ([]byte, []int) {
34
+	return fileDescriptor_689dc58a5060aff5, []int{0}
35
+}
36
+func (m *Vertex) XXX_Unmarshal(b []byte) error {
37
+	return xxx_messageInfo_Vertex.Unmarshal(m, b)
38
+}
39
+func (m *Vertex) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
40
+	return xxx_messageInfo_Vertex.Marshal(b, m, deterministic)
41
+}
42
+func (m *Vertex) XXX_Merge(src proto.Message) {
43
+	xxx_messageInfo_Vertex.Merge(m, src)
44
+}
45
+func (m *Vertex) XXX_Size() int {
46
+	return xxx_messageInfo_Vertex.Size(m)
47
+}
48
+func (m *Vertex) XXX_DiscardUnknown() {
49
+	xxx_messageInfo_Vertex.DiscardUnknown(m)
50
+}
51
+
52
+var xxx_messageInfo_Vertex proto.InternalMessageInfo
53
+
54
+func (m *Vertex) GetDigest() string {
55
+	if m != nil {
56
+		return m.Digest
57
+	}
58
+	return ""
59
+}
60
+
61
+type Source struct {
62
+	Info                 *pb.SourceInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"`
63
+	Ranges               []*pb.Range    `protobuf:"bytes,2,rep,name=ranges,proto3" json:"ranges,omitempty"`
64
+	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
65
+	XXX_unrecognized     []byte         `json:"-"`
66
+	XXX_sizecache        int32          `json:"-"`
67
+}
68
+
69
+func (m *Source) Reset()         { *m = Source{} }
70
+func (m *Source) String() string { return proto.CompactTextString(m) }
71
+func (*Source) ProtoMessage()    {}
72
+func (*Source) Descriptor() ([]byte, []int) {
73
+	return fileDescriptor_689dc58a5060aff5, []int{1}
74
+}
75
+func (m *Source) XXX_Unmarshal(b []byte) error {
76
+	return xxx_messageInfo_Source.Unmarshal(m, b)
77
+}
78
+func (m *Source) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
79
+	return xxx_messageInfo_Source.Marshal(b, m, deterministic)
80
+}
81
+func (m *Source) XXX_Merge(src proto.Message) {
82
+	xxx_messageInfo_Source.Merge(m, src)
83
+}
84
+func (m *Source) XXX_Size() int {
85
+	return xxx_messageInfo_Source.Size(m)
86
+}
87
+func (m *Source) XXX_DiscardUnknown() {
88
+	xxx_messageInfo_Source.DiscardUnknown(m)
89
+}
90
+
91
+var xxx_messageInfo_Source proto.InternalMessageInfo
92
+
93
+func (m *Source) GetInfo() *pb.SourceInfo {
94
+	if m != nil {
95
+		return m.Info
96
+	}
97
+	return nil
98
+}
99
+
100
+func (m *Source) GetRanges() []*pb.Range {
101
+	if m != nil {
102
+		return m.Ranges
103
+	}
104
+	return nil
105
+}
106
+
107
+func init() {
108
+	proto.RegisterType((*Vertex)(nil), "errdefs.Vertex")
109
+	proto.RegisterType((*Source)(nil), "errdefs.Source")
110
+}
111
+
112
+func init() { proto.RegisterFile("errdefs.proto", fileDescriptor_689dc58a5060aff5) }
113
+
114
+var fileDescriptor_689dc58a5060aff5 = []byte{
115
+	// 177 bytes of a gzipped FileDescriptorProto
116
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x2c, 0xcd, 0xc1, 0x8a, 0x83, 0x30,
117
+	0x10, 0x80, 0x61, 0xdc, 0x5d, 0xb2, 0x18, 0xd9, 0x3d, 0xe4, 0x50, 0xa4, 0x27, 0xeb, 0xc9, 0x43,
118
+	0x49, 0xc0, 0x3e, 0x45, 0x4f, 0x85, 0x14, 0x7a, 0x6f, 0x74, 0xb4, 0xa1, 0xea, 0x84, 0x49, 0x2c,
119
+	0xed, 0xdb, 0x17, 0x6d, 0x8e, 0xff, 0x7c, 0x33, 0x0c, 0xff, 0x03, 0xa2, 0x16, 0x3a, 0x2f, 0x1d,
120
+	0x61, 0x40, 0xf1, 0x1b, 0x73, 0xbb, 0xef, 0x6d, 0xb8, 0xcd, 0x46, 0x36, 0x38, 0xaa, 0x11, 0xcd,
121
+	0x4b, 0x99, 0xd9, 0x0e, 0xed, 0xdd, 0x06, 0xe5, 0x71, 0x78, 0x00, 0x29, 0x67, 0x14, 0xba, 0x78,
122
+	0x56, 0x16, 0x9c, 0x5d, 0x80, 0x02, 0x3c, 0xc5, 0x86, 0xb3, 0xd6, 0xf6, 0xe0, 0x43, 0x9e, 0x14,
123
+	0x49, 0x95, 0xea, 0x58, 0xe5, 0x89, 0xb3, 0x33, 0xce, 0xd4, 0x80, 0x28, 0xf9, 0x8f, 0x9d, 0x3a,
124
+	0x5c, 0x3d, 0xab, 0xff, 0xa5, 0x33, 0xf2, 0x23, 0xc7, 0xa9, 0x43, 0xbd, 0x9a, 0xd8, 0x71, 0x46,
125
+	0xd7, 0xa9, 0x07, 0x9f, 0x7f, 0x15, 0xdf, 0x55, 0x56, 0xa7, 0xcb, 0x96, 0x5e, 0x26, 0x3a, 0x82,
126
+	0x61, 0xeb, 0xe7, 0xc3, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x93, 0xb5, 0x8b, 0x2a, 0xc1, 0x00, 0x00,
127
+	0x00,
128
+}
0 129
new file mode 100644
... ...
@@ -0,0 +1,14 @@
0
+syntax = "proto3";
1
+
2
+package errdefs;
3
+
4
+import "github.com/moby/buildkit/solver/pb/ops.proto";
5
+
6
+message Vertex {
7
+	string digest = 1;
8
+}
9
+
10
+message Source {
11
+	pb.SourceInfo info = 1;
12
+	repeated pb.Range ranges = 2;
13
+}
0 14
new file mode 100644
... ...
@@ -0,0 +1,3 @@
0
+package errdefs
1
+
2
+//go:generate protoc -I=. -I=../../vendor/ -I=../../../../../ --gogo_out=. errdefs.proto
0 3
new file mode 100644
... ...
@@ -0,0 +1,128 @@
0
+package errdefs
1
+
2
+import (
3
+	"fmt"
4
+	"io"
5
+	"strings"
6
+
7
+	pb "github.com/moby/buildkit/solver/pb"
8
+	"github.com/moby/buildkit/util/grpcerrors"
9
+	"github.com/pkg/errors"
10
+)
11
+
12
+func WithSource(err error, src Source) error {
13
+	if err == nil {
14
+		return nil
15
+	}
16
+	return &ErrorSource{Source: src, error: err}
17
+}
18
+
19
+type ErrorSource struct {
20
+	Source
21
+	error
22
+}
23
+
24
+func (e *ErrorSource) Unwrap() error {
25
+	return e.error
26
+}
27
+
28
+func (e *ErrorSource) ToProto() grpcerrors.TypedErrorProto {
29
+	return &e.Source
30
+}
31
+
32
+func Sources(err error) []*Source {
33
+	var out []*Source
34
+	var es *ErrorSource
35
+	if errors.As(err, &es) {
36
+		out = Sources(es.Unwrap())
37
+		out = append(out, &es.Source)
38
+	}
39
+	return out
40
+}
41
+
42
+func (s *Source) WrapError(err error) error {
43
+	return &ErrorSource{error: err, Source: *s}
44
+}
45
+
46
+func (s *Source) Print(w io.Writer) error {
47
+	si := s.Info
48
+	if si == nil {
49
+		return nil
50
+	}
51
+	lines := strings.Split(string(si.Data), "\n")
52
+
53
+	start, end, ok := getStartEndLine(s.Ranges)
54
+	if !ok {
55
+		return nil
56
+	}
57
+	if start > len(lines) || start < 1 {
58
+		return nil
59
+	}
60
+	if end > len(lines) {
61
+		end = len(lines)
62
+	}
63
+
64
+	pad := 2
65
+	if end == start {
66
+		pad = 4
67
+	}
68
+	var p int
69
+
70
+	prepadStart := start
71
+	for {
72
+		if p >= pad {
73
+			break
74
+		}
75
+		if start > 1 {
76
+			start--
77
+			p++
78
+		}
79
+		if end != len(lines) {
80
+			end++
81
+			p++
82
+		}
83
+		p++
84
+	}
85
+
86
+	fmt.Fprintf(w, "%s:%d\n--------------------\n", si.Filename, prepadStart)
87
+	for i := start; i <= end; i++ {
88
+		pfx := "   "
89
+		if containsLine(s.Ranges, i) {
90
+			pfx = ">>>"
91
+		}
92
+		fmt.Fprintf(w, " %3d | %s %s\n", i, pfx, lines[i-1])
93
+	}
94
+	fmt.Fprintf(w, "--------------------\n")
95
+	return nil
96
+}
97
+
98
+func containsLine(rr []*pb.Range, l int) bool {
99
+	for _, r := range rr {
100
+		e := r.End.Line
101
+		if e < r.Start.Line {
102
+			e = r.Start.Line
103
+		}
104
+		if r.Start.Line <= int32(l) && e >= int32(l) {
105
+			return true
106
+		}
107
+	}
108
+	return false
109
+}
110
+
111
+func getStartEndLine(rr []*pb.Range) (start int, end int, ok bool) {
112
+	first := true
113
+	for _, r := range rr {
114
+		e := r.End.Line
115
+		if e < r.Start.Line {
116
+			e = r.Start.Line
117
+		}
118
+		if first || int(r.Start.Line) < start {
119
+			start = int(r.Start.Line)
120
+		}
121
+		if int(e) > end {
122
+			end = int(e)
123
+		}
124
+		first = false
125
+	}
126
+	return start, end, !first
127
+}
0 128
new file mode 100644
... ...
@@ -0,0 +1,36 @@
0
+package errdefs
1
+
2
+import (
3
+	proto "github.com/golang/protobuf/proto"
4
+	"github.com/moby/buildkit/util/grpcerrors"
5
+	digest "github.com/opencontainers/go-digest"
6
+)
7
+
8
+func init() {
9
+	proto.RegisterType((*Vertex)(nil), "errdefs.Vertex")
10
+	proto.RegisterType((*Source)(nil), "errdefs.Source")
11
+}
12
+
13
+type VertexError struct {
14
+	Vertex
15
+	error
16
+}
17
+
18
+func (e *VertexError) Unwrap() error {
19
+	return e.error
20
+}
21
+
22
+func (e *VertexError) ToProto() grpcerrors.TypedErrorProto {
23
+	return &e.Vertex
24
+}
25
+
26
+func WrapVertex(err error, dgst digest.Digest) error {
27
+	if err == nil {
28
+		return nil
29
+	}
30
+	return &VertexError{Vertex: Vertex{Digest: dgst.String()}, error: err}
31
+}
32
+
33
+func (v *Vertex) WrapError(err error) error {
34
+	return &VertexError{error: err, Vertex: *v}
35
+}
... ...
@@ -159,7 +159,7 @@ func (pw *sender) Finalize(v interface{}, err error) {
159 159
 	}
160 160
 	pw.status.Err = err
161 161
 	pw.status.Completed = true
162
-	if errors.Cause(err) == context.Canceled && pw.req.Canceled {
162
+	if errors.Is(err, context.Canceled) && pw.req.Canceled {
163 163
 		pw.status.Canceled = true
164 164
 	}
165 165
 	pw.sendChannel.Send(pw.status)
... ...
@@ -9,6 +9,7 @@ import (
9 9
 
10 10
 	"github.com/moby/buildkit/client"
11 11
 	"github.com/moby/buildkit/session"
12
+	"github.com/moby/buildkit/solver/errdefs"
12 13
 	"github.com/moby/buildkit/util/flightcontrol"
13 14
 	"github.com/moby/buildkit/util/progress"
14 15
 	"github.com/moby/buildkit/util/tracing"
... ...
@@ -53,6 +54,7 @@ type state struct {
53 53
 
54 54
 	vtx          Vertex
55 55
 	clientVertex client.Vertex
56
+	origDigest   digest.Digest // original LLB digest. TODO: probably better to use string ID so this isn't needed
56 57
 
57 58
 	mu    sync.Mutex
58 59
 	op    *sharedOp
... ...
@@ -318,6 +320,7 @@ func (jl *Solver) loadUnlocked(v, parent Vertex, j *Job, cache map[Vertex]Vertex
318 318
 			mainCache:    jl.opts.DefaultCache,
319 319
 			cache:        map[string]CacheManager{},
320 320
 			solver:       jl,
321
+			origDigest:   origVtx.Digest(),
321 322
 		}
322 323
 		jl.actives[dgst] = st
323 324
 	}
... ...
@@ -564,7 +567,10 @@ func (s *sharedOp) LoadCache(ctx context.Context, rec *CacheRecord) (Result, err
564 564
 	return res, err
565 565
 }
566 566
 
567
-func (s *sharedOp) CalcSlowCache(ctx context.Context, index Index, f ResultBasedCacheFunc, res Result) (digest.Digest, error) {
567
+func (s *sharedOp) CalcSlowCache(ctx context.Context, index Index, f ResultBasedCacheFunc, res Result) (dgst digest.Digest, err error) {
568
+	defer func() {
569
+		err = errdefs.WrapVertex(err, s.st.origDigest)
570
+	}()
568 571
 	key, err := s.g.Do(ctx, fmt.Sprintf("slow-compute-%d", index), func(ctx context.Context) (interface{}, error) {
569 572
 		s.slowMu.Lock()
570 573
 		// TODO: add helpers for these stored values
... ...
@@ -609,7 +615,10 @@ func (s *sharedOp) CalcSlowCache(ctx context.Context, index Index, f ResultBased
609 609
 	return key.(digest.Digest), nil
610 610
 }
611 611
 
612
-func (s *sharedOp) CacheMap(ctx context.Context, index int) (*cacheMapResp, error) {
612
+func (s *sharedOp) CacheMap(ctx context.Context, index int) (resp *cacheMapResp, err error) {
613
+	defer func() {
614
+		err = errdefs.WrapVertex(err, s.st.origDigest)
615
+	}()
613 616
 	op, err := s.getOp()
614 617
 	if err != nil {
615 618
 		return nil, err
... ...
@@ -665,6 +674,9 @@ func (s *sharedOp) CacheMap(ctx context.Context, index int) (*cacheMapResp, erro
665 665
 }
666 666
 
667 667
 func (s *sharedOp) Exec(ctx context.Context, inputs []Result) (outputs []Result, exporters []ExportableCacheKey, err error) {
668
+	defer func() {
669
+		err = errdefs.WrapVertex(err, s.st.origDigest)
670
+	}()
668 671
 	op, err := s.getOp()
669 672
 	if err != nil {
670 673
 		return nil, nil, err
... ...
@@ -18,12 +18,12 @@ import (
18 18
 	gw "github.com/moby/buildkit/frontend/gateway/client"
19 19
 	"github.com/moby/buildkit/session"
20 20
 	"github.com/moby/buildkit/solver"
21
+	"github.com/moby/buildkit/solver/errdefs"
21 22
 	"github.com/moby/buildkit/solver/pb"
22 23
 	"github.com/moby/buildkit/util/flightcontrol"
23 24
 	"github.com/moby/buildkit/util/tracing"
24 25
 	"github.com/moby/buildkit/worker"
25 26
 	digest "github.com/opencontainers/go-digest"
26
-	specs "github.com/opencontainers/image-spec/specs-go/v1"
27 27
 	"github.com/pkg/errors"
28 28
 	"github.com/sirupsen/logrus"
29 29
 )
... ...
@@ -36,7 +36,6 @@ type llbBridge struct {
36 36
 	resolveCacheImporterFuncs map[string]remotecache.ResolveCacheImporterFunc
37 37
 	cms                       map[string]solver.CacheManager
38 38
 	cmsMu                     sync.Mutex
39
-	platforms                 []specs.Platform
40 39
 	sm                        *session.Manager
41 40
 }
42 41
 
... ...
@@ -88,7 +87,7 @@ func (b *llbBridge) loadResult(ctx context.Context, def *pb.Definition, cacheImp
88 88
 	}
89 89
 	dpc := &detectPrunedCacheID{}
90 90
 
91
-	edge, err := Load(def, dpc.Load, ValidateEntitlements(ent), WithCacheSources(cms), RuntimePlatforms(b.platforms), WithValidateCaps())
91
+	edge, err := Load(def, dpc.Load, ValidateEntitlements(ent), WithCacheSources(cms), NormalizeRuntimePlatforms(), WithValidateCaps())
92 92
 	if err != nil {
93 93
 		return nil, errors.Wrap(err, "failed to load LLB")
94 94
 	}
... ...
@@ -182,7 +181,31 @@ func (rp *resultProxy) Release(ctx context.Context) error {
182 182
 	return nil
183 183
 }
184 184
 
185
-func (rp *resultProxy) Result(ctx context.Context) (solver.CachedResult, error) {
185
+func (rp *resultProxy) wrapError(err error) error {
186
+	if err == nil {
187
+		return nil
188
+	}
189
+	var ve *errdefs.VertexError
190
+	if errors.As(err, &ve) {
191
+		if rp.def.Source != nil {
192
+			locs, ok := rp.def.Source.Locations[string(ve.Digest)]
193
+			if ok {
194
+				for _, loc := range locs.Locations {
195
+					err = errdefs.WithSource(err, errdefs.Source{
196
+						Info:   rp.def.Source.Infos[loc.SourceIndex],
197
+						Ranges: loc.Ranges,
198
+					})
199
+				}
200
+			}
201
+		}
202
+	}
203
+	return err
204
+}
205
+
206
+func (rp *resultProxy) Result(ctx context.Context) (res solver.CachedResult, err error) {
207
+	defer func() {
208
+		err = rp.wrapError(err)
209
+	}()
186 210
 	r, err := rp.g.Do(ctx, "result", func(ctx context.Context) (interface{}, error) {
187 211
 		rp.mu.Lock()
188 212
 		if rp.released {
... ...
@@ -34,16 +34,17 @@ func mapUserToChowner(user *copy.User, idmap *idtools.IdentityMapping) (copy.Cho
34 34
 					return nil, nil
35 35
 				}
36 36
 				old = &copy.User{} // root
37
-			}
38
-			if idmap != nil {
39
-				identity, err := idmap.ToHost(idtools.Identity{
40
-					UID: old.Uid,
41
-					GID: old.Gid,
42
-				})
43
-				if err != nil {
44
-					return nil, err
37
+				// non-nil old is already mapped
38
+				if idmap != nil {
39
+					identity, err := idmap.ToHost(idtools.Identity{
40
+						UID: old.Uid,
41
+						GID: old.Gid,
42
+					})
43
+					if err != nil {
44
+						return nil, err
45
+					}
46
+					return &copy.User{Uid: identity.UID, Gid: identity.GID}, nil
45 47
 				}
46
-				return &copy.User{Uid: identity.UID, Gid: identity.GID}, nil
47 48
 			}
48 49
 			return old, nil
49 50
 		}, nil
... ...
@@ -82,7 +83,7 @@ func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.
82 82
 		}
83 83
 	} else {
84 84
 		if err := os.Mkdir(p, os.FileMode(action.Mode)&0777); err != nil {
85
-			if os.IsExist(err) {
85
+			if errors.Is(err, os.ErrExist) {
86 86
 				return nil
87 87
 			}
88 88
 			return err
... ...
@@ -151,7 +152,7 @@ func rmPath(root, src string, allowNotFound bool) error {
151 151
 	}
152 152
 
153 153
 	if err := os.RemoveAll(p); err != nil {
154
-		if os.IsNotExist(errors.Cause(err)) && allowNotFound {
154
+		if errors.Is(err, os.ErrNotExist) && allowNotFound {
155 155
 			return nil
156 156
 		}
157 157
 		return err
... ...
@@ -293,6 +294,7 @@ func (fb *Backend) Mkfile(ctx context.Context, m, user, group fileoptypes.Mount,
293 293
 
294 294
 	return mkfile(ctx, dir, action, u, mnt.m.IdentityMapping())
295 295
 }
296
+
296 297
 func (fb *Backend) Rm(ctx context.Context, m fileoptypes.Mount, action pb.FileActionRm) error {
297 298
 	mnt, ok := m.(*Mount)
298 299
 	if !ok {
... ...
@@ -308,6 +310,7 @@ func (fb *Backend) Rm(ctx context.Context, m fileoptypes.Mount, action pb.FileAc
308 308
 
309 309
 	return rm(ctx, dir, action)
310 310
 }
311
+
311 312
 func (fb *Backend) Copy(ctx context.Context, m1, m2, user, group fileoptypes.Mount, action pb.FileActionCopy) error {
312 313
 	mnt1, ok := m1.(*Mount)
313 314
 	if !ok {
... ...
@@ -31,6 +31,7 @@ import (
31 31
 	"github.com/moby/buildkit/solver"
32 32
 	"github.com/moby/buildkit/solver/llbsolver"
33 33
 	"github.com/moby/buildkit/solver/pb"
34
+	"github.com/moby/buildkit/util/grpcerrors"
34 35
 	"github.com/moby/buildkit/util/progress/logs"
35 36
 	utilsystem "github.com/moby/buildkit/util/system"
36 37
 	"github.com/moby/buildkit/worker"
... ...
@@ -41,7 +42,6 @@ import (
41 41
 	"github.com/sirupsen/logrus"
42 42
 	bolt "go.etcd.io/bbolt"
43 43
 	"google.golang.org/grpc/codes"
44
-	"google.golang.org/grpc/status"
45 44
 )
46 45
 
47 46
 const execCacheType = "buildkit.exec.v0"
... ...
@@ -293,7 +293,7 @@ func (g *cacheRefGetter) getRefCacheDirNoCache(ctx context.Context, key string,
293 293
 			if mRef, err := g.cm.GetMutable(ctx, si.ID()); err == nil {
294 294
 				logrus.Debugf("reusing ref for cache dir: %s", mRef.ID())
295 295
 				return mRef, nil
296
-			} else if errors.Cause(err) == cache.ErrLocked {
296
+			} else if errors.Is(err, cache.ErrLocked) {
297 297
 				locked = true
298 298
 			}
299 299
 		}
... ...
@@ -349,7 +349,7 @@ func (e *execOp) getSSHMountable(ctx context.Context, m *pb.Mount) (cache.Mounta
349 349
 		if m.SSHOpt.Optional {
350 350
 			return nil, nil
351 351
 		}
352
-		if st, ok := status.FromError(errors.Cause(err)); ok && st.Code() == codes.Unimplemented {
352
+		if grpcerrors.Code(err) == codes.Unimplemented {
353 353
 			return nil, errors.Errorf("no SSH key %q forwarded from the client", m.SSHOpt.ID)
354 354
 		}
355 355
 		return nil, err
... ...
@@ -447,7 +447,7 @@ func (e *execOp) getSecretMountable(ctx context.Context, m *pb.Mount) (cache.Mou
447 447
 
448 448
 	dt, err := secrets.GetSecret(ctx, caller, id)
449 449
 	if err != nil {
450
-		if errors.Cause(err) == secrets.ErrNotFound && m.SecretOpt.Optional {
450
+		if errors.Is(err, secrets.ErrNotFound) && m.SecretOpt.Optional {
451 451
 			return nil, nil
452 452
 		}
453 453
 		return nil, err
... ...
@@ -708,6 +708,20 @@ func (e *execOp) Exec(ctx context.Context, inputs []solver.Result) ([]solver.Res
708 708
 		return nil, err
709 709
 	}
710 710
 
711
+	emu, err := getEmulator(e.platform, e.cm.IdentityMapping())
712
+	if err == nil && emu != nil {
713
+		e.op.Meta.Args = append([]string{qemuMountName}, e.op.Meta.Args...)
714
+
715
+		mounts = append(mounts, executor.Mount{
716
+			Readonly: true,
717
+			Src:      emu,
718
+			Dest:     qemuMountName,
719
+		})
720
+	}
721
+	if err != nil {
722
+		logrus.Warn(err.Error()) // TODO: remove this with pull support
723
+	}
724
+
711 725
 	meta := executor.Meta{
712 726
 		Args:           e.op.Meta.Args,
713 727
 		Env:            e.op.Meta.Env,
714 728
new file mode 100644
... ...
@@ -0,0 +1,114 @@
0
+package ops
1
+
2
+import (
3
+	"context"
4
+	"io/ioutil"
5
+	"os"
6
+	"os/exec"
7
+	"path/filepath"
8
+
9
+	"github.com/containerd/containerd/mount"
10
+	"github.com/containerd/containerd/platforms"
11
+	"github.com/docker/docker/pkg/idtools"
12
+	"github.com/moby/buildkit/snapshot"
13
+	"github.com/moby/buildkit/solver/pb"
14
+	"github.com/moby/buildkit/util/binfmt_misc"
15
+	specs "github.com/opencontainers/image-spec/specs-go/v1"
16
+	"github.com/pkg/errors"
17
+	copy "github.com/tonistiigi/fsutil/copy"
18
+)
19
+
20
+const qemuMountName = "/dev/.buildkit_qemu_emulator"
21
+
22
+var qemuArchMap = map[string]string{
23
+	"arm64":   "aarch64",
24
+	"amd64":   "x86_64",
25
+	"riscv64": "riscv64",
26
+	"arm":     "arm",
27
+	"s390x":   "s390x",
28
+	"ppc64le": "ppc64le",
29
+}
30
+
31
+type emulator struct {
32
+	path  string
33
+	idmap *idtools.IdentityMapping
34
+}
35
+
36
+func (e *emulator) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
37
+	return &staticEmulatorMount{path: e.path, idmap: e.idmap}, nil
38
+}
39
+
40
+type staticEmulatorMount struct {
41
+	path  string
42
+	idmap *idtools.IdentityMapping
43
+}
44
+
45
+func (m *staticEmulatorMount) Mount() ([]mount.Mount, func() error, error) {
46
+	tmpdir, err := ioutil.TempDir("", "buildkit-qemu-emulator")
47
+	if err != nil {
48
+		return nil, nil, err
49
+	}
50
+	var ret bool
51
+	defer func() {
52
+		if !ret {
53
+			os.RemoveAll(tmpdir)
54
+		}
55
+	}()
56
+
57
+	var uid, gid int
58
+	if m.idmap != nil {
59
+		root := m.idmap.RootPair()
60
+		uid = root.UID
61
+		gid = root.GID
62
+	}
63
+	if err := copy.Copy(context.TODO(), filepath.Dir(m.path), filepath.Base(m.path), tmpdir, qemuMountName, func(ci *copy.CopyInfo) {
64
+		m := 0555
65
+		ci.Mode = &m
66
+	}, copy.WithChown(uid, gid)); err != nil {
67
+		return nil, nil, err
68
+	}
69
+
70
+	ret = true
71
+	return []mount.Mount{{
72
+			Type:    "bind",
73
+			Source:  filepath.Join(tmpdir, qemuMountName),
74
+			Options: []string{"ro", "bind"},
75
+		}}, func() error {
76
+			return os.RemoveAll(tmpdir)
77
+		}, nil
78
+
79
+}
80
+func (m *staticEmulatorMount) IdentityMapping() *idtools.IdentityMapping {
81
+	return m.idmap
82
+}
83
+
84
+func getEmulator(p *pb.Platform, idmap *idtools.IdentityMapping) (*emulator, error) {
85
+	all := binfmt_misc.SupportedPlatforms(false)
86
+	m := make(map[string]struct{}, len(all))
87
+
88
+	for _, p := range all {
89
+		m[p] = struct{}{}
90
+	}
91
+
92
+	pp := platforms.Normalize(specs.Platform{
93
+		Architecture: p.Architecture,
94
+		OS:           p.OS,
95
+		Variant:      p.Variant,
96
+	})
97
+
98
+	if _, ok := m[platforms.Format(pp)]; ok {
99
+		return nil, nil
100
+	}
101
+
102
+	a, ok := qemuArchMap[pp.Architecture]
103
+	if !ok {
104
+		a = pp.Architecture
105
+	}
106
+
107
+	fn, err := exec.LookPath("buildkit-qemu-" + a)
108
+	if err != nil {
109
+		return nil, errors.Errorf("no emulator available for %v", pp.OS)
110
+	}
111
+
112
+	return &emulator{path: fn}, nil
113
+}
... ...
@@ -20,7 +20,6 @@ import (
20 20
 	"github.com/moby/buildkit/util/progress"
21 21
 	"github.com/moby/buildkit/worker"
22 22
 	digest "github.com/opencontainers/go-digest"
23
-	specs "github.com/opencontainers/image-spec/specs-go/v1"
24 23
 	"github.com/pkg/errors"
25 24
 	"golang.org/x/sync/errgroup"
26 25
 )
... ...
@@ -43,7 +42,6 @@ type Solver struct {
43 43
 	eachWorker                func(func(worker.Worker) error) error
44 44
 	frontends                 map[string]frontend.Frontend
45 45
 	resolveCacheImporterFuncs map[string]remotecache.ResolveCacheImporterFunc
46
-	platforms                 []specs.Platform
47 46
 	gatewayForwarder          *controlgateway.GatewayForwarder
48 47
 	sm                        *session.Manager
49 48
 	entitlements              []string
... ...
@@ -61,13 +59,6 @@ func New(wc *worker.Controller, f map[string]frontend.Frontend, cache solver.Cac
61 61
 		entitlements:              ents,
62 62
 	}
63 63
 
64
-	// executing is currently only allowed on default worker
65
-	w, err := wc.GetDefault()
66
-	if err != nil {
67
-		return nil, err
68
-	}
69
-	s.platforms = w.Platforms(false)
70
-
71 64
 	s.solver = solver.NewSolver(solver.SolverOpt{
72 65
 		ResolveOpFunc: s.resolver(),
73 66
 		DefaultCache:  cache,
... ...
@@ -93,7 +84,6 @@ func (s *Solver) Bridge(b solver.Builder) frontend.FrontendLLBBridge {
93 93
 		eachWorker:                s.eachWorker,
94 94
 		resolveCacheImporterFuncs: s.resolveCacheImporterFuncs,
95 95
 		cms:                       map[string]solver.CacheManager{},
96
-		platforms:                 s.platforms,
97 96
 		sm:                        s.sm,
98 97
 	}
99 98
 }
... ...
@@ -8,7 +8,6 @@ import (
8 8
 	"github.com/moby/buildkit/solver"
9 9
 	"github.com/moby/buildkit/solver/pb"
10 10
 	"github.com/moby/buildkit/source"
11
-	"github.com/moby/buildkit/util/binfmt_misc"
12 11
 	"github.com/moby/buildkit/util/entitlements"
13 12
 	digest "github.com/opencontainers/go-digest"
14 13
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
... ...
@@ -69,12 +68,8 @@ func WithCacheSources(cms []solver.CacheManager) LoadOpt {
69 69
 	}
70 70
 }
71 71
 
72
-func RuntimePlatforms(p []specs.Platform) LoadOpt {
72
+func NormalizeRuntimePlatforms() LoadOpt {
73 73
 	var defaultPlatform *pb.Platform
74
-	pp := make([]specs.Platform, len(p))
75
-	for i := range p {
76
-		pp[i] = platforms.Normalize(p[i])
77
-	}
78 74
 	return func(op *pb.Op, _ *pb.OpMetadata, opt *solver.VertexOptions) error {
79 75
 		if op.Platform == nil {
80 76
 			if defaultPlatform == nil {
... ...
@@ -96,22 +91,6 @@ func RuntimePlatforms(p []specs.Platform) LoadOpt {
96 96
 			Variant:      normalizedPlatform.Variant,
97 97
 		}
98 98
 
99
-		if _, ok := op.Op.(*pb.Op_Exec); ok {
100
-			var found bool
101
-			for _, pp := range pp {
102
-				if pp.OS == op.Platform.OS && pp.Architecture == op.Platform.Architecture && pp.Variant == op.Platform.Variant {
103
-					found = true
104
-					break
105
-				}
106
-			}
107
-			if !found {
108
-				if !binfmt_misc.Check(normalizedPlatform) {
109
-					return errors.Errorf("runtime execution on platform %s not supported", platforms.Format(specs.Platform{OS: op.Platform.OS, Architecture: op.Platform.Architecture, Variant: op.Platform.Variant}))
110
-				} else {
111
-					pp = append(pp, normalizedPlatform)
112
-				}
113
-			}
114
-		}
115 99
 		return nil
116 100
 	}
117 101
 }
... ...
@@ -1054,6 +1054,300 @@ func (m *OpMetadata) GetCaps() map[github_com_moby_buildkit_util_apicaps.CapID]b
1054 1054
 	return nil
1055 1055
 }
1056 1056
 
1057
+// Source is a source mapping description for a file
1058
+type Source struct {
1059
+	Locations map[string]*Locations `protobuf:"bytes,1,rep,name=locations,proto3" json:"locations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
1060
+	Infos     []*SourceInfo         `protobuf:"bytes,2,rep,name=infos,proto3" json:"infos,omitempty"`
1061
+}
1062
+
1063
+func (m *Source) Reset()         { *m = Source{} }
1064
+func (m *Source) String() string { return proto.CompactTextString(m) }
1065
+func (*Source) ProtoMessage()    {}
1066
+func (*Source) Descriptor() ([]byte, []int) {
1067
+	return fileDescriptor_8de16154b2733812, []int{13}
1068
+}
1069
+func (m *Source) XXX_Unmarshal(b []byte) error {
1070
+	return m.Unmarshal(b)
1071
+}
1072
+func (m *Source) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
1073
+	b = b[:cap(b)]
1074
+	n, err := m.MarshalToSizedBuffer(b)
1075
+	if err != nil {
1076
+		return nil, err
1077
+	}
1078
+	return b[:n], nil
1079
+}
1080
+func (m *Source) XXX_Merge(src proto.Message) {
1081
+	xxx_messageInfo_Source.Merge(m, src)
1082
+}
1083
+func (m *Source) XXX_Size() int {
1084
+	return m.Size()
1085
+}
1086
+func (m *Source) XXX_DiscardUnknown() {
1087
+	xxx_messageInfo_Source.DiscardUnknown(m)
1088
+}
1089
+
1090
+var xxx_messageInfo_Source proto.InternalMessageInfo
1091
+
1092
+func (m *Source) GetLocations() map[string]*Locations {
1093
+	if m != nil {
1094
+		return m.Locations
1095
+	}
1096
+	return nil
1097
+}
1098
+
1099
+func (m *Source) GetInfos() []*SourceInfo {
1100
+	if m != nil {
1101
+		return m.Infos
1102
+	}
1103
+	return nil
1104
+}
1105
+
1106
+// Locations is a list of ranges with a index to its source map.
1107
+type Locations struct {
1108
+	Locations []*Location `protobuf:"bytes,1,rep,name=locations,proto3" json:"locations,omitempty"`
1109
+}
1110
+
1111
+func (m *Locations) Reset()         { *m = Locations{} }
1112
+func (m *Locations) String() string { return proto.CompactTextString(m) }
1113
+func (*Locations) ProtoMessage()    {}
1114
+func (*Locations) Descriptor() ([]byte, []int) {
1115
+	return fileDescriptor_8de16154b2733812, []int{14}
1116
+}
1117
+func (m *Locations) XXX_Unmarshal(b []byte) error {
1118
+	return m.Unmarshal(b)
1119
+}
1120
+func (m *Locations) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
1121
+	b = b[:cap(b)]
1122
+	n, err := m.MarshalToSizedBuffer(b)
1123
+	if err != nil {
1124
+		return nil, err
1125
+	}
1126
+	return b[:n], nil
1127
+}
1128
+func (m *Locations) XXX_Merge(src proto.Message) {
1129
+	xxx_messageInfo_Locations.Merge(m, src)
1130
+}
1131
+func (m *Locations) XXX_Size() int {
1132
+	return m.Size()
1133
+}
1134
+func (m *Locations) XXX_DiscardUnknown() {
1135
+	xxx_messageInfo_Locations.DiscardUnknown(m)
1136
+}
1137
+
1138
+var xxx_messageInfo_Locations proto.InternalMessageInfo
1139
+
1140
+func (m *Locations) GetLocations() []*Location {
1141
+	if m != nil {
1142
+		return m.Locations
1143
+	}
1144
+	return nil
1145
+}
1146
+
1147
+// Source info contains the shared metadata of a source mapping
1148
+type SourceInfo struct {
1149
+	Filename   string      `protobuf:"bytes,1,opt,name=filename,proto3" json:"filename,omitempty"`
1150
+	Data       []byte      `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
1151
+	Definition *Definition `protobuf:"bytes,3,opt,name=definition,proto3" json:"definition,omitempty"`
1152
+}
1153
+
1154
+func (m *SourceInfo) Reset()         { *m = SourceInfo{} }
1155
+func (m *SourceInfo) String() string { return proto.CompactTextString(m) }
1156
+func (*SourceInfo) ProtoMessage()    {}
1157
+func (*SourceInfo) Descriptor() ([]byte, []int) {
1158
+	return fileDescriptor_8de16154b2733812, []int{15}
1159
+}
1160
+func (m *SourceInfo) XXX_Unmarshal(b []byte) error {
1161
+	return m.Unmarshal(b)
1162
+}
1163
+func (m *SourceInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
1164
+	b = b[:cap(b)]
1165
+	n, err := m.MarshalToSizedBuffer(b)
1166
+	if err != nil {
1167
+		return nil, err
1168
+	}
1169
+	return b[:n], nil
1170
+}
1171
+func (m *SourceInfo) XXX_Merge(src proto.Message) {
1172
+	xxx_messageInfo_SourceInfo.Merge(m, src)
1173
+}
1174
+func (m *SourceInfo) XXX_Size() int {
1175
+	return m.Size()
1176
+}
1177
+func (m *SourceInfo) XXX_DiscardUnknown() {
1178
+	xxx_messageInfo_SourceInfo.DiscardUnknown(m)
1179
+}
1180
+
1181
+var xxx_messageInfo_SourceInfo proto.InternalMessageInfo
1182
+
1183
+func (m *SourceInfo) GetFilename() string {
1184
+	if m != nil {
1185
+		return m.Filename
1186
+	}
1187
+	return ""
1188
+}
1189
+
1190
+func (m *SourceInfo) GetData() []byte {
1191
+	if m != nil {
1192
+		return m.Data
1193
+	}
1194
+	return nil
1195
+}
1196
+
1197
+func (m *SourceInfo) GetDefinition() *Definition {
1198
+	if m != nil {
1199
+		return m.Definition
1200
+	}
1201
+	return nil
1202
+}
1203
+
1204
+// Location defines list of areas in to source file
1205
+type Location struct {
1206
+	SourceIndex int32    `protobuf:"varint,1,opt,name=sourceIndex,proto3" json:"sourceIndex,omitempty"`
1207
+	Ranges      []*Range `protobuf:"bytes,2,rep,name=ranges,proto3" json:"ranges,omitempty"`
1208
+}
1209
+
1210
+func (m *Location) Reset()         { *m = Location{} }
1211
+func (m *Location) String() string { return proto.CompactTextString(m) }
1212
+func (*Location) ProtoMessage()    {}
1213
+func (*Location) Descriptor() ([]byte, []int) {
1214
+	return fileDescriptor_8de16154b2733812, []int{16}
1215
+}
1216
+func (m *Location) XXX_Unmarshal(b []byte) error {
1217
+	return m.Unmarshal(b)
1218
+}
1219
+func (m *Location) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
1220
+	b = b[:cap(b)]
1221
+	n, err := m.MarshalToSizedBuffer(b)
1222
+	if err != nil {
1223
+		return nil, err
1224
+	}
1225
+	return b[:n], nil
1226
+}
1227
+func (m *Location) XXX_Merge(src proto.Message) {
1228
+	xxx_messageInfo_Location.Merge(m, src)
1229
+}
1230
+func (m *Location) XXX_Size() int {
1231
+	return m.Size()
1232
+}
1233
+func (m *Location) XXX_DiscardUnknown() {
1234
+	xxx_messageInfo_Location.DiscardUnknown(m)
1235
+}
1236
+
1237
+var xxx_messageInfo_Location proto.InternalMessageInfo
1238
+
1239
+func (m *Location) GetSourceIndex() int32 {
1240
+	if m != nil {
1241
+		return m.SourceIndex
1242
+	}
1243
+	return 0
1244
+}
1245
+
1246
+func (m *Location) GetRanges() []*Range {
1247
+	if m != nil {
1248
+		return m.Ranges
1249
+	}
1250
+	return nil
1251
+}
1252
+
1253
+// Range is an area in the source file
1254
+type Range struct {
1255
+	Start Position `protobuf:"bytes,1,opt,name=start,proto3" json:"start"`
1256
+	End   Position `protobuf:"bytes,2,opt,name=end,proto3" json:"end"`
1257
+}
1258
+
1259
+func (m *Range) Reset()         { *m = Range{} }
1260
+func (m *Range) String() string { return proto.CompactTextString(m) }
1261
+func (*Range) ProtoMessage()    {}
1262
+func (*Range) Descriptor() ([]byte, []int) {
1263
+	return fileDescriptor_8de16154b2733812, []int{17}
1264
+}
1265
+func (m *Range) XXX_Unmarshal(b []byte) error {
1266
+	return m.Unmarshal(b)
1267
+}
1268
+func (m *Range) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
1269
+	b = b[:cap(b)]
1270
+	n, err := m.MarshalToSizedBuffer(b)
1271
+	if err != nil {
1272
+		return nil, err
1273
+	}
1274
+	return b[:n], nil
1275
+}
1276
+func (m *Range) XXX_Merge(src proto.Message) {
1277
+	xxx_messageInfo_Range.Merge(m, src)
1278
+}
1279
+func (m *Range) XXX_Size() int {
1280
+	return m.Size()
1281
+}
1282
+func (m *Range) XXX_DiscardUnknown() {
1283
+	xxx_messageInfo_Range.DiscardUnknown(m)
1284
+}
1285
+
1286
+var xxx_messageInfo_Range proto.InternalMessageInfo
1287
+
1288
+func (m *Range) GetStart() Position {
1289
+	if m != nil {
1290
+		return m.Start
1291
+	}
1292
+	return Position{}
1293
+}
1294
+
1295
+func (m *Range) GetEnd() Position {
1296
+	if m != nil {
1297
+		return m.End
1298
+	}
1299
+	return Position{}
1300
+}
1301
+
1302
+// Position is single location in a source file
1303
+type Position struct {
1304
+	Line      int32 `protobuf:"varint,1,opt,name=Line,proto3" json:"Line,omitempty"`
1305
+	Character int32 `protobuf:"varint,2,opt,name=Character,proto3" json:"Character,omitempty"`
1306
+}
1307
+
1308
+func (m *Position) Reset()         { *m = Position{} }
1309
+func (m *Position) String() string { return proto.CompactTextString(m) }
1310
+func (*Position) ProtoMessage()    {}
1311
+func (*Position) Descriptor() ([]byte, []int) {
1312
+	return fileDescriptor_8de16154b2733812, []int{18}
1313
+}
1314
+func (m *Position) XXX_Unmarshal(b []byte) error {
1315
+	return m.Unmarshal(b)
1316
+}
1317
+func (m *Position) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
1318
+	b = b[:cap(b)]
1319
+	n, err := m.MarshalToSizedBuffer(b)
1320
+	if err != nil {
1321
+		return nil, err
1322
+	}
1323
+	return b[:n], nil
1324
+}
1325
+func (m *Position) XXX_Merge(src proto.Message) {
1326
+	xxx_messageInfo_Position.Merge(m, src)
1327
+}
1328
+func (m *Position) XXX_Size() int {
1329
+	return m.Size()
1330
+}
1331
+func (m *Position) XXX_DiscardUnknown() {
1332
+	xxx_messageInfo_Position.DiscardUnknown(m)
1333
+}
1334
+
1335
+var xxx_messageInfo_Position proto.InternalMessageInfo
1336
+
1337
+func (m *Position) GetLine() int32 {
1338
+	if m != nil {
1339
+		return m.Line
1340
+	}
1341
+	return 0
1342
+}
1343
+
1344
+func (m *Position) GetCharacter() int32 {
1345
+	if m != nil {
1346
+		return m.Character
1347
+	}
1348
+	return 0
1349
+}
1350
+
1057 1351
 type ExportCache struct {
1058 1352
 	Value bool `protobuf:"varint,1,opt,name=Value,proto3" json:"Value,omitempty"`
1059 1353
 }
... ...
@@ -1062,7 +1356,7 @@ func (m *ExportCache) Reset()         { *m = ExportCache{} }
1062 1062
 func (m *ExportCache) String() string { return proto.CompactTextString(m) }
1063 1063
 func (*ExportCache) ProtoMessage()    {}
1064 1064
 func (*ExportCache) Descriptor() ([]byte, []int) {
1065
-	return fileDescriptor_8de16154b2733812, []int{13}
1065
+	return fileDescriptor_8de16154b2733812, []int{19}
1066 1066
 }
1067 1067
 func (m *ExportCache) XXX_Unmarshal(b []byte) error {
1068 1068
 	return m.Unmarshal(b)
... ...
@@ -1105,7 +1399,7 @@ func (m *ProxyEnv) Reset()         { *m = ProxyEnv{} }
1105 1105
 func (m *ProxyEnv) String() string { return proto.CompactTextString(m) }
1106 1106
 func (*ProxyEnv) ProtoMessage()    {}
1107 1107
 func (*ProxyEnv) Descriptor() ([]byte, []int) {
1108
-	return fileDescriptor_8de16154b2733812, []int{14}
1108
+	return fileDescriptor_8de16154b2733812, []int{20}
1109 1109
 }
1110 1110
 func (m *ProxyEnv) XXX_Unmarshal(b []byte) error {
1111 1111
 	return m.Unmarshal(b)
... ...
@@ -1167,7 +1461,7 @@ func (m *WorkerConstraints) Reset()         { *m = WorkerConstraints{} }
1167 1167
 func (m *WorkerConstraints) String() string { return proto.CompactTextString(m) }
1168 1168
 func (*WorkerConstraints) ProtoMessage()    {}
1169 1169
 func (*WorkerConstraints) Descriptor() ([]byte, []int) {
1170
-	return fileDescriptor_8de16154b2733812, []int{15}
1170
+	return fileDescriptor_8de16154b2733812, []int{21}
1171 1171
 }
1172 1172
 func (m *WorkerConstraints) XXX_Unmarshal(b []byte) error {
1173 1173
 	return m.Unmarshal(b)
... ...
@@ -1206,13 +1500,15 @@ type Definition struct {
1206 1206
 	// metadata contains metadata for the each of the Op messages.
1207 1207
 	// 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.
1208 1208
 	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"`
1209
+	// Source contains the source mapping information for the vertexes in the definition
1210
+	Source *Source `protobuf:"bytes,3,opt,name=Source,proto3" json:"Source,omitempty"`
1209 1211
 }
1210 1212
 
1211 1213
 func (m *Definition) Reset()         { *m = Definition{} }
1212 1214
 func (m *Definition) String() string { return proto.CompactTextString(m) }
1213 1215
 func (*Definition) ProtoMessage()    {}
1214 1216
 func (*Definition) Descriptor() ([]byte, []int) {
1215
-	return fileDescriptor_8de16154b2733812, []int{16}
1217
+	return fileDescriptor_8de16154b2733812, []int{22}
1216 1218
 }
1217 1219
 func (m *Definition) XXX_Unmarshal(b []byte) error {
1218 1220
 	return m.Unmarshal(b)
... ...
@@ -1251,6 +1547,13 @@ func (m *Definition) GetMetadata() map[github_com_opencontainers_go_digest.Diges
1251 1251
 	return nil
1252 1252
 }
1253 1253
 
1254
+func (m *Definition) GetSource() *Source {
1255
+	if m != nil {
1256
+		return m.Source
1257
+	}
1258
+	return nil
1259
+}
1260
+
1254 1261
 type HostIP struct {
1255 1262
 	Host string `protobuf:"bytes,1,opt,name=Host,proto3" json:"Host,omitempty"`
1256 1263
 	IP   string `protobuf:"bytes,2,opt,name=IP,proto3" json:"IP,omitempty"`
... ...
@@ -1260,7 +1563,7 @@ func (m *HostIP) Reset()         { *m = HostIP{} }
1260 1260
 func (m *HostIP) String() string { return proto.CompactTextString(m) }
1261 1261
 func (*HostIP) ProtoMessage()    {}
1262 1262
 func (*HostIP) Descriptor() ([]byte, []int) {
1263
-	return fileDescriptor_8de16154b2733812, []int{17}
1263
+	return fileDescriptor_8de16154b2733812, []int{23}
1264 1264
 }
1265 1265
 func (m *HostIP) XXX_Unmarshal(b []byte) error {
1266 1266
 	return m.Unmarshal(b)
... ...
@@ -1307,7 +1610,7 @@ func (m *FileOp) Reset()         { *m = FileOp{} }
1307 1307
 func (m *FileOp) String() string { return proto.CompactTextString(m) }
1308 1308
 func (*FileOp) ProtoMessage()    {}
1309 1309
 func (*FileOp) Descriptor() ([]byte, []int) {
1310
-	return fileDescriptor_8de16154b2733812, []int{18}
1310
+	return fileDescriptor_8de16154b2733812, []int{24}
1311 1311
 }
1312 1312
 func (m *FileOp) XXX_Unmarshal(b []byte) error {
1313 1313
 	return m.Unmarshal(b)
... ...
@@ -1355,7 +1658,7 @@ func (m *FileAction) Reset()         { *m = FileAction{} }
1355 1355
 func (m *FileAction) String() string { return proto.CompactTextString(m) }
1356 1356
 func (*FileAction) ProtoMessage()    {}
1357 1357
 func (*FileAction) Descriptor() ([]byte, []int) {
1358
-	return fileDescriptor_8de16154b2733812, []int{19}
1358
+	return fileDescriptor_8de16154b2733812, []int{25}
1359 1359
 }
1360 1360
 func (m *FileAction) XXX_Unmarshal(b []byte) error {
1361 1361
 	return m.Unmarshal(b)
... ...
@@ -1478,7 +1781,7 @@ func (m *FileActionCopy) Reset()         { *m = FileActionCopy{} }
1478 1478
 func (m *FileActionCopy) String() string { return proto.CompactTextString(m) }
1479 1479
 func (*FileActionCopy) ProtoMessage()    {}
1480 1480
 func (*FileActionCopy) Descriptor() ([]byte, []int) {
1481
-	return fileDescriptor_8de16154b2733812, []int{20}
1481
+	return fileDescriptor_8de16154b2733812, []int{26}
1482 1482
 }
1483 1483
 func (m *FileActionCopy) XXX_Unmarshal(b []byte) error {
1484 1484
 	return m.Unmarshal(b)
... ...
@@ -1597,7 +1900,7 @@ func (m *FileActionMkFile) Reset()         { *m = FileActionMkFile{} }
1597 1597
 func (m *FileActionMkFile) String() string { return proto.CompactTextString(m) }
1598 1598
 func (*FileActionMkFile) ProtoMessage()    {}
1599 1599
 func (*FileActionMkFile) Descriptor() ([]byte, []int) {
1600
-	return fileDescriptor_8de16154b2733812, []int{21}
1600
+	return fileDescriptor_8de16154b2733812, []int{27}
1601 1601
 }
1602 1602
 func (m *FileActionMkFile) XXX_Unmarshal(b []byte) error {
1603 1603
 	return m.Unmarshal(b)
... ...
@@ -1674,7 +1977,7 @@ func (m *FileActionMkDir) Reset()         { *m = FileActionMkDir{} }
1674 1674
 func (m *FileActionMkDir) String() string { return proto.CompactTextString(m) }
1675 1675
 func (*FileActionMkDir) ProtoMessage()    {}
1676 1676
 func (*FileActionMkDir) Descriptor() ([]byte, []int) {
1677
-	return fileDescriptor_8de16154b2733812, []int{22}
1677
+	return fileDescriptor_8de16154b2733812, []int{28}
1678 1678
 }
1679 1679
 func (m *FileActionMkDir) XXX_Unmarshal(b []byte) error {
1680 1680
 	return m.Unmarshal(b)
... ...
@@ -1747,7 +2050,7 @@ func (m *FileActionRm) Reset()         { *m = FileActionRm{} }
1747 1747
 func (m *FileActionRm) String() string { return proto.CompactTextString(m) }
1748 1748
 func (*FileActionRm) ProtoMessage()    {}
1749 1749
 func (*FileActionRm) Descriptor() ([]byte, []int) {
1750
-	return fileDescriptor_8de16154b2733812, []int{23}
1750
+	return fileDescriptor_8de16154b2733812, []int{29}
1751 1751
 }
1752 1752
 func (m *FileActionRm) XXX_Unmarshal(b []byte) error {
1753 1753
 	return m.Unmarshal(b)
... ...
@@ -1802,7 +2105,7 @@ func (m *ChownOpt) Reset()         { *m = ChownOpt{} }
1802 1802
 func (m *ChownOpt) String() string { return proto.CompactTextString(m) }
1803 1803
 func (*ChownOpt) ProtoMessage()    {}
1804 1804
 func (*ChownOpt) Descriptor() ([]byte, []int) {
1805
-	return fileDescriptor_8de16154b2733812, []int{24}
1805
+	return fileDescriptor_8de16154b2733812, []int{30}
1806 1806
 }
1807 1807
 func (m *ChownOpt) XXX_Unmarshal(b []byte) error {
1808 1808
 	return m.Unmarshal(b)
... ...
@@ -1852,7 +2155,7 @@ func (m *UserOpt) Reset()         { *m = UserOpt{} }
1852 1852
 func (m *UserOpt) String() string { return proto.CompactTextString(m) }
1853 1853
 func (*UserOpt) ProtoMessage()    {}
1854 1854
 func (*UserOpt) Descriptor() ([]byte, []int) {
1855
-	return fileDescriptor_8de16154b2733812, []int{25}
1855
+	return fileDescriptor_8de16154b2733812, []int{31}
1856 1856
 }
1857 1857
 func (m *UserOpt) XXX_Unmarshal(b []byte) error {
1858 1858
 	return m.Unmarshal(b)
... ...
@@ -1931,7 +2234,7 @@ func (m *NamedUserOpt) Reset()         { *m = NamedUserOpt{} }
1931 1931
 func (m *NamedUserOpt) String() string { return proto.CompactTextString(m) }
1932 1932
 func (*NamedUserOpt) ProtoMessage()    {}
1933 1933
 func (*NamedUserOpt) Descriptor() ([]byte, []int) {
1934
-	return fileDescriptor_8de16154b2733812, []int{26}
1934
+	return fileDescriptor_8de16154b2733812, []int{32}
1935 1935
 }
1936 1936
 func (m *NamedUserOpt) XXX_Unmarshal(b []byte) error {
1937 1937
 	return m.Unmarshal(b)
... ...
@@ -1986,6 +2289,13 @@ func init() {
1986 1986
 	proto.RegisterType((*OpMetadata)(nil), "pb.OpMetadata")
1987 1987
 	proto.RegisterMapType((map[github_com_moby_buildkit_util_apicaps.CapID]bool)(nil), "pb.OpMetadata.CapsEntry")
1988 1988
 	proto.RegisterMapType((map[string]string)(nil), "pb.OpMetadata.DescriptionEntry")
1989
+	proto.RegisterType((*Source)(nil), "pb.Source")
1990
+	proto.RegisterMapType((map[string]*Locations)(nil), "pb.Source.LocationsEntry")
1991
+	proto.RegisterType((*Locations)(nil), "pb.Locations")
1992
+	proto.RegisterType((*SourceInfo)(nil), "pb.SourceInfo")
1993
+	proto.RegisterType((*Location)(nil), "pb.Location")
1994
+	proto.RegisterType((*Range)(nil), "pb.Range")
1995
+	proto.RegisterType((*Position)(nil), "pb.Position")
1989 1996
 	proto.RegisterType((*ExportCache)(nil), "pb.ExportCache")
1990 1997
 	proto.RegisterType((*ProxyEnv)(nil), "pb.ProxyEnv")
1991 1998
 	proto.RegisterType((*WorkerConstraints)(nil), "pb.WorkerConstraints")
... ...
@@ -2006,131 +2316,144 @@ func init() {
2006 2006
 func init() { proto.RegisterFile("ops.proto", fileDescriptor_8de16154b2733812) }
2007 2007
 
2008 2008
 var fileDescriptor_8de16154b2733812 = []byte{
2009
-	// 1978 bytes of a gzipped FileDescriptorProto
2010
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x5f, 0x6f, 0x1b, 0xc7,
2011
-	0x11, 0xd7, 0x1d, 0xff, 0xde, 0x50, 0x92, 0xd9, 0x8d, 0x93, 0xb2, 0xaa, 0x2b, 0x29, 0x97, 0x34,
2012
-	0x90, 0x65, 0x5b, 0x02, 0x14, 0x20, 0x09, 0xf2, 0x50, 0x54, 0xfc, 0x63, 0x88, 0x49, 0x2c, 0x0a,
2013
-	0x4b, 0xdb, 0xe9, 0x9b, 0x71, 0xbc, 0x5b, 0x52, 0x07, 0xf2, 0x6e, 0x0f, 0x7b, 0x4b, 0x5b, 0x7c,
2014
-	0xe9, 0x83, 0x3f, 0x41, 0x80, 0x02, 0x7d, 0x6b, 0x81, 0xbe, 0x14, 0xe8, 0x87, 0xe8, 0x7b, 0x1e,
2015
-	0x83, 0xa2, 0x0f, 0x69, 0x1f, 0xd2, 0xc2, 0xfe, 0x22, 0xc5, 0xec, 0xee, 0xf1, 0x8e, 0xb4, 0x02,
2016
-	0xdb, 0x68, 0xd1, 0x27, 0xce, 0xcd, 0xfc, 0x76, 0x76, 0x76, 0x66, 0x76, 0x66, 0x96, 0xe0, 0xf0,
2017
-	0x24, 0x3d, 0x4a, 0x04, 0x97, 0x9c, 0xd8, 0xc9, 0x68, 0xe7, 0xde, 0x24, 0x94, 0x97, 0xf3, 0xd1,
2018
-	0x91, 0xcf, 0xa3, 0xe3, 0x09, 0x9f, 0xf0, 0x63, 0x25, 0x1a, 0xcd, 0xc7, 0xea, 0x4b, 0x7d, 0x28,
2019
-	0x4a, 0x2f, 0x71, 0xff, 0x64, 0x83, 0x3d, 0x48, 0xc8, 0xfb, 0x50, 0x0d, 0xe3, 0x64, 0x2e, 0xd3,
2020
-	0x96, 0xb5, 0x5f, 0x3a, 0x68, 0x9c, 0x38, 0x47, 0xc9, 0xe8, 0xa8, 0x8f, 0x1c, 0x6a, 0x04, 0x64,
2021
-	0x1f, 0xca, 0xec, 0x8a, 0xf9, 0x2d, 0x7b, 0xdf, 0x3a, 0x68, 0x9c, 0x00, 0x02, 0x7a, 0x57, 0xcc,
2022
-	0x1f, 0x24, 0x67, 0x1b, 0x54, 0x49, 0xc8, 0x47, 0x50, 0x4d, 0xf9, 0x5c, 0xf8, 0xac, 0x55, 0x52,
2023
-	0x98, 0x4d, 0xc4, 0x0c, 0x15, 0x47, 0xa1, 0x8c, 0x14, 0x35, 0x8d, 0xc3, 0x19, 0x6b, 0x95, 0x73,
2024
-	0x4d, 0xf7, 0xc3, 0x99, 0xc6, 0x28, 0x09, 0xf9, 0x00, 0x2a, 0xa3, 0x79, 0x38, 0x0b, 0x5a, 0x15,
2025
-	0x05, 0x69, 0x20, 0xa4, 0x8d, 0x0c, 0x85, 0xd1, 0x32, 0x72, 0x00, 0xf5, 0x64, 0xe6, 0xc9, 0x31,
2026
-	0x17, 0x51, 0x0b, 0xf2, 0x0d, 0x2f, 0x0c, 0x8f, 0x2e, 0xa5, 0xe4, 0x53, 0x68, 0xf8, 0x3c, 0x4e,
2027
-	0xa5, 0xf0, 0xc2, 0x58, 0xa6, 0xad, 0x86, 0x02, 0xbf, 0x8b, 0xe0, 0xaf, 0xb9, 0x98, 0x32, 0xd1,
2028
-	0xc9, 0x85, 0xb4, 0x88, 0x6c, 0x97, 0xc1, 0xe6, 0x89, 0xfb, 0x7b, 0x0b, 0xea, 0x99, 0x56, 0xe2,
2029
-	0xc2, 0xe6, 0xa9, 0xf0, 0x2f, 0x43, 0xc9, 0x7c, 0x39, 0x17, 0xac, 0x65, 0xed, 0x5b, 0x07, 0x0e,
2030
-	0x5d, 0xe1, 0x91, 0x6d, 0xb0, 0x07, 0x43, 0xe5, 0x28, 0x87, 0xda, 0x83, 0x21, 0x69, 0x41, 0xed,
2031
-	0xb1, 0x27, 0x42, 0x2f, 0x96, 0xca, 0x33, 0x0e, 0xcd, 0x3e, 0xc9, 0x2d, 0x70, 0x06, 0xc3, 0xc7,
2032
-	0x4c, 0xa4, 0x21, 0x8f, 0x95, 0x3f, 0x1c, 0x9a, 0x33, 0xc8, 0x2e, 0xc0, 0x60, 0x78, 0x9f, 0x79,
2033
-	0xa8, 0x34, 0x6d, 0x55, 0xf6, 0x4b, 0x07, 0x0e, 0x2d, 0x70, 0xdc, 0xdf, 0x42, 0x45, 0xc5, 0x88,
2034
-	0x7c, 0x01, 0xd5, 0x20, 0x9c, 0xb0, 0x54, 0x6a, 0x73, 0xda, 0x27, 0xdf, 0xfe, 0xb0, 0xb7, 0xf1,
2035
-	0xcf, 0x1f, 0xf6, 0x0e, 0x0b, 0xc9, 0xc0, 0x13, 0x16, 0xfb, 0x3c, 0x96, 0x5e, 0x18, 0x33, 0x91,
2036
-	0x1e, 0x4f, 0xf8, 0x3d, 0xbd, 0xe4, 0xa8, 0xab, 0x7e, 0xa8, 0xd1, 0x40, 0x6e, 0x43, 0x25, 0x8c,
2037
-	0x03, 0x76, 0xa5, 0xec, 0x2f, 0xb5, 0xdf, 0x31, 0xaa, 0x1a, 0x83, 0xb9, 0x4c, 0xe6, 0xb2, 0x8f,
2038
-	0x22, 0xaa, 0x11, 0xee, 0x1f, 0x2d, 0xa8, 0xea, 0x1c, 0x20, 0xb7, 0xa0, 0x1c, 0x31, 0xe9, 0xa9,
2039
-	0xfd, 0x1b, 0x27, 0x75, 0xf4, 0xed, 0x03, 0x26, 0x3d, 0xaa, 0xb8, 0x98, 0x5e, 0x11, 0x9f, 0xa3,
2040
-	0xef, 0xed, 0x3c, 0xbd, 0x1e, 0x20, 0x87, 0x1a, 0x01, 0xf9, 0x25, 0xd4, 0x62, 0x26, 0x9f, 0x71,
2041
-	0x31, 0x55, 0x3e, 0xda, 0xd6, 0x41, 0x3f, 0x67, 0xf2, 0x01, 0x0f, 0x18, 0xcd, 0x64, 0xe4, 0x2e,
2042
-	0xd4, 0x53, 0xe6, 0xcf, 0x45, 0x28, 0x17, 0xca, 0x5f, 0xdb, 0x27, 0x4d, 0x95, 0x65, 0x86, 0xa7,
2043
-	0xc0, 0x4b, 0x84, 0xfb, 0x17, 0x0b, 0xca, 0x68, 0x06, 0x21, 0x50, 0xf6, 0xc4, 0x44, 0x67, 0xb7,
2044
-	0x43, 0x15, 0x4d, 0x9a, 0x50, 0x62, 0xf1, 0x53, 0x65, 0x91, 0x43, 0x91, 0x44, 0x8e, 0xff, 0x2c,
2045
-	0x30, 0x31, 0x42, 0x12, 0xd7, 0xcd, 0x53, 0x26, 0x4c, 0x68, 0x14, 0x4d, 0x6e, 0x83, 0x93, 0x08,
2046
-	0x7e, 0xb5, 0x78, 0x82, 0xab, 0x2b, 0x85, 0xc4, 0x43, 0x66, 0x2f, 0x7e, 0x4a, 0xeb, 0x89, 0xa1,
2047
-	0xc8, 0x21, 0x00, 0xbb, 0x92, 0xc2, 0x3b, 0xe3, 0xa9, 0x4c, 0x5b, 0x55, 0x75, 0x76, 0x95, 0xef,
2048
-	0xc8, 0xe8, 0x5f, 0xd0, 0x82, 0xd4, 0xfd, 0x9b, 0x0d, 0x15, 0xe5, 0x12, 0x72, 0x80, 0x11, 0x48,
2049
-	0xe6, 0x3a, 0x98, 0xa5, 0x36, 0x31, 0x11, 0x00, 0x15, 0xeb, 0x65, 0x00, 0x30, 0xee, 0x3b, 0xe8,
2050
-	0x8d, 0x19, 0xf3, 0x25, 0x17, 0x26, 0xdd, 0x96, 0xdf, 0x68, 0x7a, 0x80, 0x19, 0xa1, 0x4f, 0xa3,
2051
-	0x68, 0x72, 0x07, 0xaa, 0x5c, 0x85, 0x51, 0x1d, 0xe8, 0x47, 0x82, 0x6b, 0x20, 0xa8, 0x5c, 0x30,
2052
-	0x2f, 0xe0, 0xf1, 0x6c, 0xa1, 0x8e, 0x59, 0xa7, 0xcb, 0x6f, 0x72, 0x07, 0x1c, 0x15, 0xb7, 0x87,
2053
-	0x8b, 0x84, 0xb5, 0xaa, 0x2a, 0x0e, 0x5b, 0xcb, 0x98, 0x22, 0x93, 0xe6, 0x72, 0xbc, 0xa8, 0xbe,
2054
-	0xe7, 0x5f, 0xb2, 0x41, 0x22, 0x5b, 0x37, 0x73, 0x7f, 0x75, 0x0c, 0x8f, 0x2e, 0xa5, 0xa8, 0x36,
2055
-	0x65, 0xbe, 0x60, 0x12, 0xa1, 0xef, 0x2a, 0xe8, 0x96, 0x09, 0xaf, 0x66, 0xd2, 0x5c, 0x4e, 0x5c,
2056
-	0xa8, 0x0e, 0x87, 0x67, 0x88, 0x7c, 0x2f, 0x2f, 0x24, 0x9a, 0x43, 0x8d, 0xc4, 0xed, 0x43, 0x3d,
2057
-	0xdb, 0x06, 0x6f, 0x65, 0xbf, 0x6b, 0xee, 0xab, 0xdd, 0xef, 0x92, 0x7b, 0x50, 0x4b, 0x2f, 0x3d,
2058
-	0x11, 0xc6, 0x13, 0xe5, 0xbb, 0xed, 0x93, 0x77, 0x96, 0x56, 0x0d, 0x35, 0x1f, 0x35, 0x65, 0x18,
2059
-	0x97, 0x83, 0xb3, 0x34, 0xe3, 0x15, 0x5d, 0x4d, 0x28, 0xcd, 0xc3, 0x40, 0xe9, 0xd9, 0xa2, 0x48,
2060
-	0x22, 0x67, 0x12, 0xea, 0x5c, 0xda, 0xa2, 0x48, 0x62, 0x40, 0x22, 0x1e, 0xe8, 0xb2, 0xb7, 0x45,
2061
-	0x15, 0x8d, 0x3e, 0xe6, 0x89, 0x0c, 0x79, 0xec, 0xcd, 0x32, 0x1f, 0x67, 0xdf, 0xee, 0x2c, 0x3b,
2062
-	0xdf, 0xff, 0x65, 0xb7, 0xdf, 0x59, 0x50, 0xcf, 0x6a, 0x35, 0x16, 0x9e, 0x30, 0x60, 0xb1, 0x0c,
2063
-	0xc7, 0x21, 0x13, 0x66, 0xe3, 0x02, 0x87, 0xdc, 0x83, 0x8a, 0x27, 0xa5, 0xc8, 0xae, 0xf3, 0x4f,
2064
-	0x8b, 0x85, 0xfe, 0xe8, 0x14, 0x25, 0xbd, 0x58, 0x8a, 0x05, 0xd5, 0xa8, 0x9d, 0xcf, 0x00, 0x72,
2065
-	0x26, 0xda, 0x3a, 0x65, 0x0b, 0xa3, 0x15, 0x49, 0x72, 0x13, 0x2a, 0x4f, 0xbd, 0xd9, 0x9c, 0x99,
2066
-	0x1c, 0xd6, 0x1f, 0x9f, 0xdb, 0x9f, 0x59, 0xee, 0x5f, 0x6d, 0xa8, 0x99, 0xc2, 0x4f, 0xee, 0x42,
2067
-	0x4d, 0x15, 0x7e, 0x63, 0xd1, 0xf5, 0x17, 0x23, 0x83, 0x90, 0xe3, 0x65, 0x47, 0x2b, 0xd8, 0x68,
2068
-	0x54, 0xe9, 0xce, 0x66, 0x6c, 0xcc, 0xfb, 0x5b, 0x29, 0x60, 0x63, 0xd3, 0xba, 0xb6, 0x11, 0xdd,
2069
-	0x65, 0xe3, 0x30, 0x0e, 0xd1, 0x3f, 0x14, 0x45, 0xe4, 0x6e, 0x76, 0xea, 0xb2, 0xd2, 0xf8, 0x5e,
2070
-	0x51, 0xe3, 0xab, 0x87, 0xee, 0x43, 0xa3, 0xb0, 0xcd, 0x35, 0xa7, 0xfe, 0xb0, 0x78, 0x6a, 0xb3,
2071
-	0xa5, 0x52, 0xa7, 0xfb, 0x6e, 0xee, 0x85, 0xff, 0xc2, 0x7f, 0x9f, 0x00, 0xe4, 0x2a, 0xdf, 0xbc,
2072
-	0xb0, 0xb8, 0xcf, 0x4b, 0x00, 0x83, 0x04, 0x4b, 0x67, 0xe0, 0xa9, 0xfa, 0xbd, 0x19, 0x4e, 0x62,
2073
-	0x2e, 0xd8, 0x13, 0x75, 0x55, 0xd5, 0xfa, 0x3a, 0x6d, 0x68, 0x9e, 0xba, 0x31, 0xe4, 0x14, 0x1a,
2074
-	0x01, 0x4b, 0x7d, 0x11, 0xaa, 0x84, 0x32, 0x4e, 0xdf, 0xc3, 0x33, 0xe5, 0x7a, 0x8e, 0xba, 0x39,
2075
-	0x42, 0xfb, 0xaa, 0xb8, 0x86, 0x9c, 0xc0, 0x26, 0xbb, 0x4a, 0xb8, 0x90, 0x66, 0x17, 0x3d, 0x1f,
2076
-	0xdc, 0xd0, 0x93, 0x06, 0xf2, 0xd5, 0x4e, 0xb4, 0xc1, 0xf2, 0x0f, 0xe2, 0x41, 0xd9, 0xf7, 0x12,
2077
-	0xdd, 0x1c, 0x1b, 0x27, 0xad, 0xb5, 0xfd, 0x3a, 0x5e, 0xa2, 0x9d, 0xd6, 0xfe, 0x18, 0xcf, 0xfa,
2078
-	0xfc, 0x5f, 0x7b, 0x77, 0x0a, 0x1d, 0x31, 0xe2, 0xa3, 0xc5, 0xb1, 0xca, 0x97, 0x69, 0x28, 0x8f,
2079
-	0xe7, 0x32, 0x9c, 0x1d, 0x7b, 0x49, 0x88, 0xea, 0x70, 0x61, 0xbf, 0x4b, 0x95, 0xea, 0x9d, 0x5f,
2080
-	0x41, 0x73, 0xdd, 0xee, 0xb7, 0x89, 0xc1, 0xce, 0xa7, 0xe0, 0x2c, 0xed, 0x78, 0xdd, 0xc2, 0x7a,
2081
-	0x31, 0x78, 0x1f, 0x40, 0xa3, 0x70, 0x6e, 0x04, 0x3e, 0x56, 0x40, 0xed, 0x7d, 0xfd, 0xe1, 0x3e,
2082
-	0xc7, 0xe1, 0x24, 0xeb, 0x37, 0xbf, 0x00, 0xb8, 0x94, 0x32, 0x79, 0xa2, 0x1a, 0x90, 0xd9, 0xc4,
2083
-	0x41, 0x8e, 0x42, 0x90, 0x3d, 0x68, 0xe0, 0x47, 0x6a, 0xe4, 0xda, 0x52, 0xb5, 0x22, 0xd5, 0x80,
2084
-	0x9f, 0x83, 0x33, 0x5e, 0x2e, 0xd7, 0x8d, 0xa3, 0x3e, 0xce, 0x56, 0xff, 0x0c, 0xea, 0x31, 0x37,
2085
-	0x32, 0xdd, 0x0f, 0x6b, 0x31, 0x57, 0x22, 0xf7, 0x0e, 0xfc, 0xe4, 0x95, 0x49, 0x8a, 0xbc, 0x07,
2086
-	0xd5, 0x71, 0x38, 0x93, 0xea, 0xba, 0x62, 0x8b, 0x35, 0x5f, 0xee, 0x3f, 0x2c, 0x80, 0xfc, 0x6a,
2087
-	0xa1, 0x47, 0xf0, 0xde, 0x21, 0x66, 0x53, 0xdf, 0xb3, 0x19, 0xd4, 0x23, 0x13, 0x41, 0x93, 0x47,
2088
-	0xb7, 0x56, 0xaf, 0xe3, 0x51, 0x16, 0x60, 0x1d, 0xdb, 0x13, 0x13, 0xdb, 0xb7, 0x99, 0x76, 0x96,
2089
-	0x3b, 0xec, 0x7c, 0x09, 0x5b, 0x2b, 0xea, 0xde, 0xf0, 0xa6, 0xe6, 0x59, 0x56, 0x0c, 0xd9, 0x5d,
2090
-	0xa8, 0xea, 0xd6, 0x8e, 0xf5, 0x17, 0x29, 0xa3, 0x46, 0xd1, 0xaa, 0x8e, 0x5f, 0x64, 0x73, 0x61,
2091
-	0xff, 0xc2, 0x3d, 0x81, 0xaa, 0x1e, 0x7c, 0xc9, 0x01, 0xd4, 0x3c, 0x1f, 0x8f, 0x96, 0x95, 0xab,
2092
-	0xed, 0x6c, 0x2a, 0x3e, 0x55, 0x6c, 0x9a, 0x89, 0xdd, 0xbf, 0xdb, 0x00, 0x39, 0xff, 0x2d, 0x66,
2093
-	0x85, 0xcf, 0x61, 0x3b, 0x65, 0x3e, 0x8f, 0x03, 0x4f, 0x2c, 0x94, 0xd4, 0x0c, 0x78, 0xd7, 0x2d,
2094
-	0x59, 0x43, 0x16, 0xe6, 0x86, 0xd2, 0xeb, 0xe7, 0x86, 0x03, 0x28, 0xfb, 0x3c, 0x59, 0x98, 0xeb,
2095
-	0x4b, 0x56, 0x0f, 0xd2, 0xe1, 0xc9, 0x02, 0xc7, 0x7c, 0x44, 0x90, 0x23, 0xa8, 0x46, 0x53, 0xf5,
2096
-	0x14, 0xd0, 0x63, 0xd4, 0xcd, 0x55, 0xec, 0x83, 0x29, 0xd2, 0xf8, 0x70, 0xd0, 0x28, 0x72, 0x07,
2097
-	0x2a, 0xd1, 0x34, 0x08, 0x85, 0x9a, 0x38, 0x1a, 0xba, 0x5f, 0x17, 0xe1, 0xdd, 0x50, 0xe0, 0xf3,
2098
-	0x40, 0x61, 0x88, 0x0b, 0xb6, 0x88, 0x5a, 0x35, 0x85, 0x6c, 0xae, 0x79, 0x33, 0x3a, 0xdb, 0xa0,
2099
-	0xb6, 0x88, 0xda, 0x75, 0xa8, 0x6a, 0xbf, 0xba, 0x7f, 0x2e, 0xc1, 0xf6, 0xaa, 0x95, 0x98, 0x07,
2100
-	0xa9, 0xf0, 0xb3, 0x3c, 0x48, 0x85, 0xbf, 0x1c, 0xa9, 0xec, 0xc2, 0x48, 0xe5, 0x42, 0x85, 0x3f,
2101
-	0x8b, 0x99, 0x28, 0xbe, 0x79, 0x3a, 0x97, 0xfc, 0x59, 0x8c, 0xc3, 0x83, 0x16, 0xad, 0xf4, 0xe2,
2102
-	0x8a, 0xe9, 0xc5, 0x1f, 0xc2, 0xd6, 0x98, 0xcf, 0x66, 0xfc, 0xd9, 0x70, 0x11, 0xcd, 0xc2, 0x78,
2103
-	0x6a, 0x1a, 0xf2, 0x2a, 0x93, 0x1c, 0xc0, 0x8d, 0x20, 0x14, 0x68, 0x4e, 0x87, 0xc7, 0x92, 0xc5,
2104
-	0x6a, 0x8a, 0x44, 0xdc, 0x3a, 0x9b, 0x7c, 0x01, 0xfb, 0x9e, 0x94, 0x2c, 0x4a, 0xe4, 0xa3, 0x38,
2105
-	0xf1, 0xfc, 0x69, 0x97, 0xfb, 0xea, 0x3e, 0x46, 0x89, 0x27, 0xc3, 0x51, 0x38, 0xc3, 0x81, 0xb9,
2106
-	0xa6, 0x96, 0xbe, 0x16, 0x47, 0x3e, 0x82, 0x6d, 0x5f, 0x30, 0x4f, 0xb2, 0x2e, 0x4b, 0xe5, 0x85,
2107
-	0x27, 0x2f, 0x5b, 0x75, 0xb5, 0x72, 0x8d, 0x8b, 0x67, 0xf0, 0xd0, 0xda, 0xaf, 0xc3, 0x59, 0xe0,
2108
-	0x7b, 0x22, 0x68, 0x39, 0xfa, 0x0c, 0x2b, 0x4c, 0x72, 0x04, 0x44, 0x31, 0x7a, 0x51, 0x22, 0x17,
2109
-	0x4b, 0x28, 0x28, 0xe8, 0x35, 0x12, 0x7c, 0x13, 0xc9, 0x30, 0x62, 0xa9, 0xf4, 0xa2, 0x44, 0xbd,
2110
-	0xd5, 0x4a, 0x34, 0x67, 0xb8, 0xdf, 0x58, 0xd0, 0x5c, 0x4f, 0x11, 0x74, 0x70, 0x82, 0x66, 0x9a,
2111
-	0xcb, 0x86, 0xf4, 0xd2, 0xe9, 0x76, 0xc1, 0xe9, 0x18, 0x40, 0xac, 0x2a, 0x18, 0xab, 0x4d, 0xaa,
2112
-	0xe8, 0x3c, 0x80, 0xe5, 0x1f, 0x0f, 0xe0, 0x8a, 0x49, 0x95, 0x75, 0x93, 0xfe, 0x60, 0xc1, 0x8d,
2113
-	0xb5, 0x34, 0x7c, 0x63, 0x8b, 0xf6, 0xa1, 0x11, 0x79, 0x53, 0x76, 0xe1, 0x09, 0x15, 0xdc, 0x92,
2114
-	0x6e, 0xac, 0x05, 0xd6, 0xff, 0xc0, 0xbe, 0x18, 0x36, 0x8b, 0xb9, 0x7f, 0xad, 0x6d, 0x59, 0x28,
2115
-	0xcf, 0xb9, 0xbc, 0xcf, 0xe7, 0x71, 0x60, 0xba, 0xd1, 0x2a, 0xf3, 0xd5, 0x80, 0x97, 0xae, 0x09,
2116
-	0xb8, 0x7b, 0x0e, 0xf5, 0xcc, 0x40, 0xb2, 0x67, 0x1e, 0x50, 0x56, 0xfe, 0x90, 0x7f, 0x94, 0x32,
2117
-	0x81, 0xb6, 0xeb, 0xd7, 0xd4, 0xfb, 0x50, 0x99, 0x08, 0x3e, 0x4f, 0x4c, 0x6d, 0x5d, 0x41, 0x68,
2118
-	0x89, 0x3b, 0x84, 0x9a, 0xe1, 0x90, 0x43, 0xa8, 0x8e, 0x16, 0xe7, 0x5e, 0xc4, 0x8c, 0x42, 0x75,
2119
-	0xb1, 0xf1, 0x3b, 0x30, 0x08, 0xac, 0x16, 0x1a, 0x41, 0x6e, 0x42, 0x79, 0xb4, 0xe8, 0x77, 0xf5,
2120
-	0x98, 0x8c, 0x35, 0x07, 0xbf, 0xda, 0x55, 0x6d, 0x90, 0xfb, 0x15, 0x6c, 0x16, 0xd7, 0xa1, 0x53,
2121
-	0xe2, 0x4c, 0xaf, 0x43, 0x15, 0x9d, 0x17, 0x57, 0xfb, 0x35, 0xc5, 0xf5, 0xf0, 0x00, 0x6a, 0xe6,
2122
-	0xa9, 0x4a, 0x1c, 0xa8, 0x3c, 0x3a, 0x1f, 0xf6, 0x1e, 0x36, 0x37, 0x48, 0x1d, 0xca, 0x67, 0x83,
2123
-	0xe1, 0xc3, 0xa6, 0x85, 0xd4, 0xf9, 0xe0, 0xbc, 0xd7, 0xb4, 0x0f, 0x6f, 0xc3, 0x66, 0xf1, 0xb1,
2124
-	0x4a, 0x1a, 0x50, 0x1b, 0x9e, 0x9e, 0x77, 0xdb, 0x83, 0xdf, 0x34, 0x37, 0xc8, 0x26, 0xd4, 0xfb,
2125
-	0xe7, 0xc3, 0x5e, 0xe7, 0x11, 0xed, 0x35, 0xad, 0xc3, 0x5f, 0x83, 0xb3, 0x7c, 0x4f, 0xa1, 0x86,
2126
-	0x76, 0xff, 0xbc, 0xdb, 0xdc, 0x20, 0x00, 0xd5, 0x61, 0xaf, 0x43, 0x7b, 0xa8, 0xb7, 0x06, 0xa5,
2127
-	0xe1, 0xf0, 0xac, 0x69, 0xe3, 0xae, 0x9d, 0xd3, 0xce, 0x59, 0xaf, 0x59, 0x42, 0xf2, 0xe1, 0x83,
2128
-	0x8b, 0xfb, 0xc3, 0x66, 0xf9, 0xf0, 0x13, 0xb8, 0xb1, 0xf6, 0x9e, 0x51, 0xab, 0xcf, 0x4e, 0x69,
2129
-	0x0f, 0x35, 0x35, 0xa0, 0x76, 0x41, 0xfb, 0x8f, 0x4f, 0x1f, 0xf6, 0x9a, 0x16, 0x0a, 0xbe, 0x1a,
2130
-	0x74, 0xbe, 0xec, 0x75, 0x9b, 0x76, 0xfb, 0xd6, 0xb7, 0x2f, 0x76, 0xad, 0xef, 0x5e, 0xec, 0x5a,
2131
-	0xdf, 0xbf, 0xd8, 0xb5, 0xfe, 0xfd, 0x62, 0xd7, 0xfa, 0xe6, 0xe5, 0xee, 0xc6, 0x77, 0x2f, 0x77,
2132
-	0x37, 0xbe, 0x7f, 0xb9, 0xbb, 0x31, 0xaa, 0xaa, 0xbf, 0x8e, 0x3e, 0xfe, 0x4f, 0x00, 0x00, 0x00,
2133
-	0xff, 0xff, 0x87, 0x95, 0x80, 0x20, 0x7a, 0x12, 0x00, 0x00,
2009
+	// 2189 bytes of a gzipped FileDescriptorProto
2010
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4b, 0x6f, 0x1b, 0xc9,
2011
+	0xf1, 0x17, 0xdf, 0x64, 0x51, 0x92, 0xf9, 0xef, 0xf5, 0xee, 0x9f, 0xab, 0x38, 0x92, 0x76, 0xec,
2012
+	0x2c, 0x64, 0xd9, 0xa6, 0x00, 0x2d, 0xb0, 0x5e, 0x2c, 0x82, 0x20, 0xe2, 0xc3, 0x10, 0xd7, 0xb6,
2013
+	0x28, 0x34, 0xfd, 0xc8, 0xcd, 0x18, 0x0d, 0x9b, 0xd4, 0x40, 0xe4, 0xf4, 0xa0, 0xa7, 0x69, 0x8b,
2014
+	0x97, 0x1c, 0xfc, 0x09, 0x16, 0x08, 0x90, 0x5b, 0x02, 0xe4, 0x12, 0x20, 0xf7, 0x5c, 0x73, 0xdf,
2015
+	0xe3, 0x22, 0xc8, 0x61, 0x91, 0xc3, 0x26, 0xb0, 0x3f, 0x47, 0x80, 0xa0, 0xaa, 0x7b, 0x1e, 0x94,
2016
+	0x65, 0xd8, 0x46, 0x82, 0x9c, 0xd8, 0xfd, 0xab, 0x5f, 0x57, 0x57, 0x57, 0x55, 0xd7, 0x54, 0x13,
2017
+	0x6a, 0x32, 0x8c, 0x5a, 0xa1, 0x92, 0x5a, 0xb2, 0x7c, 0x78, 0xb2, 0x71, 0x67, 0xe2, 0xeb, 0xd3,
2018
+	0xf9, 0x49, 0xcb, 0x93, 0xb3, 0xbd, 0x89, 0x9c, 0xc8, 0x3d, 0x12, 0x9d, 0xcc, 0xc7, 0x34, 0xa3,
2019
+	0x09, 0x8d, 0xcc, 0x12, 0xe7, 0x0f, 0x79, 0xc8, 0x0f, 0x42, 0xf6, 0x19, 0x94, 0xfd, 0x20, 0x9c,
2020
+	0xeb, 0xa8, 0x99, 0xdb, 0x2e, 0xec, 0xd4, 0xf7, 0x6b, 0xad, 0xf0, 0xa4, 0xd5, 0x47, 0x84, 0x5b,
2021
+	0x01, 0xdb, 0x86, 0xa2, 0x38, 0x17, 0x5e, 0x33, 0xbf, 0x9d, 0xdb, 0xa9, 0xef, 0x03, 0x12, 0x7a,
2022
+	0xe7, 0xc2, 0x1b, 0x84, 0x87, 0x2b, 0x9c, 0x24, 0xec, 0x73, 0x28, 0x47, 0x72, 0xae, 0x3c, 0xd1,
2023
+	0x2c, 0x10, 0x67, 0x15, 0x39, 0x43, 0x42, 0x88, 0x65, 0xa5, 0xa8, 0x69, 0xec, 0x4f, 0x45, 0xb3,
2024
+	0x98, 0x6a, 0xba, 0xe7, 0x4f, 0x0d, 0x87, 0x24, 0xec, 0x3a, 0x94, 0x4e, 0xe6, 0xfe, 0x74, 0xd4,
2025
+	0x2c, 0x11, 0xa5, 0x8e, 0x94, 0x36, 0x02, 0xc4, 0x31, 0x32, 0xb6, 0x03, 0xd5, 0x70, 0xea, 0xea,
2026
+	0xb1, 0x54, 0xb3, 0x26, 0xa4, 0x1b, 0x1e, 0x5b, 0x8c, 0x27, 0x52, 0x76, 0x17, 0xea, 0x9e, 0x0c,
2027
+	0x22, 0xad, 0x5c, 0x3f, 0xd0, 0x51, 0xb3, 0x4e, 0xe4, 0x8f, 0x91, 0xfc, 0x54, 0xaa, 0x33, 0xa1,
2028
+	0x3a, 0xa9, 0x90, 0x67, 0x99, 0xed, 0x22, 0xe4, 0x65, 0xe8, 0xfc, 0x36, 0x07, 0xd5, 0x58, 0x2b,
2029
+	0x73, 0x60, 0xf5, 0x40, 0x79, 0xa7, 0xbe, 0x16, 0x9e, 0x9e, 0x2b, 0xd1, 0xcc, 0x6d, 0xe7, 0x76,
2030
+	0x6a, 0x7c, 0x09, 0x63, 0xeb, 0x90, 0x1f, 0x0c, 0xc9, 0x51, 0x35, 0x9e, 0x1f, 0x0c, 0x59, 0x13,
2031
+	0x2a, 0x4f, 0x5c, 0xe5, 0xbb, 0x81, 0x26, 0xcf, 0xd4, 0x78, 0x3c, 0x65, 0xd7, 0xa0, 0x36, 0x18,
2032
+	0x3e, 0x11, 0x2a, 0xf2, 0x65, 0x40, 0xfe, 0xa8, 0xf1, 0x14, 0x60, 0x9b, 0x00, 0x83, 0xe1, 0x3d,
2033
+	0xe1, 0xa2, 0xd2, 0xa8, 0x59, 0xda, 0x2e, 0xec, 0xd4, 0x78, 0x06, 0x71, 0x7e, 0x0d, 0x25, 0x8a,
2034
+	0x11, 0xfb, 0x06, 0xca, 0x23, 0x7f, 0x22, 0x22, 0x6d, 0xcc, 0x69, 0xef, 0x7f, 0xf7, 0xe3, 0xd6,
2035
+	0xca, 0xdf, 0x7f, 0xdc, 0xda, 0xcd, 0x24, 0x83, 0x0c, 0x45, 0xe0, 0xc9, 0x40, 0xbb, 0x7e, 0x20,
2036
+	0x54, 0xb4, 0x37, 0x91, 0x77, 0xcc, 0x92, 0x56, 0x97, 0x7e, 0xb8, 0xd5, 0xc0, 0x6e, 0x42, 0xc9,
2037
+	0x0f, 0x46, 0xe2, 0x9c, 0xec, 0x2f, 0xb4, 0x3f, 0xb2, 0xaa, 0xea, 0x83, 0xb9, 0x0e, 0xe7, 0xba,
2038
+	0x8f, 0x22, 0x6e, 0x18, 0xce, 0xef, 0x73, 0x50, 0x36, 0x39, 0xc0, 0xae, 0x41, 0x71, 0x26, 0xb4,
2039
+	0x4b, 0xfb, 0xd7, 0xf7, 0xab, 0xe8, 0xdb, 0x87, 0x42, 0xbb, 0x9c, 0x50, 0x4c, 0xaf, 0x99, 0x9c,
2040
+	0xa3, 0xef, 0xf3, 0x69, 0x7a, 0x3d, 0x44, 0x84, 0x5b, 0x01, 0xfb, 0x19, 0x54, 0x02, 0xa1, 0x5f,
2041
+	0x48, 0x75, 0x46, 0x3e, 0x5a, 0x37, 0x41, 0x3f, 0x12, 0xfa, 0xa1, 0x1c, 0x09, 0x1e, 0xcb, 0xd8,
2042
+	0x6d, 0xa8, 0x46, 0xc2, 0x9b, 0x2b, 0x5f, 0x2f, 0xc8, 0x5f, 0xeb, 0xfb, 0x0d, 0xca, 0x32, 0x8b,
2043
+	0x11, 0x39, 0x61, 0x38, 0x7f, 0xca, 0x41, 0x11, 0xcd, 0x60, 0x0c, 0x8a, 0xae, 0x9a, 0x98, 0xec,
2044
+	0xae, 0x71, 0x1a, 0xb3, 0x06, 0x14, 0x44, 0xf0, 0x9c, 0x2c, 0xaa, 0x71, 0x1c, 0x22, 0xe2, 0xbd,
2045
+	0x18, 0xd9, 0x18, 0xe1, 0x10, 0xd7, 0xcd, 0x23, 0xa1, 0x6c, 0x68, 0x68, 0xcc, 0x6e, 0x42, 0x2d,
2046
+	0x54, 0xf2, 0x7c, 0xf1, 0x0c, 0x57, 0x97, 0x32, 0x89, 0x87, 0x60, 0x2f, 0x78, 0xce, 0xab, 0xa1,
2047
+	0x1d, 0xb1, 0x5d, 0x00, 0x71, 0xae, 0x95, 0x7b, 0x28, 0x23, 0x1d, 0x35, 0xcb, 0x74, 0x76, 0xca,
2048
+	0x77, 0x04, 0xfa, 0xc7, 0x3c, 0x23, 0x75, 0xfe, 0x9a, 0x87, 0x12, 0xb9, 0x84, 0xed, 0x60, 0x04,
2049
+	0xc2, 0xb9, 0x09, 0x66, 0xa1, 0xcd, 0x6c, 0x04, 0x80, 0x62, 0x9d, 0x04, 0x00, 0xe3, 0xbe, 0x81,
2050
+	0xde, 0x98, 0x0a, 0x4f, 0x4b, 0x65, 0xd3, 0x2d, 0x99, 0xa3, 0xe9, 0x23, 0xcc, 0x08, 0x73, 0x1a,
2051
+	0x1a, 0xb3, 0x5b, 0x50, 0x96, 0x14, 0x46, 0x3a, 0xd0, 0x5b, 0x82, 0x6b, 0x29, 0xa8, 0x5c, 0x09,
2052
+	0x77, 0x24, 0x83, 0xe9, 0x82, 0x8e, 0x59, 0xe5, 0xc9, 0x9c, 0xdd, 0x82, 0x1a, 0xc5, 0xed, 0xd1,
2053
+	0x22, 0x14, 0xcd, 0x32, 0xc5, 0x61, 0x2d, 0x89, 0x29, 0x82, 0x3c, 0x95, 0xe3, 0x45, 0xf5, 0x5c,
2054
+	0xef, 0x54, 0x0c, 0x42, 0xdd, 0xbc, 0x9a, 0xfa, 0xab, 0x63, 0x31, 0x9e, 0x48, 0x51, 0x6d, 0x24,
2055
+	0x3c, 0x25, 0x34, 0x52, 0x3f, 0x26, 0xea, 0x9a, 0x0d, 0xaf, 0x01, 0x79, 0x2a, 0x67, 0x0e, 0x94,
2056
+	0x87, 0xc3, 0x43, 0x64, 0x7e, 0x92, 0x16, 0x12, 0x83, 0x70, 0x2b, 0x71, 0xfa, 0x50, 0x8d, 0xb7,
2057
+	0xc1, 0x5b, 0xd9, 0xef, 0xda, 0xfb, 0x9a, 0xef, 0x77, 0xd9, 0x1d, 0xa8, 0x44, 0xa7, 0xae, 0xf2,
2058
+	0x83, 0x09, 0xf9, 0x6e, 0x7d, 0xff, 0xa3, 0xc4, 0xaa, 0xa1, 0xc1, 0x51, 0x53, 0xcc, 0x71, 0x24,
2059
+	0xd4, 0x12, 0x33, 0xde, 0xd0, 0xd5, 0x80, 0xc2, 0xdc, 0x1f, 0x91, 0x9e, 0x35, 0x8e, 0x43, 0x44,
2060
+	0x26, 0xbe, 0xc9, 0xa5, 0x35, 0x8e, 0x43, 0x0c, 0xc8, 0x4c, 0x8e, 0x4c, 0xd9, 0x5b, 0xe3, 0x34,
2061
+	0x46, 0x1f, 0xcb, 0x50, 0xfb, 0x32, 0x70, 0xa7, 0xb1, 0x8f, 0xe3, 0xb9, 0x33, 0x8d, 0xcf, 0xf7,
2062
+	0x3f, 0xd9, 0xed, 0x37, 0x39, 0xa8, 0xc6, 0xb5, 0x1a, 0x0b, 0x8f, 0x3f, 0x12, 0x81, 0xf6, 0xc7,
2063
+	0xbe, 0x50, 0x76, 0xe3, 0x0c, 0xc2, 0xee, 0x40, 0xc9, 0xd5, 0x5a, 0xc5, 0xd7, 0xf9, 0xff, 0xb3,
2064
+	0x85, 0xbe, 0x75, 0x80, 0x92, 0x5e, 0xa0, 0xd5, 0x82, 0x1b, 0xd6, 0xc6, 0x57, 0x00, 0x29, 0x88,
2065
+	0xb6, 0x9e, 0x89, 0x85, 0xd5, 0x8a, 0x43, 0x76, 0x15, 0x4a, 0xcf, 0xdd, 0xe9, 0x5c, 0xd8, 0x1c,
2066
+	0x36, 0x93, 0xaf, 0xf3, 0x5f, 0xe5, 0x9c, 0xbf, 0xe4, 0xa1, 0x62, 0x0b, 0x3f, 0xbb, 0x0d, 0x15,
2067
+	0x2a, 0xfc, 0xd6, 0xa2, 0xcb, 0x2f, 0x46, 0x4c, 0x61, 0x7b, 0xc9, 0x17, 0x2d, 0x63, 0xa3, 0x55,
2068
+	0x65, 0xbe, 0x6c, 0xd6, 0xc6, 0xf4, 0xfb, 0x56, 0x18, 0x89, 0xb1, 0xfd, 0x74, 0xad, 0x23, 0xbb,
2069
+	0x2b, 0xc6, 0x7e, 0xe0, 0xa3, 0x7f, 0x38, 0x8a, 0xd8, 0xed, 0xf8, 0xd4, 0x45, 0xd2, 0xf8, 0x49,
2070
+	0x56, 0xe3, 0x9b, 0x87, 0xee, 0x43, 0x3d, 0xb3, 0xcd, 0x25, 0xa7, 0xbe, 0x91, 0x3d, 0xb5, 0xdd,
2071
+	0x92, 0xd4, 0x99, 0xef, 0x6e, 0xea, 0x85, 0xff, 0xc0, 0x7f, 0x5f, 0x02, 0xa4, 0x2a, 0xdf, 0xbf,
2072
+	0xb0, 0x38, 0x2f, 0x0b, 0x00, 0x83, 0x10, 0x4b, 0xe7, 0xc8, 0xa5, 0xfa, 0xbd, 0xea, 0x4f, 0x02,
2073
+	0xa9, 0xc4, 0x33, 0xba, 0xaa, 0xb4, 0xbe, 0xca, 0xeb, 0x06, 0xa3, 0x1b, 0xc3, 0x0e, 0xa0, 0x3e,
2074
+	0x12, 0x91, 0xa7, 0x7c, 0x4a, 0x28, 0xeb, 0xf4, 0x2d, 0x3c, 0x53, 0xaa, 0xa7, 0xd5, 0x4d, 0x19,
2075
+	0xc6, 0x57, 0xd9, 0x35, 0x6c, 0x1f, 0x56, 0xc5, 0x79, 0x28, 0x95, 0xb6, 0xbb, 0x98, 0xfe, 0xe0,
2076
+	0x8a, 0xe9, 0x34, 0x10, 0xa7, 0x9d, 0x78, 0x5d, 0xa4, 0x13, 0xe6, 0x42, 0xd1, 0x73, 0x43, 0xf3,
2077
+	0x71, 0xac, 0xef, 0x37, 0x2f, 0xec, 0xd7, 0x71, 0x43, 0xe3, 0xb4, 0xf6, 0x17, 0x78, 0xd6, 0x97,
2078
+	0xff, 0xd8, 0xba, 0x95, 0xf9, 0x22, 0xce, 0xe4, 0xc9, 0x62, 0x8f, 0xf2, 0xe5, 0xcc, 0xd7, 0x7b,
2079
+	0x73, 0xed, 0x4f, 0xf7, 0xdc, 0xd0, 0x47, 0x75, 0xb8, 0xb0, 0xdf, 0xe5, 0xa4, 0x7a, 0xe3, 0x17,
2080
+	0xd0, 0xb8, 0x68, 0xf7, 0x87, 0xc4, 0x60, 0xe3, 0x2e, 0xd4, 0x12, 0x3b, 0xde, 0xb5, 0xb0, 0x9a,
2081
+	0x0d, 0xde, 0x9f, 0x73, 0x50, 0x36, 0xb7, 0x8a, 0xdd, 0x85, 0xda, 0x54, 0x7a, 0x2e, 0x1a, 0x10,
2082
+	0xb7, 0x68, 0x9f, 0xa6, 0x97, 0xae, 0xf5, 0x20, 0x96, 0x19, 0xaf, 0xa6, 0x5c, 0x4c, 0x32, 0x3f,
2083
+	0x18, 0xcb, 0xf8, 0x16, 0xac, 0xa7, 0x8b, 0xfa, 0xc1, 0x58, 0x72, 0x23, 0xdc, 0xb8, 0x0f, 0xeb,
2084
+	0xcb, 0x2a, 0x2e, 0xb1, 0xf3, 0xfa, 0x72, 0xba, 0x52, 0x5d, 0x4e, 0x16, 0x65, 0xcd, 0xbe, 0x0b,
2085
+	0xb5, 0x04, 0x67, 0xbb, 0x6f, 0x1a, 0xbe, 0x9a, 0x5d, 0x99, 0xb1, 0xd5, 0x99, 0x02, 0xa4, 0xa6,
2086
+	0x61, 0xb1, 0xc2, 0x5e, 0x30, 0x70, 0x67, 0x71, 0x93, 0x95, 0xcc, 0xe9, 0xdb, 0xe6, 0x6a, 0x97,
2087
+	0x4c, 0x59, 0xe5, 0x34, 0x66, 0x2d, 0x80, 0x51, 0x72, 0x61, 0xdf, 0x72, 0x8d, 0x33, 0x0c, 0x67,
2088
+	0x00, 0xd5, 0xd8, 0x08, 0xb6, 0x0d, 0xf5, 0xc8, 0xee, 0x8c, 0x9d, 0x0f, 0x6e, 0x57, 0xe2, 0x59,
2089
+	0x08, 0x3b, 0x18, 0xe5, 0x06, 0x13, 0xb1, 0xd4, 0xc1, 0x70, 0x44, 0xb8, 0x15, 0x38, 0x4f, 0xa1,
2090
+	0x44, 0x00, 0x5e, 0xb3, 0x48, 0xbb, 0x4a, 0xdb, 0x66, 0xc8, 0x34, 0x07, 0x32, 0xa2, 0x6d, 0xdb,
2091
+	0x45, 0x4c, 0x44, 0x6e, 0x08, 0xec, 0x06, 0xb6, 0x20, 0x23, 0xeb, 0xd1, 0xcb, 0x78, 0x28, 0x76,
2092
+	0x7e, 0x0e, 0xd5, 0x18, 0xc6, 0x93, 0x3f, 0xf0, 0x03, 0x61, 0x4d, 0xa4, 0x31, 0x36, 0x91, 0x9d,
2093
+	0x53, 0x57, 0xb9, 0x9e, 0x16, 0xa6, 0x0d, 0x28, 0xf1, 0x14, 0x70, 0xae, 0x43, 0x3d, 0x73, 0x7b,
2094
+	0x30, 0xdd, 0x9e, 0x50, 0x18, 0xcd, 0x1d, 0x36, 0x13, 0xe7, 0x25, 0xb6, 0xb8, 0x71, 0xd7, 0xf2,
2095
+	0x53, 0x80, 0x53, 0xad, 0xc3, 0x67, 0xd4, 0xc6, 0x58, 0xdf, 0xd7, 0x10, 0x21, 0x06, 0xdb, 0x82,
2096
+	0x3a, 0x4e, 0x22, 0x2b, 0x37, 0xf9, 0x4e, 0x2b, 0x22, 0x43, 0xf8, 0x09, 0xd4, 0xc6, 0xc9, 0xf2,
2097
+	0x82, 0x0d, 0x5d, 0xbc, 0xfa, 0x53, 0xa8, 0x06, 0xd2, 0xca, 0x4c, 0x57, 0x55, 0x09, 0x24, 0x89,
2098
+	0x9c, 0x5b, 0xf0, 0x7f, 0x6f, 0xf4, 0xe3, 0xec, 0x13, 0x28, 0x8f, 0xfd, 0xa9, 0xa6, 0xa2, 0x8f,
2099
+	0x8d, 0x9a, 0x9d, 0x39, 0xff, 0xca, 0x01, 0xa4, 0x91, 0xc5, 0x7c, 0xc5, 0xea, 0x8d, 0x9c, 0x55,
2100
+	0x53, 0xad, 0xa7, 0x50, 0x9d, 0xd9, 0x3a, 0x60, 0x63, 0x76, 0x6d, 0x39, 0x1b, 0x5a, 0x71, 0x99,
2101
+	0x30, 0x15, 0x62, 0xdf, 0x56, 0x88, 0x0f, 0xe9, 0x99, 0x93, 0x1d, 0xa8, 0x19, 0xc9, 0xbe, 0x7d,
2102
+	0x20, 0xbd, 0x68, 0xdc, 0x4a, 0x36, 0xee, 0xc3, 0xda, 0xd2, 0x96, 0xef, 0xf9, 0x4d, 0x48, 0xeb,
2103
+	0x59, 0xf6, 0x96, 0xdd, 0x86, 0xb2, 0x69, 0x22, 0x31, 0x25, 0x70, 0x64, 0xd5, 0xd0, 0x98, 0x3a,
2104
+	0x86, 0xe3, 0xf8, 0x05, 0xd2, 0x3f, 0x76, 0xf6, 0xa1, 0x6c, 0x9e, 0x58, 0x6c, 0x07, 0x2a, 0xae,
2105
+	0x67, 0xae, 0x63, 0xa6, 0x24, 0xa0, 0xf0, 0x80, 0x60, 0x1e, 0x8b, 0x9d, 0xbf, 0xe5, 0x01, 0x52,
2106
+	0xfc, 0x03, 0xba, 0xd2, 0xaf, 0x61, 0x3d, 0x12, 0x9e, 0x0c, 0x46, 0xae, 0x5a, 0x90, 0xd4, 0x3e,
2107
+	0x25, 0x2e, 0x5b, 0x72, 0x81, 0x99, 0xe9, 0x50, 0x0b, 0xef, 0xee, 0x50, 0x77, 0xa0, 0xe8, 0xc9,
2108
+	0x70, 0x61, 0x3f, 0x14, 0x6c, 0xf9, 0x20, 0x1d, 0x19, 0x2e, 0xf0, 0x41, 0x89, 0x0c, 0xd6, 0x82,
2109
+	0xf2, 0xec, 0x8c, 0x1e, 0x9d, 0xa6, 0x61, 0xbf, 0xba, 0xcc, 0x7d, 0x78, 0x86, 0x63, 0x7c, 0xa2,
2110
+	0x1a, 0x16, 0xbb, 0x05, 0xa5, 0xd9, 0xd9, 0xc8, 0x57, 0xd4, 0xdb, 0xd6, 0x4d, 0x67, 0x98, 0xa5,
2111
+	0x77, 0x7d, 0x85, 0x0f, 0x51, 0xe2, 0x30, 0x07, 0xf2, 0x6a, 0xd6, 0xac, 0x10, 0xb3, 0x71, 0xc1,
2112
+	0x9b, 0xb3, 0xc3, 0x15, 0x9e, 0x57, 0xb3, 0x76, 0x15, 0xca, 0xc6, 0xaf, 0xce, 0x1f, 0x0b, 0xb0,
2113
+	0xbe, 0x6c, 0x25, 0xe6, 0x41, 0xa4, 0xbc, 0x38, 0x0f, 0x22, 0xe5, 0x25, 0xcd, 0x7b, 0x3e, 0xd3,
2114
+	0xbc, 0x3b, 0x50, 0x92, 0x2f, 0x02, 0xa1, 0xb2, 0xaf, 0xeb, 0xce, 0xa9, 0x7c, 0x11, 0x60, 0x9b,
2115
+	0x6a, 0x44, 0x4b, 0x5d, 0x5f, 0xc9, 0x76, 0x7d, 0x37, 0x60, 0x6d, 0x2c, 0xa7, 0x53, 0xf9, 0x62,
2116
+	0xb8, 0x98, 0x4d, 0xfd, 0xe0, 0xcc, 0xb6, 0x7e, 0xcb, 0x20, 0xdb, 0x81, 0x2b, 0x23, 0x5f, 0xa1,
2117
+	0x39, 0x1d, 0x19, 0x68, 0x11, 0xd0, 0x7b, 0x05, 0x79, 0x17, 0x61, 0xf6, 0x0d, 0x6c, 0xbb, 0x5a,
2118
+	0x8b, 0x59, 0xa8, 0x1f, 0x07, 0xa1, 0xeb, 0x9d, 0x75, 0xa5, 0x47, 0x77, 0x76, 0x16, 0xba, 0xda,
2119
+	0x3f, 0xf1, 0xa7, 0xf8, 0x34, 0xab, 0xd0, 0xd2, 0x77, 0xf2, 0xd8, 0xe7, 0xb0, 0xee, 0x29, 0xe1,
2120
+	0x6a, 0xd1, 0x15, 0x91, 0x3e, 0x76, 0xf5, 0x69, 0xb3, 0x4a, 0x2b, 0x2f, 0xa0, 0x78, 0x06, 0x17,
2121
+	0xad, 0x7d, 0xea, 0x4f, 0x47, 0x9e, 0xab, 0x46, 0xcd, 0x9a, 0x39, 0xc3, 0x12, 0xc8, 0x5a, 0xc0,
2122
+	0x08, 0xe8, 0xcd, 0x42, 0xbd, 0x48, 0xa8, 0x40, 0xd4, 0x4b, 0x24, 0x58, 0x38, 0xb5, 0x3f, 0x13,
2123
+	0x91, 0x76, 0x67, 0x21, 0xfd, 0x2b, 0x50, 0xe0, 0x29, 0xe0, 0x7c, 0x9b, 0x83, 0xc6, 0xc5, 0x14,
2124
+	0x41, 0x07, 0x87, 0x68, 0xa6, 0xbd, 0x6c, 0x38, 0x4e, 0x9c, 0x9e, 0xcf, 0x38, 0x3d, 0xfe, 0x42,
2125
+	0x15, 0x32, 0x5f, 0xa8, 0x24, 0x80, 0xc5, 0xb7, 0x07, 0x70, 0xc9, 0xa4, 0xd2, 0x45, 0x93, 0x7e,
2126
+	0x97, 0x83, 0x2b, 0x17, 0xd2, 0xf0, 0xbd, 0x2d, 0xda, 0x86, 0xfa, 0xcc, 0x3d, 0x13, 0xc7, 0xae,
2127
+	0xa2, 0xe0, 0x16, 0x4c, 0x0b, 0x97, 0x81, 0xfe, 0x0b, 0xf6, 0x05, 0xb0, 0x9a, 0xcd, 0xfd, 0x4b,
2128
+	0x6d, 0x8b, 0x43, 0x79, 0x24, 0xf5, 0x3d, 0x39, 0xb7, 0x5f, 0xbf, 0x38, 0x94, 0x31, 0xf8, 0x66,
2129
+	0xc0, 0x0b, 0x97, 0x04, 0xdc, 0x39, 0x82, 0x6a, 0x6c, 0x20, 0xdb, 0xb2, 0x4f, 0xf5, 0x5c, 0xfa,
2130
+	0x97, 0xd1, 0xe3, 0x48, 0x28, 0xb4, 0xdd, 0xbc, 0xdb, 0x3f, 0x83, 0xd2, 0x44, 0xc9, 0x79, 0x68,
2131
+	0x6b, 0xeb, 0x12, 0xc3, 0x48, 0x9c, 0x21, 0x54, 0x2c, 0xc2, 0x76, 0xa1, 0x7c, 0xb2, 0x38, 0x8a,
2132
+	0x9b, 0x0f, 0x7b, 0xb1, 0x71, 0x3e, 0xb2, 0x0c, 0xac, 0x16, 0x86, 0xc1, 0xae, 0x42, 0xf1, 0x64,
2133
+	0xd1, 0xef, 0x9a, 0x07, 0x19, 0xd6, 0x1c, 0x9c, 0xb5, 0xcb, 0xc6, 0x20, 0xe7, 0x01, 0xac, 0x66,
2134
+	0xd7, 0xa1, 0x53, 0x32, 0x4d, 0x0d, 0x8d, 0xd3, 0xe2, 0x9a, 0x7f, 0x47, 0x71, 0xdd, 0xdd, 0x81,
2135
+	0x8a, 0xfd, 0x53, 0x84, 0xd5, 0xa0, 0xf4, 0xf8, 0x68, 0xd8, 0x7b, 0xd4, 0x58, 0x61, 0x55, 0x28,
2136
+	0x1e, 0x0e, 0x86, 0x8f, 0x1a, 0x39, 0x1c, 0x1d, 0x0d, 0x8e, 0x7a, 0x8d, 0xfc, 0xee, 0x4d, 0x58,
2137
+	0xcd, 0xfe, 0x2d, 0xc2, 0xea, 0x50, 0x19, 0x1e, 0x1c, 0x75, 0xdb, 0x83, 0x5f, 0x35, 0x56, 0xd8,
2138
+	0x2a, 0x54, 0xfb, 0x47, 0xc3, 0x5e, 0xe7, 0x31, 0xef, 0x35, 0x72, 0xbb, 0xbf, 0x84, 0x5a, 0xf2,
2139
+	0x72, 0x47, 0x0d, 0xed, 0xfe, 0x51, 0xb7, 0xb1, 0xc2, 0x00, 0xca, 0xc3, 0x5e, 0x87, 0xf7, 0x50,
2140
+	0x6f, 0x05, 0x0a, 0xc3, 0xe1, 0x61, 0x23, 0x8f, 0xbb, 0x76, 0x0e, 0x3a, 0x87, 0xbd, 0x46, 0x01,
2141
+	0x87, 0x8f, 0x1e, 0x1e, 0xdf, 0x1b, 0x36, 0x8a, 0xbb, 0x5f, 0xc2, 0x95, 0x0b, 0x2f, 0x67, 0x5a,
2142
+	0x7d, 0x78, 0xc0, 0x7b, 0xa8, 0xa9, 0x0e, 0x95, 0x63, 0xde, 0x7f, 0x72, 0xf0, 0xa8, 0xd7, 0xc8,
2143
+	0xa1, 0xe0, 0xc1, 0xa0, 0x73, 0xbf, 0xd7, 0x6d, 0xe4, 0xdb, 0xd7, 0xbe, 0x7b, 0xb5, 0x99, 0xfb,
2144
+	0xfe, 0xd5, 0x66, 0xee, 0x87, 0x57, 0x9b, 0xb9, 0x7f, 0xbe, 0xda, 0xcc, 0x7d, 0xfb, 0x7a, 0x73,
2145
+	0xe5, 0xfb, 0xd7, 0x9b, 0x2b, 0x3f, 0xbc, 0xde, 0x5c, 0x39, 0x29, 0xd3, 0x9f, 0x94, 0x5f, 0xfc,
2146
+	0x3b, 0x00, 0x00, 0xff, 0xff, 0x7e, 0x60, 0x46, 0x7d, 0xe4, 0x14, 0x00, 0x00,
2134 2147
 }
2135 2148
 
2136 2149
 func (m *Op) Marshal() (dAtA []byte, err error) {
... ...
@@ -3044,6 +3367,278 @@ func (m *OpMetadata) MarshalToSizedBuffer(dAtA []byte) (int, error) {
3044 3044
 	return len(dAtA) - i, nil
3045 3045
 }
3046 3046
 
3047
+func (m *Source) Marshal() (dAtA []byte, err error) {
3048
+	size := m.Size()
3049
+	dAtA = make([]byte, size)
3050
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
3051
+	if err != nil {
3052
+		return nil, err
3053
+	}
3054
+	return dAtA[:n], nil
3055
+}
3056
+
3057
+func (m *Source) MarshalTo(dAtA []byte) (int, error) {
3058
+	size := m.Size()
3059
+	return m.MarshalToSizedBuffer(dAtA[:size])
3060
+}
3061
+
3062
+func (m *Source) MarshalToSizedBuffer(dAtA []byte) (int, error) {
3063
+	i := len(dAtA)
3064
+	_ = i
3065
+	var l int
3066
+	_ = l
3067
+	if len(m.Infos) > 0 {
3068
+		for iNdEx := len(m.Infos) - 1; iNdEx >= 0; iNdEx-- {
3069
+			{
3070
+				size, err := m.Infos[iNdEx].MarshalToSizedBuffer(dAtA[:i])
3071
+				if err != nil {
3072
+					return 0, err
3073
+				}
3074
+				i -= size
3075
+				i = encodeVarintOps(dAtA, i, uint64(size))
3076
+			}
3077
+			i--
3078
+			dAtA[i] = 0x12
3079
+		}
3080
+	}
3081
+	if len(m.Locations) > 0 {
3082
+		keysForLocations := make([]string, 0, len(m.Locations))
3083
+		for k := range m.Locations {
3084
+			keysForLocations = append(keysForLocations, string(k))
3085
+		}
3086
+		github_com_gogo_protobuf_sortkeys.Strings(keysForLocations)
3087
+		for iNdEx := len(keysForLocations) - 1; iNdEx >= 0; iNdEx-- {
3088
+			v := m.Locations[string(keysForLocations[iNdEx])]
3089
+			baseI := i
3090
+			if v != nil {
3091
+				{
3092
+					size, err := v.MarshalToSizedBuffer(dAtA[:i])
3093
+					if err != nil {
3094
+						return 0, err
3095
+					}
3096
+					i -= size
3097
+					i = encodeVarintOps(dAtA, i, uint64(size))
3098
+				}
3099
+				i--
3100
+				dAtA[i] = 0x12
3101
+			}
3102
+			i -= len(keysForLocations[iNdEx])
3103
+			copy(dAtA[i:], keysForLocations[iNdEx])
3104
+			i = encodeVarintOps(dAtA, i, uint64(len(keysForLocations[iNdEx])))
3105
+			i--
3106
+			dAtA[i] = 0xa
3107
+			i = encodeVarintOps(dAtA, i, uint64(baseI-i))
3108
+			i--
3109
+			dAtA[i] = 0xa
3110
+		}
3111
+	}
3112
+	return len(dAtA) - i, nil
3113
+}
3114
+
3115
+func (m *Locations) Marshal() (dAtA []byte, err error) {
3116
+	size := m.Size()
3117
+	dAtA = make([]byte, size)
3118
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
3119
+	if err != nil {
3120
+		return nil, err
3121
+	}
3122
+	return dAtA[:n], nil
3123
+}
3124
+
3125
+func (m *Locations) MarshalTo(dAtA []byte) (int, error) {
3126
+	size := m.Size()
3127
+	return m.MarshalToSizedBuffer(dAtA[:size])
3128
+}
3129
+
3130
+func (m *Locations) MarshalToSizedBuffer(dAtA []byte) (int, error) {
3131
+	i := len(dAtA)
3132
+	_ = i
3133
+	var l int
3134
+	_ = l
3135
+	if len(m.Locations) > 0 {
3136
+		for iNdEx := len(m.Locations) - 1; iNdEx >= 0; iNdEx-- {
3137
+			{
3138
+				size, err := m.Locations[iNdEx].MarshalToSizedBuffer(dAtA[:i])
3139
+				if err != nil {
3140
+					return 0, err
3141
+				}
3142
+				i -= size
3143
+				i = encodeVarintOps(dAtA, i, uint64(size))
3144
+			}
3145
+			i--
3146
+			dAtA[i] = 0xa
3147
+		}
3148
+	}
3149
+	return len(dAtA) - i, nil
3150
+}
3151
+
3152
+func (m *SourceInfo) Marshal() (dAtA []byte, err error) {
3153
+	size := m.Size()
3154
+	dAtA = make([]byte, size)
3155
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
3156
+	if err != nil {
3157
+		return nil, err
3158
+	}
3159
+	return dAtA[:n], nil
3160
+}
3161
+
3162
+func (m *SourceInfo) MarshalTo(dAtA []byte) (int, error) {
3163
+	size := m.Size()
3164
+	return m.MarshalToSizedBuffer(dAtA[:size])
3165
+}
3166
+
3167
+func (m *SourceInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
3168
+	i := len(dAtA)
3169
+	_ = i
3170
+	var l int
3171
+	_ = l
3172
+	if m.Definition != nil {
3173
+		{
3174
+			size, err := m.Definition.MarshalToSizedBuffer(dAtA[:i])
3175
+			if err != nil {
3176
+				return 0, err
3177
+			}
3178
+			i -= size
3179
+			i = encodeVarintOps(dAtA, i, uint64(size))
3180
+		}
3181
+		i--
3182
+		dAtA[i] = 0x1a
3183
+	}
3184
+	if len(m.Data) > 0 {
3185
+		i -= len(m.Data)
3186
+		copy(dAtA[i:], m.Data)
3187
+		i = encodeVarintOps(dAtA, i, uint64(len(m.Data)))
3188
+		i--
3189
+		dAtA[i] = 0x12
3190
+	}
3191
+	if len(m.Filename) > 0 {
3192
+		i -= len(m.Filename)
3193
+		copy(dAtA[i:], m.Filename)
3194
+		i = encodeVarintOps(dAtA, i, uint64(len(m.Filename)))
3195
+		i--
3196
+		dAtA[i] = 0xa
3197
+	}
3198
+	return len(dAtA) - i, nil
3199
+}
3200
+
3201
+func (m *Location) Marshal() (dAtA []byte, err error) {
3202
+	size := m.Size()
3203
+	dAtA = make([]byte, size)
3204
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
3205
+	if err != nil {
3206
+		return nil, err
3207
+	}
3208
+	return dAtA[:n], nil
3209
+}
3210
+
3211
+func (m *Location) MarshalTo(dAtA []byte) (int, error) {
3212
+	size := m.Size()
3213
+	return m.MarshalToSizedBuffer(dAtA[:size])
3214
+}
3215
+
3216
+func (m *Location) MarshalToSizedBuffer(dAtA []byte) (int, error) {
3217
+	i := len(dAtA)
3218
+	_ = i
3219
+	var l int
3220
+	_ = l
3221
+	if len(m.Ranges) > 0 {
3222
+		for iNdEx := len(m.Ranges) - 1; iNdEx >= 0; iNdEx-- {
3223
+			{
3224
+				size, err := m.Ranges[iNdEx].MarshalToSizedBuffer(dAtA[:i])
3225
+				if err != nil {
3226
+					return 0, err
3227
+				}
3228
+				i -= size
3229
+				i = encodeVarintOps(dAtA, i, uint64(size))
3230
+			}
3231
+			i--
3232
+			dAtA[i] = 0x12
3233
+		}
3234
+	}
3235
+	if m.SourceIndex != 0 {
3236
+		i = encodeVarintOps(dAtA, i, uint64(m.SourceIndex))
3237
+		i--
3238
+		dAtA[i] = 0x8
3239
+	}
3240
+	return len(dAtA) - i, nil
3241
+}
3242
+
3243
+func (m *Range) Marshal() (dAtA []byte, err error) {
3244
+	size := m.Size()
3245
+	dAtA = make([]byte, size)
3246
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
3247
+	if err != nil {
3248
+		return nil, err
3249
+	}
3250
+	return dAtA[:n], nil
3251
+}
3252
+
3253
+func (m *Range) MarshalTo(dAtA []byte) (int, error) {
3254
+	size := m.Size()
3255
+	return m.MarshalToSizedBuffer(dAtA[:size])
3256
+}
3257
+
3258
+func (m *Range) MarshalToSizedBuffer(dAtA []byte) (int, error) {
3259
+	i := len(dAtA)
3260
+	_ = i
3261
+	var l int
3262
+	_ = l
3263
+	{
3264
+		size, err := m.End.MarshalToSizedBuffer(dAtA[:i])
3265
+		if err != nil {
3266
+			return 0, err
3267
+		}
3268
+		i -= size
3269
+		i = encodeVarintOps(dAtA, i, uint64(size))
3270
+	}
3271
+	i--
3272
+	dAtA[i] = 0x12
3273
+	{
3274
+		size, err := m.Start.MarshalToSizedBuffer(dAtA[:i])
3275
+		if err != nil {
3276
+			return 0, err
3277
+		}
3278
+		i -= size
3279
+		i = encodeVarintOps(dAtA, i, uint64(size))
3280
+	}
3281
+	i--
3282
+	dAtA[i] = 0xa
3283
+	return len(dAtA) - i, nil
3284
+}
3285
+
3286
+func (m *Position) Marshal() (dAtA []byte, err error) {
3287
+	size := m.Size()
3288
+	dAtA = make([]byte, size)
3289
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
3290
+	if err != nil {
3291
+		return nil, err
3292
+	}
3293
+	return dAtA[:n], nil
3294
+}
3295
+
3296
+func (m *Position) MarshalTo(dAtA []byte) (int, error) {
3297
+	size := m.Size()
3298
+	return m.MarshalToSizedBuffer(dAtA[:size])
3299
+}
3300
+
3301
+func (m *Position) MarshalToSizedBuffer(dAtA []byte) (int, error) {
3302
+	i := len(dAtA)
3303
+	_ = i
3304
+	var l int
3305
+	_ = l
3306
+	if m.Character != 0 {
3307
+		i = encodeVarintOps(dAtA, i, uint64(m.Character))
3308
+		i--
3309
+		dAtA[i] = 0x10
3310
+	}
3311
+	if m.Line != 0 {
3312
+		i = encodeVarintOps(dAtA, i, uint64(m.Line))
3313
+		i--
3314
+		dAtA[i] = 0x8
3315
+	}
3316
+	return len(dAtA) - i, nil
3317
+}
3318
+
3047 3319
 func (m *ExportCache) Marshal() (dAtA []byte, err error) {
3048 3320
 	size := m.Size()
3049 3321
 	dAtA = make([]byte, size)
... ...
@@ -3180,6 +3775,18 @@ func (m *Definition) MarshalToSizedBuffer(dAtA []byte) (int, error) {
3180 3180
 	_ = i
3181 3181
 	var l int
3182 3182
 	_ = l
3183
+	if m.Source != nil {
3184
+		{
3185
+			size, err := m.Source.MarshalToSizedBuffer(dAtA[:i])
3186
+			if err != nil {
3187
+				return 0, err
3188
+			}
3189
+			i -= size
3190
+			i = encodeVarintOps(dAtA, i, uint64(size))
3191
+		}
3192
+		i--
3193
+		dAtA[i] = 0x1a
3194
+	}
3183 3195
 	if len(m.Metadata) > 0 {
3184 3196
 		keysForMetadata := make([]string, 0, len(m.Metadata))
3185 3197
 		for k := range m.Metadata {
... ...
@@ -4268,6 +4875,116 @@ func (m *OpMetadata) Size() (n int) {
4268 4268
 	return n
4269 4269
 }
4270 4270
 
4271
+func (m *Source) Size() (n int) {
4272
+	if m == nil {
4273
+		return 0
4274
+	}
4275
+	var l int
4276
+	_ = l
4277
+	if len(m.Locations) > 0 {
4278
+		for k, v := range m.Locations {
4279
+			_ = k
4280
+			_ = v
4281
+			l = 0
4282
+			if v != nil {
4283
+				l = v.Size()
4284
+				l += 1 + sovOps(uint64(l))
4285
+			}
4286
+			mapEntrySize := 1 + len(k) + sovOps(uint64(len(k))) + l
4287
+			n += mapEntrySize + 1 + sovOps(uint64(mapEntrySize))
4288
+		}
4289
+	}
4290
+	if len(m.Infos) > 0 {
4291
+		for _, e := range m.Infos {
4292
+			l = e.Size()
4293
+			n += 1 + l + sovOps(uint64(l))
4294
+		}
4295
+	}
4296
+	return n
4297
+}
4298
+
4299
+func (m *Locations) Size() (n int) {
4300
+	if m == nil {
4301
+		return 0
4302
+	}
4303
+	var l int
4304
+	_ = l
4305
+	if len(m.Locations) > 0 {
4306
+		for _, e := range m.Locations {
4307
+			l = e.Size()
4308
+			n += 1 + l + sovOps(uint64(l))
4309
+		}
4310
+	}
4311
+	return n
4312
+}
4313
+
4314
+func (m *SourceInfo) Size() (n int) {
4315
+	if m == nil {
4316
+		return 0
4317
+	}
4318
+	var l int
4319
+	_ = l
4320
+	l = len(m.Filename)
4321
+	if l > 0 {
4322
+		n += 1 + l + sovOps(uint64(l))
4323
+	}
4324
+	l = len(m.Data)
4325
+	if l > 0 {
4326
+		n += 1 + l + sovOps(uint64(l))
4327
+	}
4328
+	if m.Definition != nil {
4329
+		l = m.Definition.Size()
4330
+		n += 1 + l + sovOps(uint64(l))
4331
+	}
4332
+	return n
4333
+}
4334
+
4335
+func (m *Location) Size() (n int) {
4336
+	if m == nil {
4337
+		return 0
4338
+	}
4339
+	var l int
4340
+	_ = l
4341
+	if m.SourceIndex != 0 {
4342
+		n += 1 + sovOps(uint64(m.SourceIndex))
4343
+	}
4344
+	if len(m.Ranges) > 0 {
4345
+		for _, e := range m.Ranges {
4346
+			l = e.Size()
4347
+			n += 1 + l + sovOps(uint64(l))
4348
+		}
4349
+	}
4350
+	return n
4351
+}
4352
+
4353
+func (m *Range) Size() (n int) {
4354
+	if m == nil {
4355
+		return 0
4356
+	}
4357
+	var l int
4358
+	_ = l
4359
+	l = m.Start.Size()
4360
+	n += 1 + l + sovOps(uint64(l))
4361
+	l = m.End.Size()
4362
+	n += 1 + l + sovOps(uint64(l))
4363
+	return n
4364
+}
4365
+
4366
+func (m *Position) Size() (n int) {
4367
+	if m == nil {
4368
+		return 0
4369
+	}
4370
+	var l int
4371
+	_ = l
4372
+	if m.Line != 0 {
4373
+		n += 1 + sovOps(uint64(m.Line))
4374
+	}
4375
+	if m.Character != 0 {
4376
+		n += 1 + sovOps(uint64(m.Character))
4377
+	}
4378
+	return n
4379
+}
4380
+
4271 4381
 func (m *ExportCache) Size() (n int) {
4272 4382
 	if m == nil {
4273 4383
 		return 0
... ...
@@ -4341,6 +5058,10 @@ func (m *Definition) Size() (n int) {
4341 4341
 			n += mapEntrySize + 1 + sovOps(uint64(mapEntrySize))
4342 4342
 		}
4343 4343
 	}
4344
+	if m.Source != nil {
4345
+		l = m.Source.Size()
4346
+		n += 1 + l + sovOps(uint64(l))
4347
+	}
4344 4348
 	return n
4345 4349
 }
4346 4350
 
... ...
@@ -7391,6 +8112,780 @@ func (m *OpMetadata) Unmarshal(dAtA []byte) error {
7391 7391
 	}
7392 7392
 	return nil
7393 7393
 }
7394
+func (m *Source) Unmarshal(dAtA []byte) error {
7395
+	l := len(dAtA)
7396
+	iNdEx := 0
7397
+	for iNdEx < l {
7398
+		preIndex := iNdEx
7399
+		var wire uint64
7400
+		for shift := uint(0); ; shift += 7 {
7401
+			if shift >= 64 {
7402
+				return ErrIntOverflowOps
7403
+			}
7404
+			if iNdEx >= l {
7405
+				return io.ErrUnexpectedEOF
7406
+			}
7407
+			b := dAtA[iNdEx]
7408
+			iNdEx++
7409
+			wire |= uint64(b&0x7F) << shift
7410
+			if b < 0x80 {
7411
+				break
7412
+			}
7413
+		}
7414
+		fieldNum := int32(wire >> 3)
7415
+		wireType := int(wire & 0x7)
7416
+		if wireType == 4 {
7417
+			return fmt.Errorf("proto: Source: wiretype end group for non-group")
7418
+		}
7419
+		if fieldNum <= 0 {
7420
+			return fmt.Errorf("proto: Source: illegal tag %d (wire type %d)", fieldNum, wire)
7421
+		}
7422
+		switch fieldNum {
7423
+		case 1:
7424
+			if wireType != 2 {
7425
+				return fmt.Errorf("proto: wrong wireType = %d for field Locations", wireType)
7426
+			}
7427
+			var msglen int
7428
+			for shift := uint(0); ; shift += 7 {
7429
+				if shift >= 64 {
7430
+					return ErrIntOverflowOps
7431
+				}
7432
+				if iNdEx >= l {
7433
+					return io.ErrUnexpectedEOF
7434
+				}
7435
+				b := dAtA[iNdEx]
7436
+				iNdEx++
7437
+				msglen |= int(b&0x7F) << shift
7438
+				if b < 0x80 {
7439
+					break
7440
+				}
7441
+			}
7442
+			if msglen < 0 {
7443
+				return ErrInvalidLengthOps
7444
+			}
7445
+			postIndex := iNdEx + msglen
7446
+			if postIndex < 0 {
7447
+				return ErrInvalidLengthOps
7448
+			}
7449
+			if postIndex > l {
7450
+				return io.ErrUnexpectedEOF
7451
+			}
7452
+			if m.Locations == nil {
7453
+				m.Locations = make(map[string]*Locations)
7454
+			}
7455
+			var mapkey string
7456
+			var mapvalue *Locations
7457
+			for iNdEx < postIndex {
7458
+				entryPreIndex := iNdEx
7459
+				var wire uint64
7460
+				for shift := uint(0); ; shift += 7 {
7461
+					if shift >= 64 {
7462
+						return ErrIntOverflowOps
7463
+					}
7464
+					if iNdEx >= l {
7465
+						return io.ErrUnexpectedEOF
7466
+					}
7467
+					b := dAtA[iNdEx]
7468
+					iNdEx++
7469
+					wire |= uint64(b&0x7F) << shift
7470
+					if b < 0x80 {
7471
+						break
7472
+					}
7473
+				}
7474
+				fieldNum := int32(wire >> 3)
7475
+				if fieldNum == 1 {
7476
+					var stringLenmapkey uint64
7477
+					for shift := uint(0); ; shift += 7 {
7478
+						if shift >= 64 {
7479
+							return ErrIntOverflowOps
7480
+						}
7481
+						if iNdEx >= l {
7482
+							return io.ErrUnexpectedEOF
7483
+						}
7484
+						b := dAtA[iNdEx]
7485
+						iNdEx++
7486
+						stringLenmapkey |= uint64(b&0x7F) << shift
7487
+						if b < 0x80 {
7488
+							break
7489
+						}
7490
+					}
7491
+					intStringLenmapkey := int(stringLenmapkey)
7492
+					if intStringLenmapkey < 0 {
7493
+						return ErrInvalidLengthOps
7494
+					}
7495
+					postStringIndexmapkey := iNdEx + intStringLenmapkey
7496
+					if postStringIndexmapkey < 0 {
7497
+						return ErrInvalidLengthOps
7498
+					}
7499
+					if postStringIndexmapkey > l {
7500
+						return io.ErrUnexpectedEOF
7501
+					}
7502
+					mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
7503
+					iNdEx = postStringIndexmapkey
7504
+				} else if fieldNum == 2 {
7505
+					var mapmsglen int
7506
+					for shift := uint(0); ; shift += 7 {
7507
+						if shift >= 64 {
7508
+							return ErrIntOverflowOps
7509
+						}
7510
+						if iNdEx >= l {
7511
+							return io.ErrUnexpectedEOF
7512
+						}
7513
+						b := dAtA[iNdEx]
7514
+						iNdEx++
7515
+						mapmsglen |= int(b&0x7F) << shift
7516
+						if b < 0x80 {
7517
+							break
7518
+						}
7519
+					}
7520
+					if mapmsglen < 0 {
7521
+						return ErrInvalidLengthOps
7522
+					}
7523
+					postmsgIndex := iNdEx + mapmsglen
7524
+					if postmsgIndex < 0 {
7525
+						return ErrInvalidLengthOps
7526
+					}
7527
+					if postmsgIndex > l {
7528
+						return io.ErrUnexpectedEOF
7529
+					}
7530
+					mapvalue = &Locations{}
7531
+					if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil {
7532
+						return err
7533
+					}
7534
+					iNdEx = postmsgIndex
7535
+				} else {
7536
+					iNdEx = entryPreIndex
7537
+					skippy, err := skipOps(dAtA[iNdEx:])
7538
+					if err != nil {
7539
+						return err
7540
+					}
7541
+					if skippy < 0 {
7542
+						return ErrInvalidLengthOps
7543
+					}
7544
+					if (iNdEx + skippy) > postIndex {
7545
+						return io.ErrUnexpectedEOF
7546
+					}
7547
+					iNdEx += skippy
7548
+				}
7549
+			}
7550
+			m.Locations[mapkey] = mapvalue
7551
+			iNdEx = postIndex
7552
+		case 2:
7553
+			if wireType != 2 {
7554
+				return fmt.Errorf("proto: wrong wireType = %d for field Infos", wireType)
7555
+			}
7556
+			var msglen int
7557
+			for shift := uint(0); ; shift += 7 {
7558
+				if shift >= 64 {
7559
+					return ErrIntOverflowOps
7560
+				}
7561
+				if iNdEx >= l {
7562
+					return io.ErrUnexpectedEOF
7563
+				}
7564
+				b := dAtA[iNdEx]
7565
+				iNdEx++
7566
+				msglen |= int(b&0x7F) << shift
7567
+				if b < 0x80 {
7568
+					break
7569
+				}
7570
+			}
7571
+			if msglen < 0 {
7572
+				return ErrInvalidLengthOps
7573
+			}
7574
+			postIndex := iNdEx + msglen
7575
+			if postIndex < 0 {
7576
+				return ErrInvalidLengthOps
7577
+			}
7578
+			if postIndex > l {
7579
+				return io.ErrUnexpectedEOF
7580
+			}
7581
+			m.Infos = append(m.Infos, &SourceInfo{})
7582
+			if err := m.Infos[len(m.Infos)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
7583
+				return err
7584
+			}
7585
+			iNdEx = postIndex
7586
+		default:
7587
+			iNdEx = preIndex
7588
+			skippy, err := skipOps(dAtA[iNdEx:])
7589
+			if err != nil {
7590
+				return err
7591
+			}
7592
+			if skippy < 0 {
7593
+				return ErrInvalidLengthOps
7594
+			}
7595
+			if (iNdEx + skippy) < 0 {
7596
+				return ErrInvalidLengthOps
7597
+			}
7598
+			if (iNdEx + skippy) > l {
7599
+				return io.ErrUnexpectedEOF
7600
+			}
7601
+			iNdEx += skippy
7602
+		}
7603
+	}
7604
+
7605
+	if iNdEx > l {
7606
+		return io.ErrUnexpectedEOF
7607
+	}
7608
+	return nil
7609
+}
7610
+func (m *Locations) Unmarshal(dAtA []byte) error {
7611
+	l := len(dAtA)
7612
+	iNdEx := 0
7613
+	for iNdEx < l {
7614
+		preIndex := iNdEx
7615
+		var wire uint64
7616
+		for shift := uint(0); ; shift += 7 {
7617
+			if shift >= 64 {
7618
+				return ErrIntOverflowOps
7619
+			}
7620
+			if iNdEx >= l {
7621
+				return io.ErrUnexpectedEOF
7622
+			}
7623
+			b := dAtA[iNdEx]
7624
+			iNdEx++
7625
+			wire |= uint64(b&0x7F) << shift
7626
+			if b < 0x80 {
7627
+				break
7628
+			}
7629
+		}
7630
+		fieldNum := int32(wire >> 3)
7631
+		wireType := int(wire & 0x7)
7632
+		if wireType == 4 {
7633
+			return fmt.Errorf("proto: Locations: wiretype end group for non-group")
7634
+		}
7635
+		if fieldNum <= 0 {
7636
+			return fmt.Errorf("proto: Locations: illegal tag %d (wire type %d)", fieldNum, wire)
7637
+		}
7638
+		switch fieldNum {
7639
+		case 1:
7640
+			if wireType != 2 {
7641
+				return fmt.Errorf("proto: wrong wireType = %d for field Locations", wireType)
7642
+			}
7643
+			var msglen int
7644
+			for shift := uint(0); ; shift += 7 {
7645
+				if shift >= 64 {
7646
+					return ErrIntOverflowOps
7647
+				}
7648
+				if iNdEx >= l {
7649
+					return io.ErrUnexpectedEOF
7650
+				}
7651
+				b := dAtA[iNdEx]
7652
+				iNdEx++
7653
+				msglen |= int(b&0x7F) << shift
7654
+				if b < 0x80 {
7655
+					break
7656
+				}
7657
+			}
7658
+			if msglen < 0 {
7659
+				return ErrInvalidLengthOps
7660
+			}
7661
+			postIndex := iNdEx + msglen
7662
+			if postIndex < 0 {
7663
+				return ErrInvalidLengthOps
7664
+			}
7665
+			if postIndex > l {
7666
+				return io.ErrUnexpectedEOF
7667
+			}
7668
+			m.Locations = append(m.Locations, &Location{})
7669
+			if err := m.Locations[len(m.Locations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
7670
+				return err
7671
+			}
7672
+			iNdEx = postIndex
7673
+		default:
7674
+			iNdEx = preIndex
7675
+			skippy, err := skipOps(dAtA[iNdEx:])
7676
+			if err != nil {
7677
+				return err
7678
+			}
7679
+			if skippy < 0 {
7680
+				return ErrInvalidLengthOps
7681
+			}
7682
+			if (iNdEx + skippy) < 0 {
7683
+				return ErrInvalidLengthOps
7684
+			}
7685
+			if (iNdEx + skippy) > l {
7686
+				return io.ErrUnexpectedEOF
7687
+			}
7688
+			iNdEx += skippy
7689
+		}
7690
+	}
7691
+
7692
+	if iNdEx > l {
7693
+		return io.ErrUnexpectedEOF
7694
+	}
7695
+	return nil
7696
+}
7697
+func (m *SourceInfo) Unmarshal(dAtA []byte) error {
7698
+	l := len(dAtA)
7699
+	iNdEx := 0
7700
+	for iNdEx < l {
7701
+		preIndex := iNdEx
7702
+		var wire uint64
7703
+		for shift := uint(0); ; shift += 7 {
7704
+			if shift >= 64 {
7705
+				return ErrIntOverflowOps
7706
+			}
7707
+			if iNdEx >= l {
7708
+				return io.ErrUnexpectedEOF
7709
+			}
7710
+			b := dAtA[iNdEx]
7711
+			iNdEx++
7712
+			wire |= uint64(b&0x7F) << shift
7713
+			if b < 0x80 {
7714
+				break
7715
+			}
7716
+		}
7717
+		fieldNum := int32(wire >> 3)
7718
+		wireType := int(wire & 0x7)
7719
+		if wireType == 4 {
7720
+			return fmt.Errorf("proto: SourceInfo: wiretype end group for non-group")
7721
+		}
7722
+		if fieldNum <= 0 {
7723
+			return fmt.Errorf("proto: SourceInfo: illegal tag %d (wire type %d)", fieldNum, wire)
7724
+		}
7725
+		switch fieldNum {
7726
+		case 1:
7727
+			if wireType != 2 {
7728
+				return fmt.Errorf("proto: wrong wireType = %d for field Filename", wireType)
7729
+			}
7730
+			var stringLen uint64
7731
+			for shift := uint(0); ; shift += 7 {
7732
+				if shift >= 64 {
7733
+					return ErrIntOverflowOps
7734
+				}
7735
+				if iNdEx >= l {
7736
+					return io.ErrUnexpectedEOF
7737
+				}
7738
+				b := dAtA[iNdEx]
7739
+				iNdEx++
7740
+				stringLen |= uint64(b&0x7F) << shift
7741
+				if b < 0x80 {
7742
+					break
7743
+				}
7744
+			}
7745
+			intStringLen := int(stringLen)
7746
+			if intStringLen < 0 {
7747
+				return ErrInvalidLengthOps
7748
+			}
7749
+			postIndex := iNdEx + intStringLen
7750
+			if postIndex < 0 {
7751
+				return ErrInvalidLengthOps
7752
+			}
7753
+			if postIndex > l {
7754
+				return io.ErrUnexpectedEOF
7755
+			}
7756
+			m.Filename = string(dAtA[iNdEx:postIndex])
7757
+			iNdEx = postIndex
7758
+		case 2:
7759
+			if wireType != 2 {
7760
+				return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
7761
+			}
7762
+			var byteLen int
7763
+			for shift := uint(0); ; shift += 7 {
7764
+				if shift >= 64 {
7765
+					return ErrIntOverflowOps
7766
+				}
7767
+				if iNdEx >= l {
7768
+					return io.ErrUnexpectedEOF
7769
+				}
7770
+				b := dAtA[iNdEx]
7771
+				iNdEx++
7772
+				byteLen |= int(b&0x7F) << shift
7773
+				if b < 0x80 {
7774
+					break
7775
+				}
7776
+			}
7777
+			if byteLen < 0 {
7778
+				return ErrInvalidLengthOps
7779
+			}
7780
+			postIndex := iNdEx + byteLen
7781
+			if postIndex < 0 {
7782
+				return ErrInvalidLengthOps
7783
+			}
7784
+			if postIndex > l {
7785
+				return io.ErrUnexpectedEOF
7786
+			}
7787
+			m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
7788
+			if m.Data == nil {
7789
+				m.Data = []byte{}
7790
+			}
7791
+			iNdEx = postIndex
7792
+		case 3:
7793
+			if wireType != 2 {
7794
+				return fmt.Errorf("proto: wrong wireType = %d for field Definition", wireType)
7795
+			}
7796
+			var msglen int
7797
+			for shift := uint(0); ; shift += 7 {
7798
+				if shift >= 64 {
7799
+					return ErrIntOverflowOps
7800
+				}
7801
+				if iNdEx >= l {
7802
+					return io.ErrUnexpectedEOF
7803
+				}
7804
+				b := dAtA[iNdEx]
7805
+				iNdEx++
7806
+				msglen |= int(b&0x7F) << shift
7807
+				if b < 0x80 {
7808
+					break
7809
+				}
7810
+			}
7811
+			if msglen < 0 {
7812
+				return ErrInvalidLengthOps
7813
+			}
7814
+			postIndex := iNdEx + msglen
7815
+			if postIndex < 0 {
7816
+				return ErrInvalidLengthOps
7817
+			}
7818
+			if postIndex > l {
7819
+				return io.ErrUnexpectedEOF
7820
+			}
7821
+			if m.Definition == nil {
7822
+				m.Definition = &Definition{}
7823
+			}
7824
+			if err := m.Definition.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
7825
+				return err
7826
+			}
7827
+			iNdEx = postIndex
7828
+		default:
7829
+			iNdEx = preIndex
7830
+			skippy, err := skipOps(dAtA[iNdEx:])
7831
+			if err != nil {
7832
+				return err
7833
+			}
7834
+			if skippy < 0 {
7835
+				return ErrInvalidLengthOps
7836
+			}
7837
+			if (iNdEx + skippy) < 0 {
7838
+				return ErrInvalidLengthOps
7839
+			}
7840
+			if (iNdEx + skippy) > l {
7841
+				return io.ErrUnexpectedEOF
7842
+			}
7843
+			iNdEx += skippy
7844
+		}
7845
+	}
7846
+
7847
+	if iNdEx > l {
7848
+		return io.ErrUnexpectedEOF
7849
+	}
7850
+	return nil
7851
+}
7852
+func (m *Location) Unmarshal(dAtA []byte) error {
7853
+	l := len(dAtA)
7854
+	iNdEx := 0
7855
+	for iNdEx < l {
7856
+		preIndex := iNdEx
7857
+		var wire uint64
7858
+		for shift := uint(0); ; shift += 7 {
7859
+			if shift >= 64 {
7860
+				return ErrIntOverflowOps
7861
+			}
7862
+			if iNdEx >= l {
7863
+				return io.ErrUnexpectedEOF
7864
+			}
7865
+			b := dAtA[iNdEx]
7866
+			iNdEx++
7867
+			wire |= uint64(b&0x7F) << shift
7868
+			if b < 0x80 {
7869
+				break
7870
+			}
7871
+		}
7872
+		fieldNum := int32(wire >> 3)
7873
+		wireType := int(wire & 0x7)
7874
+		if wireType == 4 {
7875
+			return fmt.Errorf("proto: Location: wiretype end group for non-group")
7876
+		}
7877
+		if fieldNum <= 0 {
7878
+			return fmt.Errorf("proto: Location: illegal tag %d (wire type %d)", fieldNum, wire)
7879
+		}
7880
+		switch fieldNum {
7881
+		case 1:
7882
+			if wireType != 0 {
7883
+				return fmt.Errorf("proto: wrong wireType = %d for field SourceIndex", wireType)
7884
+			}
7885
+			m.SourceIndex = 0
7886
+			for shift := uint(0); ; shift += 7 {
7887
+				if shift >= 64 {
7888
+					return ErrIntOverflowOps
7889
+				}
7890
+				if iNdEx >= l {
7891
+					return io.ErrUnexpectedEOF
7892
+				}
7893
+				b := dAtA[iNdEx]
7894
+				iNdEx++
7895
+				m.SourceIndex |= int32(b&0x7F) << shift
7896
+				if b < 0x80 {
7897
+					break
7898
+				}
7899
+			}
7900
+		case 2:
7901
+			if wireType != 2 {
7902
+				return fmt.Errorf("proto: wrong wireType = %d for field Ranges", wireType)
7903
+			}
7904
+			var msglen int
7905
+			for shift := uint(0); ; shift += 7 {
7906
+				if shift >= 64 {
7907
+					return ErrIntOverflowOps
7908
+				}
7909
+				if iNdEx >= l {
7910
+					return io.ErrUnexpectedEOF
7911
+				}
7912
+				b := dAtA[iNdEx]
7913
+				iNdEx++
7914
+				msglen |= int(b&0x7F) << shift
7915
+				if b < 0x80 {
7916
+					break
7917
+				}
7918
+			}
7919
+			if msglen < 0 {
7920
+				return ErrInvalidLengthOps
7921
+			}
7922
+			postIndex := iNdEx + msglen
7923
+			if postIndex < 0 {
7924
+				return ErrInvalidLengthOps
7925
+			}
7926
+			if postIndex > l {
7927
+				return io.ErrUnexpectedEOF
7928
+			}
7929
+			m.Ranges = append(m.Ranges, &Range{})
7930
+			if err := m.Ranges[len(m.Ranges)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
7931
+				return err
7932
+			}
7933
+			iNdEx = postIndex
7934
+		default:
7935
+			iNdEx = preIndex
7936
+			skippy, err := skipOps(dAtA[iNdEx:])
7937
+			if err != nil {
7938
+				return err
7939
+			}
7940
+			if skippy < 0 {
7941
+				return ErrInvalidLengthOps
7942
+			}
7943
+			if (iNdEx + skippy) < 0 {
7944
+				return ErrInvalidLengthOps
7945
+			}
7946
+			if (iNdEx + skippy) > l {
7947
+				return io.ErrUnexpectedEOF
7948
+			}
7949
+			iNdEx += skippy
7950
+		}
7951
+	}
7952
+
7953
+	if iNdEx > l {
7954
+		return io.ErrUnexpectedEOF
7955
+	}
7956
+	return nil
7957
+}
7958
+func (m *Range) Unmarshal(dAtA []byte) error {
7959
+	l := len(dAtA)
7960
+	iNdEx := 0
7961
+	for iNdEx < l {
7962
+		preIndex := iNdEx
7963
+		var wire uint64
7964
+		for shift := uint(0); ; shift += 7 {
7965
+			if shift >= 64 {
7966
+				return ErrIntOverflowOps
7967
+			}
7968
+			if iNdEx >= l {
7969
+				return io.ErrUnexpectedEOF
7970
+			}
7971
+			b := dAtA[iNdEx]
7972
+			iNdEx++
7973
+			wire |= uint64(b&0x7F) << shift
7974
+			if b < 0x80 {
7975
+				break
7976
+			}
7977
+		}
7978
+		fieldNum := int32(wire >> 3)
7979
+		wireType := int(wire & 0x7)
7980
+		if wireType == 4 {
7981
+			return fmt.Errorf("proto: Range: wiretype end group for non-group")
7982
+		}
7983
+		if fieldNum <= 0 {
7984
+			return fmt.Errorf("proto: Range: illegal tag %d (wire type %d)", fieldNum, wire)
7985
+		}
7986
+		switch fieldNum {
7987
+		case 1:
7988
+			if wireType != 2 {
7989
+				return fmt.Errorf("proto: wrong wireType = %d for field Start", wireType)
7990
+			}
7991
+			var msglen int
7992
+			for shift := uint(0); ; shift += 7 {
7993
+				if shift >= 64 {
7994
+					return ErrIntOverflowOps
7995
+				}
7996
+				if iNdEx >= l {
7997
+					return io.ErrUnexpectedEOF
7998
+				}
7999
+				b := dAtA[iNdEx]
8000
+				iNdEx++
8001
+				msglen |= int(b&0x7F) << shift
8002
+				if b < 0x80 {
8003
+					break
8004
+				}
8005
+			}
8006
+			if msglen < 0 {
8007
+				return ErrInvalidLengthOps
8008
+			}
8009
+			postIndex := iNdEx + msglen
8010
+			if postIndex < 0 {
8011
+				return ErrInvalidLengthOps
8012
+			}
8013
+			if postIndex > l {
8014
+				return io.ErrUnexpectedEOF
8015
+			}
8016
+			if err := m.Start.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
8017
+				return err
8018
+			}
8019
+			iNdEx = postIndex
8020
+		case 2:
8021
+			if wireType != 2 {
8022
+				return fmt.Errorf("proto: wrong wireType = %d for field End", wireType)
8023
+			}
8024
+			var msglen int
8025
+			for shift := uint(0); ; shift += 7 {
8026
+				if shift >= 64 {
8027
+					return ErrIntOverflowOps
8028
+				}
8029
+				if iNdEx >= l {
8030
+					return io.ErrUnexpectedEOF
8031
+				}
8032
+				b := dAtA[iNdEx]
8033
+				iNdEx++
8034
+				msglen |= int(b&0x7F) << shift
8035
+				if b < 0x80 {
8036
+					break
8037
+				}
8038
+			}
8039
+			if msglen < 0 {
8040
+				return ErrInvalidLengthOps
8041
+			}
8042
+			postIndex := iNdEx + msglen
8043
+			if postIndex < 0 {
8044
+				return ErrInvalidLengthOps
8045
+			}
8046
+			if postIndex > l {
8047
+				return io.ErrUnexpectedEOF
8048
+			}
8049
+			if err := m.End.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
8050
+				return err
8051
+			}
8052
+			iNdEx = postIndex
8053
+		default:
8054
+			iNdEx = preIndex
8055
+			skippy, err := skipOps(dAtA[iNdEx:])
8056
+			if err != nil {
8057
+				return err
8058
+			}
8059
+			if skippy < 0 {
8060
+				return ErrInvalidLengthOps
8061
+			}
8062
+			if (iNdEx + skippy) < 0 {
8063
+				return ErrInvalidLengthOps
8064
+			}
8065
+			if (iNdEx + skippy) > l {
8066
+				return io.ErrUnexpectedEOF
8067
+			}
8068
+			iNdEx += skippy
8069
+		}
8070
+	}
8071
+
8072
+	if iNdEx > l {
8073
+		return io.ErrUnexpectedEOF
8074
+	}
8075
+	return nil
8076
+}
8077
+func (m *Position) Unmarshal(dAtA []byte) error {
8078
+	l := len(dAtA)
8079
+	iNdEx := 0
8080
+	for iNdEx < l {
8081
+		preIndex := iNdEx
8082
+		var wire uint64
8083
+		for shift := uint(0); ; shift += 7 {
8084
+			if shift >= 64 {
8085
+				return ErrIntOverflowOps
8086
+			}
8087
+			if iNdEx >= l {
8088
+				return io.ErrUnexpectedEOF
8089
+			}
8090
+			b := dAtA[iNdEx]
8091
+			iNdEx++
8092
+			wire |= uint64(b&0x7F) << shift
8093
+			if b < 0x80 {
8094
+				break
8095
+			}
8096
+		}
8097
+		fieldNum := int32(wire >> 3)
8098
+		wireType := int(wire & 0x7)
8099
+		if wireType == 4 {
8100
+			return fmt.Errorf("proto: Position: wiretype end group for non-group")
8101
+		}
8102
+		if fieldNum <= 0 {
8103
+			return fmt.Errorf("proto: Position: illegal tag %d (wire type %d)", fieldNum, wire)
8104
+		}
8105
+		switch fieldNum {
8106
+		case 1:
8107
+			if wireType != 0 {
8108
+				return fmt.Errorf("proto: wrong wireType = %d for field Line", wireType)
8109
+			}
8110
+			m.Line = 0
8111
+			for shift := uint(0); ; shift += 7 {
8112
+				if shift >= 64 {
8113
+					return ErrIntOverflowOps
8114
+				}
8115
+				if iNdEx >= l {
8116
+					return io.ErrUnexpectedEOF
8117
+				}
8118
+				b := dAtA[iNdEx]
8119
+				iNdEx++
8120
+				m.Line |= int32(b&0x7F) << shift
8121
+				if b < 0x80 {
8122
+					break
8123
+				}
8124
+			}
8125
+		case 2:
8126
+			if wireType != 0 {
8127
+				return fmt.Errorf("proto: wrong wireType = %d for field Character", wireType)
8128
+			}
8129
+			m.Character = 0
8130
+			for shift := uint(0); ; shift += 7 {
8131
+				if shift >= 64 {
8132
+					return ErrIntOverflowOps
8133
+				}
8134
+				if iNdEx >= l {
8135
+					return io.ErrUnexpectedEOF
8136
+				}
8137
+				b := dAtA[iNdEx]
8138
+				iNdEx++
8139
+				m.Character |= int32(b&0x7F) << shift
8140
+				if b < 0x80 {
8141
+					break
8142
+				}
8143
+			}
8144
+		default:
8145
+			iNdEx = preIndex
8146
+			skippy, err := skipOps(dAtA[iNdEx:])
8147
+			if err != nil {
8148
+				return err
8149
+			}
8150
+			if skippy < 0 {
8151
+				return ErrInvalidLengthOps
8152
+			}
8153
+			if (iNdEx + skippy) < 0 {
8154
+				return ErrInvalidLengthOps
8155
+			}
8156
+			if (iNdEx + skippy) > l {
8157
+				return io.ErrUnexpectedEOF
8158
+			}
8159
+			iNdEx += skippy
8160
+		}
8161
+	}
8162
+
8163
+	if iNdEx > l {
8164
+		return io.ErrUnexpectedEOF
8165
+	}
8166
+	return nil
8167
+}
7394 8168
 func (m *ExportCache) Unmarshal(dAtA []byte) error {
7395 8169
 	l := len(dAtA)
7396 8170
 	iNdEx := 0
... ...
@@ -7920,6 +9415,42 @@ func (m *Definition) Unmarshal(dAtA []byte) error {
7920 7920
 			}
7921 7921
 			m.Metadata[github_com_opencontainers_go_digest.Digest(mapkey)] = *mapvalue
7922 7922
 			iNdEx = postIndex
7923
+		case 3:
7924
+			if wireType != 2 {
7925
+				return fmt.Errorf("proto: wrong wireType = %d for field Source", wireType)
7926
+			}
7927
+			var msglen int
7928
+			for shift := uint(0); ; shift += 7 {
7929
+				if shift >= 64 {
7930
+					return ErrIntOverflowOps
7931
+				}
7932
+				if iNdEx >= l {
7933
+					return io.ErrUnexpectedEOF
7934
+				}
7935
+				b := dAtA[iNdEx]
7936
+				iNdEx++
7937
+				msglen |= int(b&0x7F) << shift
7938
+				if b < 0x80 {
7939
+					break
7940
+				}
7941
+			}
7942
+			if msglen < 0 {
7943
+				return ErrInvalidLengthOps
7944
+			}
7945
+			postIndex := iNdEx + msglen
7946
+			if postIndex < 0 {
7947
+				return ErrInvalidLengthOps
7948
+			}
7949
+			if postIndex > l {
7950
+				return io.ErrUnexpectedEOF
7951
+			}
7952
+			if m.Source == nil {
7953
+				m.Source = &Source{}
7954
+			}
7955
+			if err := m.Source.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
7956
+				return err
7957
+			}
7958
+			iNdEx = postIndex
7923 7959
 		default:
7924 7960
 			iNdEx = preIndex
7925 7961
 			skippy, err := skipOps(dAtA[iNdEx:])
... ...
@@ -177,6 +177,42 @@ message OpMetadata {
177 177
 	map<string, bool> caps = 5 [(gogoproto.castkey) = "github.com/moby/buildkit/util/apicaps.CapID", (gogoproto.nullable) = false];
178 178
 }
179 179
 
180
+// Source is a source mapping description for a file
181
+message Source {
182
+	map<string, Locations> locations = 1;
183
+	repeated SourceInfo infos = 2;
184
+}
185
+
186
+// Locations is a list of ranges with a index to its source map.
187
+message Locations {
188
+	repeated Location locations = 1;
189
+}
190
+
191
+// Source info contains the shared metadata of a source mapping
192
+message SourceInfo {
193
+ 	string filename = 1;
194
+	bytes data = 2;
195
+	Definition definition = 3;
196
+}
197
+
198
+// Location defines list of areas in to source file
199
+message Location {
200
+	int32 sourceIndex = 1;
201
+	repeated Range ranges = 2;
202
+}
203
+
204
+// Range is an area in the source file
205
+message Range {
206
+	Position start = 1 [(gogoproto.nullable) = false];
207
+	Position end = 2 [(gogoproto.nullable) = false];
208
+}
209
+
210
+// Position is single location in a source file
211
+message Position {
212
+	int32 Line = 1;
213
+	int32 Character = 2;
214
+}
215
+
180 216
 message ExportCache {
181 217
 	bool Value = 1;
182 218
 }
... ...
@@ -200,6 +236,8 @@ message Definition {
200 200
 	// metadata contains metadata for the each of the Op messages.
201 201
 	// 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.
202 202
 	map<string, OpMetadata> metadata = 2 [(gogoproto.castkey) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false];
203
+	// Source contains the source mapping information for the vertexes in the definition
204
+	Source Source = 3;
203 205
 }
204 206
 
205 207
 message HostIP {
... ...
@@ -302,4 +340,4 @@ message UserOpt {
302 302
 message NamedUserOpt {
303 303
 	string name = 1;
304 304
 	int64 input = 2 [(gogoproto.customtype) = "InputIndex", (gogoproto.nullable) = false];
305
-}
306 305
\ No newline at end of file
306
+}
... ...
@@ -72,7 +72,7 @@ func (gs *gitSource) mountRemote(ctx context.Context, remote string) (target str
72 72
 	for _, si := range sis {
73 73
 		remoteRef, err = gs.cache.GetMutable(ctx, si.ID())
74 74
 		if err != nil {
75
-			if cache.IsLocked(err) {
75
+			if errors.Is(err, cache.ErrLocked) {
76 76
 				// should never really happen as no other function should access this metadata, but lets be graceful
77 77
 				logrus.Warnf("mutable ref for %s  %s was locked: %v", remote, si.ID(), err)
78 78
 				continue
79 79
deleted file mode 100644
... ...
@@ -1,42 +0,0 @@
1
-package binfmt_misc
2
-
3
-import (
4
-	"bytes"
5
-	"compress/gzip"
6
-	"io"
7
-	"io/ioutil"
8
-	"os"
9
-	"os/exec"
10
-	"path/filepath"
11
-)
12
-
13
-func check(bin string) error {
14
-	tmpdir, err := ioutil.TempDir("", "qemu-check")
15
-	if err != nil {
16
-		return err
17
-	}
18
-	defer os.RemoveAll(tmpdir)
19
-	pp := filepath.Join(tmpdir, "check")
20
-
21
-	r, err := gzip.NewReader(bytes.NewReader([]byte(bin)))
22
-	if err != nil {
23
-		return err
24
-	}
25
-	defer r.Close()
26
-
27
-	f, err := os.OpenFile(pp, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0700)
28
-	if err != nil {
29
-		return err
30
-	}
31
-
32
-	if _, err := io.Copy(f, r); err != nil {
33
-		f.Close()
34
-		return err
35
-	}
36
-	f.Close()
37
-
38
-	cmd := exec.Command("/check")
39
-	withChroot(cmd, tmpdir)
40
-	err = cmd.Run()
41
-	return err
42
-}
... ...
@@ -3,7 +3,13 @@
3 3
 package binfmt_misc
4 4
 
5 5
 import (
6
+	"bytes"
7
+	"compress/gzip"
8
+	"io"
9
+	"io/ioutil"
10
+	"os"
6 11
 	"os/exec"
12
+	"path/filepath"
7 13
 	"syscall"
8 14
 )
9 15
 
... ...
@@ -12,3 +18,34 @@ func withChroot(cmd *exec.Cmd, dir string) {
12 12
 		Chroot: dir,
13 13
 	}
14 14
 }
15
+
16
+func check(bin string) error {
17
+	tmpdir, err := ioutil.TempDir("", "qemu-check")
18
+	if err != nil {
19
+		return err
20
+	}
21
+	defer os.RemoveAll(tmpdir)
22
+	pp := filepath.Join(tmpdir, "check")
23
+
24
+	r, err := gzip.NewReader(bytes.NewReader([]byte(bin)))
25
+	if err != nil {
26
+		return err
27
+	}
28
+	defer r.Close()
29
+
30
+	f, err := os.OpenFile(pp, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0700)
31
+	if err != nil {
32
+		return err
33
+	}
34
+
35
+	if _, err := io.Copy(f, r); err != nil {
36
+		f.Close()
37
+		return err
38
+	}
39
+	f.Close()
40
+
41
+	cmd := exec.Command("/check")
42
+	withChroot(cmd, tmpdir)
43
+	err = cmd.Run()
44
+	return err
45
+}
... ...
@@ -3,8 +3,13 @@
3 3
 package binfmt_misc
4 4
 
5 5
 import (
6
+	"errors"
6 7
 	"os/exec"
7 8
 )
8 9
 
9 10
 func withChroot(cmd *exec.Cmd, dir string) {
10 11
 }
12
+
13
+func check(bin string) error {
14
+	return errors.New("binfmt is not supported on Windows")
15
+}
... ...
@@ -43,7 +43,7 @@ func WhiteList(allowed, supported []Entitlement) (Set, error) {
43 43
 		}
44 44
 		if supported != nil {
45 45
 			if !supm.Allowed(e) {
46
-				return nil, errors.Errorf("entitlement %s is not allowed", e)
46
+				return nil, errors.Errorf("granting entitlement %s is not allowed by build daemon configuration", e)
47 47
 			}
48 48
 		}
49 49
 		m[e] = struct{}{}
... ...
@@ -35,7 +35,7 @@ func (g *Group) Do(ctx context.Context, key string, fn func(ctx context.Context)
35 35
 	var backoff time.Duration
36 36
 	for {
37 37
 		v, err = g.do(ctx, key, fn)
38
-		if err == nil || errors.Cause(err) != errRetry {
38
+		if err == nil || !errors.Is(err, errRetry) {
39 39
 			return v, err
40 40
 		}
41 41
 		// backoff logic
42 42
new file mode 100644
... ...
@@ -0,0 +1,188 @@
0
+package grpcerrors
1
+
2
+import (
3
+	gogotypes "github.com/gogo/protobuf/types"
4
+	"github.com/golang/protobuf/proto"
5
+	"github.com/golang/protobuf/ptypes"
6
+	"github.com/golang/protobuf/ptypes/any"
7
+	"github.com/moby/buildkit/util/stack"
8
+	spb "google.golang.org/genproto/googleapis/rpc/status"
9
+	"google.golang.org/grpc/codes"
10
+	"google.golang.org/grpc/status"
11
+)
12
+
13
+type TypedError interface {
14
+	ToProto() TypedErrorProto
15
+}
16
+
17
+type TypedErrorProto interface {
18
+	proto.Message
19
+	WrapError(error) error
20
+}
21
+
22
+func ToGRPC(err error) error {
23
+	if err == nil {
24
+		return nil
25
+	}
26
+	st, ok := AsGRPCStatus(err)
27
+	if !ok || st == nil {
28
+		st = status.New(Code(err), err.Error())
29
+	}
30
+	if st.Code() != Code(err) {
31
+		pb := st.Proto()
32
+		pb.Code = int32(Code(err))
33
+		st = status.FromProto(pb)
34
+	}
35
+
36
+	var details []proto.Message
37
+
38
+	for _, st := range stack.Traces(err) {
39
+		details = append(details, st)
40
+	}
41
+
42
+	each(err, func(err error) {
43
+		if te, ok := err.(TypedError); ok {
44
+			details = append(details, te.ToProto())
45
+		}
46
+	})
47
+
48
+	if len(details) > 0 {
49
+		if st2, err := st.WithDetails(details...); err == nil {
50
+			st = st2
51
+		}
52
+	}
53
+
54
+	return st.Err()
55
+}
56
+
57
+func Code(err error) codes.Code {
58
+	if se, ok := err.(interface {
59
+		Code() codes.Code
60
+	}); ok {
61
+		return se.Code()
62
+	}
63
+
64
+	if se, ok := err.(interface {
65
+		GRPCStatus() *status.Status
66
+	}); ok {
67
+		return se.GRPCStatus().Code()
68
+	}
69
+
70
+	wrapped, ok := err.(interface {
71
+		Unwrap() error
72
+	})
73
+	if ok {
74
+		return Code(wrapped.Unwrap())
75
+	}
76
+
77
+	return status.FromContextError(err).Code()
78
+}
79
+
80
+func WrapCode(err error, code codes.Code) error {
81
+	return &withCode{error: err, code: code}
82
+}
83
+
84
+func AsGRPCStatus(err error) (*status.Status, bool) {
85
+	if err == nil {
86
+		return nil, true
87
+	}
88
+	if se, ok := err.(interface {
89
+		GRPCStatus() *status.Status
90
+	}); ok {
91
+		return se.GRPCStatus(), true
92
+	}
93
+
94
+	wrapped, ok := err.(interface {
95
+		Unwrap() error
96
+	})
97
+	if ok {
98
+		return AsGRPCStatus(wrapped.Unwrap())
99
+	}
100
+
101
+	return nil, false
102
+}
103
+
104
+func FromGRPC(err error) error {
105
+	if err == nil {
106
+		return nil
107
+	}
108
+	st, ok := status.FromError(err)
109
+	if !ok {
110
+		return err
111
+	}
112
+
113
+	pb := st.Proto()
114
+
115
+	n := &spb.Status{
116
+		Code:    pb.Code,
117
+		Message: pb.Message,
118
+	}
119
+
120
+	details := make([]TypedErrorProto, 0, len(pb.Details))
121
+	stacks := make([]*stack.Stack, 0, len(pb.Details))
122
+
123
+	// details that we don't understand are copied as proto
124
+	for _, d := range pb.Details {
125
+		var m interface{}
126
+		detail := &ptypes.DynamicAny{}
127
+		if err := ptypes.UnmarshalAny(d, detail); err != nil {
128
+			detail := &gogotypes.DynamicAny{}
129
+			if err := gogotypes.UnmarshalAny(gogoAny(d), detail); err != nil {
130
+				n.Details = append(n.Details, d)
131
+				continue
132
+			}
133
+			m = detail.Message
134
+		} else {
135
+			m = detail.Message
136
+		}
137
+
138
+		switch v := m.(type) {
139
+		case *stack.Stack:
140
+			stacks = append(stacks, v)
141
+		case TypedErrorProto:
142
+			details = append(details, v)
143
+		default:
144
+			n.Details = append(n.Details, d)
145
+		}
146
+
147
+	}
148
+
149
+	err = status.FromProto(n).Err()
150
+
151
+	for _, s := range stacks {
152
+		if s != nil {
153
+			err = stack.Wrap(err, *s)
154
+		}
155
+	}
156
+
157
+	for _, d := range details {
158
+		err = d.WrapError(err)
159
+	}
160
+
161
+	return stack.Enable(err)
162
+}
163
+
164
+type withCode struct {
165
+	code codes.Code
166
+	error
167
+}
168
+
169
+func (e *withCode) Unwrap() error {
170
+	return e.error
171
+}
172
+
173
+func each(err error, fn func(error)) {
174
+	fn(err)
175
+	if wrapped, ok := err.(interface {
176
+		Unwrap() error
177
+	}); ok {
178
+		each(wrapped.Unwrap(), fn)
179
+	}
180
+}
181
+
182
+func gogoAny(in *any.Any) *gogotypes.Any {
183
+	return &gogotypes.Any{
184
+		TypeUrl: in.TypeUrl,
185
+		Value:   in.Value,
186
+	}
187
+}
0 188
new file mode 100644
... ...
@@ -0,0 +1,28 @@
0
+package grpcerrors
1
+
2
+import (
3
+	"context"
4
+
5
+	"google.golang.org/grpc"
6
+)
7
+
8
+func UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
9
+	resp, err = handler(ctx, req)
10
+	if err != nil {
11
+		err = ToGRPC(err)
12
+	}
13
+	return resp, err
14
+}
15
+
16
+func StreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
17
+	return ToGRPC(handler(srv, ss))
18
+}
19
+
20
+func UnaryClientInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
21
+	return FromGRPC(invoker(ctx, method, req, reply, cc, opts...))
22
+}
23
+
24
+func StreamClientInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
25
+	s, err := streamer(ctx, desc, cc, method, opts...)
26
+	return s, ToGRPC(err)
27
+}
... ...
@@ -50,7 +50,7 @@ func fillInsecureOpts(host string, c config.RegistryConfig, h *docker.RegistryHo
50 50
 func loadTLSConfig(c config.RegistryConfig) (*tls.Config, error) {
51 51
 	for _, d := range c.TLSConfigDir {
52 52
 		fs, err := ioutil.ReadDir(d)
53
-		if err != nil && !os.IsNotExist(err) && !os.IsPermission(err) {
53
+		if err != nil && !errors.Is(err, os.ErrNotExist) && !errors.Is(err, os.ErrPermission) {
54 54
 			return nil, errors.WithStack(err)
55 55
 		}
56 56
 		for _, f := range fs {
... ...
@@ -3,7 +3,7 @@ package specconv
3 3
 import (
4 4
 	"strings"
5 5
 
6
-	"github.com/opencontainers/runtime-spec/specs-go"
6
+	specs "github.com/opencontainers/runtime-spec/specs-go"
7 7
 )
8 8
 
9 9
 // ToRootless converts spec to be compatible with "rootless" runc.
10 10
new file mode 100644
... ...
@@ -0,0 +1,3 @@
0
+package stack
1
+
2
+//go:generate protoc -I=. -I=../../vendor/ --go_out=. stack.proto
0 3
new file mode 100644
... ...
@@ -0,0 +1,151 @@
0
+package stack
1
+
2
+import (
3
+	"fmt"
4
+	io "io"
5
+	"os"
6
+	"strconv"
7
+	"strings"
8
+
9
+	"github.com/pkg/errors"
10
+)
11
+
12
+var version string
13
+var revision string
14
+
15
+func SetVersionInfo(v, r string) {
16
+	version = v
17
+	revision = r
18
+}
19
+
20
+func Traces(err error) []*Stack {
21
+	var st []*Stack
22
+
23
+	wrapped, ok := err.(interface {
24
+		Unwrap() error
25
+	})
26
+	if ok {
27
+		st = Traces(wrapped.Unwrap())
28
+	}
29
+
30
+	if ste, ok := err.(interface {
31
+		StackTrace() errors.StackTrace
32
+	}); ok {
33
+		st = append(st, convertStack(ste.StackTrace()))
34
+	}
35
+
36
+	if ste, ok := err.(interface {
37
+		StackTrace() *Stack
38
+	}); ok {
39
+		st = append(st, ste.StackTrace())
40
+	}
41
+
42
+	return st
43
+}
44
+
45
+func Enable(err error) error {
46
+	if err == nil {
47
+		return nil
48
+	}
49
+	if !hasLocalStackTrace(err) {
50
+		return errors.WithStack(err)
51
+	}
52
+	return err
53
+}
54
+
55
+func Wrap(err error, s Stack) error {
56
+	return &withStack{stack: s, error: err}
57
+}
58
+
59
+func hasLocalStackTrace(err error) bool {
60
+	wrapped, ok := err.(interface {
61
+		Unwrap() error
62
+	})
63
+	if ok && hasLocalStackTrace(wrapped.Unwrap()) {
64
+		return true
65
+	}
66
+
67
+	_, ok = err.(interface {
68
+		StackTrace() errors.StackTrace
69
+	})
70
+	return ok
71
+}
72
+
73
+func Formatter(err error) fmt.Formatter {
74
+	return &formatter{err}
75
+}
76
+
77
+type formatter struct {
78
+	error
79
+}
80
+
81
+func (w *formatter) Format(s fmt.State, verb rune) {
82
+	if w.error == nil {
83
+		fmt.Fprintf(s, "%v", w.error)
84
+		return
85
+	}
86
+	switch verb {
87
+	case 'v':
88
+		if s.Flag('+') {
89
+			fmt.Fprintf(s, "%s\n", w.Error())
90
+			for _, stack := range Traces(w.error) {
91
+				fmt.Fprintf(s, "%d %s %s\n", stack.Pid, stack.Version, strings.Join(stack.Cmdline, " "))
92
+				for _, f := range stack.Frames {
93
+					fmt.Fprintf(s, "%s\n\t%s:%d\n", f.Name, f.File, f.Line)
94
+				}
95
+				fmt.Fprintln(s)
96
+			}
97
+			return
98
+		}
99
+		fallthrough
100
+	case 's':
101
+		io.WriteString(s, w.Error())
102
+	case 'q':
103
+		fmt.Fprintf(s, "%q", w.Error())
104
+	}
105
+}
106
+
107
+func convertStack(s errors.StackTrace) *Stack {
108
+	var out Stack
109
+	for _, f := range s {
110
+		dt, err := f.MarshalText()
111
+		if err != nil {
112
+			continue
113
+		}
114
+		p := strings.SplitN(string(dt), " ", 2)
115
+		if len(p) != 2 {
116
+			continue
117
+		}
118
+		idx := strings.LastIndexByte(p[1], ':')
119
+		if idx == -1 {
120
+			continue
121
+		}
122
+		line, err := strconv.Atoi(p[1][idx+1:])
123
+		if err != nil {
124
+			continue
125
+		}
126
+		out.Frames = append(out.Frames, &Frame{
127
+			Name: p[0],
128
+			File: p[1][:idx],
129
+			Line: int32(line),
130
+		})
131
+	}
132
+	out.Cmdline = os.Args
133
+	out.Pid = int32(os.Getpid())
134
+	out.Version = version
135
+	out.Revision = revision
136
+	return &out
137
+}
138
+
139
+type withStack struct {
140
+	stack Stack
141
+	error
142
+}
143
+
144
+func (e *withStack) Unwrap() error {
145
+	return e.error
146
+}
147
+
148
+func (e *withStack) StackTrace() *Stack {
149
+	return &e.stack
150
+}
0 151
new file mode 100644
... ...
@@ -0,0 +1,170 @@
0
+// Code generated by protoc-gen-go. DO NOT EDIT.
1
+// source: stack.proto
2
+
3
+package stack
4
+
5
+import (
6
+	fmt "fmt"
7
+	proto "github.com/golang/protobuf/proto"
8
+	math "math"
9
+)
10
+
11
+// Reference imports to suppress errors if they are not otherwise used.
12
+var _ = proto.Marshal
13
+var _ = fmt.Errorf
14
+var _ = math.Inf
15
+
16
+// This is a compile-time assertion to ensure that this generated file
17
+// is compatible with the proto package it is being compiled against.
18
+// A compilation error at this line likely means your copy of the
19
+// proto package needs to be updated.
20
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
21
+
22
+type Stack struct {
23
+	Frames               []*Frame `protobuf:"bytes,1,rep,name=frames,proto3" json:"frames,omitempty"`
24
+	Cmdline              []string `protobuf:"bytes,2,rep,name=cmdline,proto3" json:"cmdline,omitempty"`
25
+	Pid                  int32    `protobuf:"varint,3,opt,name=pid,proto3" json:"pid,omitempty"`
26
+	Version              string   `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"`
27
+	Revision             string   `protobuf:"bytes,5,opt,name=revision,proto3" json:"revision,omitempty"`
28
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
29
+	XXX_unrecognized     []byte   `json:"-"`
30
+	XXX_sizecache        int32    `json:"-"`
31
+}
32
+
33
+func (m *Stack) Reset()         { *m = Stack{} }
34
+func (m *Stack) String() string { return proto.CompactTextString(m) }
35
+func (*Stack) ProtoMessage()    {}
36
+func (*Stack) Descriptor() ([]byte, []int) {
37
+	return fileDescriptor_b44c07feb2ca0a5a, []int{0}
38
+}
39
+
40
+func (m *Stack) XXX_Unmarshal(b []byte) error {
41
+	return xxx_messageInfo_Stack.Unmarshal(m, b)
42
+}
43
+func (m *Stack) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
44
+	return xxx_messageInfo_Stack.Marshal(b, m, deterministic)
45
+}
46
+func (m *Stack) XXX_Merge(src proto.Message) {
47
+	xxx_messageInfo_Stack.Merge(m, src)
48
+}
49
+func (m *Stack) XXX_Size() int {
50
+	return xxx_messageInfo_Stack.Size(m)
51
+}
52
+func (m *Stack) XXX_DiscardUnknown() {
53
+	xxx_messageInfo_Stack.DiscardUnknown(m)
54
+}
55
+
56
+var xxx_messageInfo_Stack proto.InternalMessageInfo
57
+
58
+func (m *Stack) GetFrames() []*Frame {
59
+	if m != nil {
60
+		return m.Frames
61
+	}
62
+	return nil
63
+}
64
+
65
+func (m *Stack) GetCmdline() []string {
66
+	if m != nil {
67
+		return m.Cmdline
68
+	}
69
+	return nil
70
+}
71
+
72
+func (m *Stack) GetPid() int32 {
73
+	if m != nil {
74
+		return m.Pid
75
+	}
76
+	return 0
77
+}
78
+
79
+func (m *Stack) GetVersion() string {
80
+	if m != nil {
81
+		return m.Version
82
+	}
83
+	return ""
84
+}
85
+
86
+func (m *Stack) GetRevision() string {
87
+	if m != nil {
88
+		return m.Revision
89
+	}
90
+	return ""
91
+}
92
+
93
+type Frame struct {
94
+	Name                 string   `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"`
95
+	File                 string   `protobuf:"bytes,2,opt,name=File,proto3" json:"File,omitempty"`
96
+	Line                 int32    `protobuf:"varint,3,opt,name=Line,proto3" json:"Line,omitempty"`
97
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
98
+	XXX_unrecognized     []byte   `json:"-"`
99
+	XXX_sizecache        int32    `json:"-"`
100
+}
101
+
102
+func (m *Frame) Reset()         { *m = Frame{} }
103
+func (m *Frame) String() string { return proto.CompactTextString(m) }
104
+func (*Frame) ProtoMessage()    {}
105
+func (*Frame) Descriptor() ([]byte, []int) {
106
+	return fileDescriptor_b44c07feb2ca0a5a, []int{1}
107
+}
108
+
109
+func (m *Frame) XXX_Unmarshal(b []byte) error {
110
+	return xxx_messageInfo_Frame.Unmarshal(m, b)
111
+}
112
+func (m *Frame) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
113
+	return xxx_messageInfo_Frame.Marshal(b, m, deterministic)
114
+}
115
+func (m *Frame) XXX_Merge(src proto.Message) {
116
+	xxx_messageInfo_Frame.Merge(m, src)
117
+}
118
+func (m *Frame) XXX_Size() int {
119
+	return xxx_messageInfo_Frame.Size(m)
120
+}
121
+func (m *Frame) XXX_DiscardUnknown() {
122
+	xxx_messageInfo_Frame.DiscardUnknown(m)
123
+}
124
+
125
+var xxx_messageInfo_Frame proto.InternalMessageInfo
126
+
127
+func (m *Frame) GetName() string {
128
+	if m != nil {
129
+		return m.Name
130
+	}
131
+	return ""
132
+}
133
+
134
+func (m *Frame) GetFile() string {
135
+	if m != nil {
136
+		return m.File
137
+	}
138
+	return ""
139
+}
140
+
141
+func (m *Frame) GetLine() int32 {
142
+	if m != nil {
143
+		return m.Line
144
+	}
145
+	return 0
146
+}
147
+
148
+func init() {
149
+	proto.RegisterType((*Stack)(nil), "stack.Stack")
150
+	proto.RegisterType((*Frame)(nil), "stack.Frame")
151
+}
152
+
153
+func init() { proto.RegisterFile("stack.proto", fileDescriptor_b44c07feb2ca0a5a) }
154
+
155
+var fileDescriptor_b44c07feb2ca0a5a = []byte{
156
+	// 185 bytes of a gzipped FileDescriptorProto
157
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x3c, 0x8f, 0x3d, 0xce, 0x82, 0x40,
158
+	0x10, 0x86, 0xb3, 0xdf, 0xb2, 0x7c, 0x3a, 0x58, 0x98, 0xa9, 0x36, 0x56, 0x1b, 0x62, 0x41, 0x45,
159
+	0xa1, 0x47, 0x30, 0xa1, 0x32, 0x16, 0x78, 0x02, 0x84, 0x35, 0xd9, 0xc8, 0x5f, 0x76, 0x09, 0xd7,
160
+	0xf0, 0xca, 0x66, 0x06, 0xb4, 0x7b, 0xde, 0x9f, 0xe4, 0x9d, 0x81, 0x24, 0x4c, 0x55, 0xfd, 0xca,
161
+	0x47, 0x3f, 0x4c, 0x03, 0x2a, 0x16, 0xe9, 0x5b, 0x80, 0xba, 0x13, 0xe1, 0x11, 0xe2, 0xa7, 0xaf,
162
+	0x3a, 0x1b, 0xb4, 0x30, 0x32, 0x4b, 0x4e, 0xbb, 0x7c, 0xa9, 0x17, 0x64, 0x96, 0x6b, 0x86, 0x1a,
163
+	0xfe, 0xeb, 0xae, 0x69, 0x5d, 0x6f, 0xf5, 0x9f, 0x91, 0xd9, 0xb6, 0xfc, 0x4a, 0xdc, 0x83, 0x1c,
164
+	0x5d, 0xa3, 0xa5, 0x11, 0x99, 0x2a, 0x09, 0xa9, 0x3b, 0x5b, 0x1f, 0xdc, 0xd0, 0xeb, 0xc8, 0x08,
165
+	0xea, 0xae, 0x12, 0x0f, 0xb0, 0xf1, 0x76, 0x76, 0x1c, 0x29, 0x8e, 0x7e, 0x3a, 0xbd, 0x80, 0xe2,
166
+	0x49, 0x44, 0x88, 0x6e, 0x55, 0x67, 0xb5, 0xe0, 0x02, 0x33, 0x79, 0x85, 0x6b, 0x69, 0x9b, 0x3d,
167
+	0x62, 0xf2, 0xae, 0x74, 0xcf, 0xb2, 0xcc, 0xfc, 0x88, 0xf9, 0xc9, 0xf3, 0x27, 0x00, 0x00, 0xff,
168
+	0xff, 0xfd, 0x2c, 0xbb, 0xfb, 0xf3, 0x00, 0x00, 0x00,
169
+}
0 170
new file mode 100644
... ...
@@ -0,0 +1,17 @@
0
+syntax = "proto3";
1
+
2
+package stack;
3
+
4
+message Stack {
5
+    repeated Frame frames = 1;
6
+    repeated string cmdline = 2;
7
+    int32 pid = 3;
8
+    string version = 4;
9
+    string revision = 5;
10
+}
11
+
12
+message Frame {
13
+    string Name = 1;
14
+    string File = 2;
15
+    int32 Line = 3;
16
+}
0 17
\ No newline at end of file