Skip to content

Commit c2215ce

Browse files
committed
cli/command/image: move build-context detection to build
Removes direct imports of github.com/docker/docker/builder in the image package, to be moved later. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
1 parent d8089e7 commit c2215ce

2 files changed

Lines changed: 67 additions & 25 deletions

File tree

cli/command/image/build.go

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import (
2828
buildtypes "github.com/docker/docker/api/types/build"
2929
"github.com/docker/docker/api/types/container"
3030
registrytypes "github.com/docker/docker/api/types/registry"
31-
"github.com/docker/docker/builder/remotecontext/urlutil"
3231
"github.com/docker/docker/pkg/progress"
3332
"github.com/docker/docker/pkg/streamformatter"
3433
"github.com/moby/go-archive"
@@ -189,21 +188,24 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
189188
buildCtx io.ReadCloser
190189
dockerfileCtx io.ReadCloser
191190
contextDir string
192-
tempDir string
193191
relDockerfile string
194192
progBuff io.Writer
195193
buildBuff io.Writer
196194
remote string
197195
)
198196

197+
contextType, err := build.DetectContextType(options.context)
198+
if err != nil {
199+
return err
200+
}
201+
199202
if options.dockerfileFromStdin() {
200-
if options.contextFromStdin() {
203+
if contextType == build.ContextTypeStdIn {
201204
return errors.New("invalid argument: can't use stdin for both build context and dockerfile")
202205
}
203206
dockerfileCtx = dockerCli.In()
204207
}
205208

206-
specifiedContext := options.context
207209
progBuff = dockerCli.Out()
208210
buildBuff = dockerCli.Out()
209211
if options.quiet {
@@ -217,38 +219,43 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
217219
}
218220
}
219221

220-
switch {
221-
case options.contextFromStdin():
222+
switch contextType {
223+
case build.ContextTypeStdIn:
222224
// buildCtx is tar archive. if stdin was dockerfile then it is wrapped
223225
buildCtx, relDockerfile, err = build.GetContextFromReader(dockerCli.In(), options.dockerfileName)
224-
case isLocalDir(specifiedContext):
225-
contextDir, relDockerfile, err = build.GetContextFromLocalDir(specifiedContext, options.dockerfileName)
226-
if err == nil && strings.HasPrefix(relDockerfile, ".."+string(filepath.Separator)) {
226+
if err != nil {
227+
return fmt.Errorf("unable to prepare context from STDIN: %w", err)
228+
}
229+
case build.ContextTypeLocal:
230+
contextDir, relDockerfile, err = build.GetContextFromLocalDir(options.context, options.dockerfileName)
231+
if err != nil {
232+
return errors.Errorf("unable to prepare context: %s", err)
233+
}
234+
if strings.HasPrefix(relDockerfile, ".."+string(filepath.Separator)) {
227235
// Dockerfile is outside of build-context; read the Dockerfile and pass it as dockerfileCtx
228236
dockerfileCtx, err = os.Open(options.dockerfileName)
229237
if err != nil {
230238
return errors.Errorf("unable to open Dockerfile: %v", err)
231239
}
232240
defer dockerfileCtx.Close()
233241
}
234-
case urlutil.IsGitURL(specifiedContext):
235-
tempDir, relDockerfile, err = build.GetContextFromGitURL(specifiedContext, options.dockerfileName)
236-
case urlutil.IsURL(specifiedContext):
237-
buildCtx, relDockerfile, err = build.GetContextFromURL(progBuff, specifiedContext, options.dockerfileName)
238-
default:
239-
return errors.Errorf("unable to prepare context: path %q not found", specifiedContext)
240-
}
241-
242-
if err != nil {
243-
if options.quiet && urlutil.IsURL(specifiedContext) {
244-
_, _ = fmt.Fprintln(dockerCli.Err(), progBuff)
242+
case build.ContextTypeGit:
243+
var tempDir string
244+
tempDir, relDockerfile, err = build.GetContextFromGitURL(options.context, options.dockerfileName)
245+
if err != nil {
246+
return errors.Errorf("unable to prepare context: %s", err)
245247
}
246-
return errors.Errorf("unable to prepare context: %s", err)
247-
}
248-
249-
if tempDir != "" {
250-
defer os.RemoveAll(tempDir)
248+
defer func() {
249+
_ = os.RemoveAll(tempDir)
250+
}()
251251
contextDir = tempDir
252+
case build.ContextTypeRemote:
253+
buildCtx, relDockerfile, err = build.GetContextFromURL(progBuff, options.context, options.dockerfileName)
254+
if err != nil && options.quiet {
255+
_, _ = fmt.Fprintln(dockerCli.Err(), progBuff)
256+
}
257+
default:
258+
return errors.Errorf("unable to prepare context: path %q not found", options.context)
252259
}
253260

254261
// read from a directory into tar archive
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package build
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/docker/docker/builder/remotecontext/urlutil"
8+
)
9+
10+
const (
11+
ContextTypeStdIn = "stdin" // ContextTypeStdIn indicates that the build-context is a TAR archive passed through STDIN.
12+
ContextTypeLocal = "local" // ContextTypeLocal indicates that the build-context is a local directory.
13+
ContextTypeRemote = "remote" // ContextTypeRemote indicates that the build-context is a remote URL.
14+
ContextTypeGit = "git" // ContextTypeGit indicates that the build-context is a GIT URL.
15+
)
16+
17+
func DetectContextType(specifiedContext string) (string, error) {
18+
switch {
19+
case specifiedContext == "-":
20+
return ContextTypeStdIn, nil
21+
case isLocalDir(specifiedContext):
22+
return ContextTypeLocal, nil
23+
case urlutil.IsGitURL(specifiedContext):
24+
return ContextTypeGit, nil
25+
case urlutil.IsURL(specifiedContext):
26+
return ContextTypeRemote, nil
27+
default:
28+
return "", fmt.Errorf("unable to prepare context: path %q not found", specifiedContext)
29+
}
30+
}
31+
32+
func isLocalDir(c string) bool {
33+
_, err := os.Stat(c)
34+
return err == nil
35+
}

0 commit comments

Comments
 (0)