diff --git a/pkg/commands/copy.go b/pkg/commands/copy.go index afacf57eb..cc6a21721 100644 --- a/pkg/commands/copy.go +++ b/pkg/commands/copy.go @@ -52,7 +52,7 @@ func (c *CopyCommand) ExecuteCommand(config *manifest.Schema2Config) error { if err != nil { return err } - destPath, err := util.RelativeFilepath(file, src, dest, config.WorkingDir, c.buildcontext) + destPath, err := util.DestinationFilepath(file, src, dest, config.WorkingDir, c.buildcontext) if err != nil { return err } diff --git a/pkg/util/command_util.go b/pkg/util/command_util.go index 7d34fca94..4e5da9626 100644 --- a/pkg/util/command_util.go +++ b/pkg/util/command_util.go @@ -28,12 +28,8 @@ import ( // ContainsWildcards returns true if any entry in paths contains wildcards func ContainsWildcards(paths []string) bool { for _, path := range paths { - for i := 0; i < len(path); i++ { - ch := path[i] - // These are the wildcards that correspond to filepath.Match - if ch == '*' || ch == '?' || ch == '[' { - return true - } + if strings.ContainsAny(path, "*?[") { + return true } } return false @@ -87,18 +83,14 @@ func IsDestDir(path string) bool { return strings.HasSuffix(path, "/") } -func IsAbsoluteFilepath(path string) bool { - return strings.HasPrefix(path, "/") -} - -// RelativeFilepath returns the relative filepath from the build context to the image filesystem +// DestinationFilepath returns the destination filepath from the build context to the image filesystem // If source is a file: // If dest is a dir, copy it to /dest/relpath // If dest is a file, copy directly to dest // If source is a dir: // Assume dest is also a dir, and copy to dest/relpath // If dest is not an absolute filepath, add /cwd to the beginning -func RelativeFilepath(filename, srcName, dest, cwd, buildcontext string) (string, error) { +func DestinationFilepath(filename, srcName, dest, cwd, buildcontext string) (string, error) { fi, err := os.Stat(filepath.Join(buildcontext, filename)) if err != nil { return "", err @@ -116,12 +108,12 @@ func RelativeFilepath(filename, srcName, dest, cwd, buildcontext string) (string relPath = filepath.Base(filename) } destPath := filepath.Join(dest, relPath) - if IsAbsoluteFilepath(dest) { + if filepath.IsAbs(dest) { return destPath, nil } return filepath.Join(cwd, destPath), nil } - if IsAbsoluteFilepath(dest) { + if filepath.IsAbs(dest) { return dest, nil } return filepath.Join(cwd, dest), nil @@ -145,18 +137,7 @@ func SourcesToFilesMap(srcs []string, root string) (map[string][]string, error) func IsSrcsValid(srcsAndDest instructions.SourcesAndDest, srcMap map[string][]string) error { srcs := srcsAndDest[:len(srcsAndDest)-1] dest := srcsAndDest[len(srcsAndDest)-1] - // If destination is a directory, return nil - if IsDestDir(dest) { - return nil - } - // If no wildcards and multiple sources, return error - if !ContainsWildcards(srcs) { - if len(srcs) > 1 { - return errors.New("when specifying multiple sources in a COPY command, destination must be a directory and end in '/'") - } - return nil - } - // If there are wildcards, and the destination is a file, there must be exactly one file to copy over + totalFiles := 0 for _, files := range srcMap { totalFiles += len(files) @@ -164,7 +145,18 @@ func IsSrcsValid(srcsAndDest instructions.SourcesAndDest, srcMap map[string][]st if totalFiles == 0 { return errors.New("copy failed: no source files specified") } - if totalFiles > 1 { + + if !ContainsWildcards(srcs) { + // If multiple sources and destination isn't a directory, return an error + if len(srcs) > 1 && !IsDestDir(dest) { + return errors.New("when specifying multiple sources in a COPY command, destination must be a directory and end in '/'") + } + return nil + } + + // If there are wildcards, and the destination is a file, there must be exactly one file to copy over, + // Otherwise, return an error + if !IsDestDir(dest) && totalFiles > 1 { return errors.New("when specifying multiple sources in a COPY command, destination must be a directory and end in '/'") } return nil diff --git a/pkg/util/command_util_test.go b/pkg/util/command_util_test.go index 4585ef8c9..7680dbcfd 100644 --- a/pkg/util/command_util_test.go +++ b/pkg/util/command_util_test.go @@ -24,7 +24,7 @@ import ( var buildContextPath = "../../integration_tests/" -var relativeFilepathTests = []struct { +var destinationFilepathTests = []struct { srcName string filename string dest string @@ -111,9 +111,9 @@ var relativeFilepathTests = []struct { }, } -func Test_RelativeFilepath(t *testing.T) { - for _, test := range relativeFilepathTests { - actualFilepath, err := RelativeFilepath(test.filename, test.srcName, test.dest, test.cwd, buildContextPath) +func Test_DestinationFilepath(t *testing.T) { + for _, test := range destinationFilepathTests { + actualFilepath, err := DestinationFilepath(test.filename, test.srcName, test.dest, test.cwd, buildContextPath) testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedFilepath, actualFilepath) } } @@ -161,7 +161,14 @@ var isSrcValidTests = []struct { "src2", "dest", }, - files: nil, + files: map[string][]string{ + "src1": { + "file1", + }, + "src2:": { + "file2", + }, + }, shouldErr: true, }, { @@ -170,7 +177,14 @@ var isSrcValidTests = []struct { "src2", "dest/", }, - files: nil, + files: map[string][]string{ + "src1": { + "file1", + }, + "src2:": { + "file2", + }, + }, shouldErr: false, }, { @@ -178,7 +192,14 @@ var isSrcValidTests = []struct { "src2/", "dest", }, - files: nil, + files: map[string][]string{ + "src1": { + "file1", + }, + "src2:": { + "file2", + }, + }, shouldErr: false, }, { @@ -186,7 +207,14 @@ var isSrcValidTests = []struct { "src2", "dest", }, - files: nil, + files: map[string][]string{ + "src1": { + "file1", + }, + "src2:": { + "file2", + }, + }, shouldErr: false, }, { @@ -195,7 +223,14 @@ var isSrcValidTests = []struct { "src*", "dest/", }, - files: nil, + files: map[string][]string{ + "src1": { + "file1", + }, + "src2:": { + "file2", + }, + }, shouldErr: false, }, { diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index 995e7c003..036414f9e 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -129,7 +129,7 @@ func CreateFile(path string, contents []byte, perm os.FileMode) error { baseDir := filepath.Dir(path) if _, err := os.Stat(baseDir); os.IsNotExist(err) { logrus.Debugf("baseDir %s for file %s does not exist. Creating.", baseDir, path) - if err := os.MkdirAll(baseDir, perm); err != nil { + if err := os.MkdirAll(baseDir, 0755); err != nil { return err } } @@ -140,5 +140,8 @@ func CreateFile(path string, contents []byte, perm os.FileMode) error { return err } _, err = f.Write(contents) - return err + if err != nil { + return err + } + return f.Chmod(perm) }