diff --git a/builder.go b/builder.go index 5776f481..51ce6d2a 100644 --- a/builder.go +++ b/builder.go @@ -30,12 +30,29 @@ type Copy struct { Download bool // If set, the owner:group for the destination. This value is passed // to the executor for handling. - Chown string - Chmod string + Chown string + Chmod string + // If set, a checksum which the source must match, or be rejected. Checksum string // Additional files which need to be created by executor for this // instruction. Files []File + // If set, when the source is a URL for a remote Git repository, + // refrain from stripping out the .git subdirectory after cloning it. + KeepGitDir bool + // If set, instead of adding these items to the rootfs and picking them + // up as part of a subsequent diff generation, build an archive of them + // and include it as an independent layer. + Link bool + // If set, preserve leading directories in the paths of items being + // copied, relative to either the top of the build context, or to the + // "pivot point", a location in the source path marked by a path + // component named "." (i.e., where "/./" occurs in the path). + Parents bool + // Exclusion patterns, a la .dockerignore, relative to either the top + // of a directory tree being copied, or the "pivot point", a location + // in the source path marked by a path component named ".". + Excludes []string } // File defines if any additional file needs to be created diff --git a/dispatchers.go b/dispatchers.go index 137d83d8..ec929283 100644 --- a/dispatchers.go +++ b/dispatchers.go @@ -168,6 +168,9 @@ func add(b *Builder, args []string, attributes map[string]bool, flagArgs []strin var chown string var chmod string var checksum string + var keepGitDir bool + var link bool + var excludes []string last := len(args) - 1 dest := makeAbsolute(args[last], b.RunConfig.WorkingDir) filteredUserArgs := make(map[string]string) @@ -199,8 +202,22 @@ func add(b *Builder, args []string, attributes map[string]bool, flagArgs []strin if checksum == "" { return fmt.Errorf("no value specified for --checksum=") } + case arg == "--link", arg == "--link=true": + link = true + case arg == "--link=false": + link = false + case arg == "--keep-git-dir", arg == "--keep-git-dir=true": + keepGitDir = true + case arg == "--keep-git-dir=false": + keepGitDir = false + case strings.HasPrefix(arg, "--exclude="): + exclude := strings.TrimPrefix(arg, "--exclude=") + if exclude == "" { + return fmt.Errorf("no value specified for --exclude=") + } + excludes = append(excludes, exclude) default: - return fmt.Errorf("ADD only supports the --chmod=, --chown=, and --checksum= flags") + return fmt.Errorf("ADD only supports the --chmod=, --chown=, --checksum=, --link, --keep-git-dir, and --exclude= flags") } } files, err := processHereDocs(buildkitcommand.Add, original, heredocs, userArgs) @@ -208,13 +225,17 @@ func add(b *Builder, args []string, attributes map[string]bool, flagArgs []strin return err } b.PendingCopies = append(b.PendingCopies, Copy{ - Src: args[0:last], - Dest: dest, - Download: true, - Chown: chown, - Chmod: chmod, - Checksum: checksum, - Files: files}) + Src: args[0:last], + Dest: dest, + Download: true, + Chown: chown, + Chmod: chmod, + Checksum: checksum, + Files: files, + KeepGitDir: keepGitDir, + Link: link, + Excludes: excludes, + }) return nil } @@ -230,6 +251,9 @@ func dispatchCopy(b *Builder, args []string, attributes map[string]bool, flagArg var chown string var chmod string var from string + var link bool + var parents bool + var excludes []string userArgs := mergeEnv(envMapAsSlice(b.Args), b.Env) for _, a := range flagArgs { arg, err := ProcessWord(a, userArgs) @@ -253,15 +277,40 @@ func dispatchCopy(b *Builder, args []string, attributes map[string]bool, flagArg if from == "" { return fmt.Errorf("no value specified for --from=") } + case arg == "--link", arg == "--link=true": + link = true + case arg == "--link=false": + link = false + case arg == "--parents", arg == "--parents=true": + parents = true + case arg == "--parents=false": + parents = false + case strings.HasPrefix(arg, "--exclude="): + exclude := strings.TrimPrefix(arg, "--exclude=") + if exclude == "" { + return fmt.Errorf("no value specified for --exclude=") + } + excludes = append(excludes, exclude) default: - return fmt.Errorf("COPY only supports the --chmod= --chown= and the --from= flags") + return fmt.Errorf("COPY only supports the --chmod=, --chown=, --from=, --link, --parents, and --exclude= flags") } } files, err := processHereDocs(buildkitcommand.Copy, original, heredocs, userArgs) if err != nil { return err } - b.PendingCopies = append(b.PendingCopies, Copy{From: from, Src: args[0:last], Dest: dest, Download: false, Chown: chown, Chmod: chmod, Files: files}) + b.PendingCopies = append(b.PendingCopies, Copy{ + From: from, + Src: args[0:last], + Dest: dest, + Download: false, + Chown: chown, + Chmod: chmod, + Files: files, + Link: link, + Parents: parents, + Excludes: excludes, + }) return nil } @@ -768,6 +817,8 @@ func shell(b *Builder, args []string, attributes map[string]bool, flagArgs []str return nil } +// checkChmodConversion makes sure that the argument to a --chmod= flag for +// COPY or ADD is an octal number func checkChmodConversion(chmod string) error { _, err := strconv.ParseUint(chmod, 8, 32) if err != nil { diff --git a/dockerclient/client.go b/dockerclient/client.go index 7e9f3568..058dedd7 100644 --- a/dockerclient/client.go +++ b/dockerclient/client.go @@ -882,6 +882,18 @@ func (e *ClientExecutor) Copy(excludes []string, copies ...imagebuilder.Copy) er if copy.Checksum != "" { return fmt.Errorf("ADD --checksum not supported") } + if copy.Link { + return fmt.Errorf("ADD or COPY --link not supported") + } + if copy.Parents { + return fmt.Errorf("COPY --parents not supported") + } + if copy.KeepGitDir { + return fmt.Errorf("ADD --keep-git-dir not supported") + } + if len(copy.Excludes) > 0 { + return fmt.Errorf("ADD or COPY --exclude not supported") + } if len(copy.Files) > 0 { return fmt.Errorf("Heredoc syntax is not supported") }