diff --git a/integration_tests/context/arr[0].txt b/integration_tests/context/arr[0].txt new file mode 100644 index 0000000000..b6fc4c620b --- /dev/null +++ b/integration_tests/context/arr[0].txt @@ -0,0 +1 @@ +hello \ No newline at end of file diff --git a/integration_tests/context/empty/.gitignore b/integration_tests/context/empty/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_tests/dockerfiles/Dockerfile_test_copy b/integration_tests/dockerfiles/Dockerfile_test_copy index 517f655a29..44e49e82ff 100644 --- a/integration_tests/dockerfiles/Dockerfile_test_copy +++ b/integration_tests/dockerfiles/Dockerfile_test_copy @@ -10,3 +10,5 @@ COPY . newdir COPY context/bar /baz/ COPY ["context/foo", "/tmp/foo" ] COPY context/b* /baz/ +COPY context/foo context/bar/ba? /test/ +COPY context/arr[[]0].txt /mydir/ \ No newline at end of file diff --git a/pkg/commands/copy.go b/pkg/commands/copy.go index 9b0ffaf56b..afacf57ebe 100644 --- a/pkg/commands/copy.go +++ b/pkg/commands/copy.go @@ -41,7 +41,7 @@ func (c *CopyCommand) ExecuteCommand(config *manifest.Schema2Config) error { logrus.Infof("dest: %s", dest) // Get a map of [src]:[files rooted at src] - srcMap, err := util.ResolveSources(c.cmd.SourcesAndDest, c.buildcontext, config.WorkingDir) + srcMap, err := util.ResolveSources(c.cmd.SourcesAndDest, c.buildcontext) if err != nil { return err } @@ -88,7 +88,7 @@ func (c *CopyCommand) FilesToSnapshot() []string { return c.snapshotFiles } -// Author returns some information about the command for the image config +// CreatedBy returns some information about the command for the image config func (c *CopyCommand) CreatedBy() string { return strings.Join(c.cmd.SourcesAndDest, " ") } diff --git a/pkg/util/command_util.go b/pkg/util/command_util.go index 86321c5bdf..0b92e133fd 100644 --- a/pkg/util/command_util.go +++ b/pkg/util/command_util.go @@ -19,6 +19,7 @@ package util import ( "github.com/docker/docker/builder/dockerfile/instructions" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "os" "path/filepath" "strings" @@ -38,21 +39,22 @@ func ContainsWildcards(paths []string) bool { return false } -// ResolveSources resolves the given sources if the sources contains wildcard +// ResolveSources resolves the given sources if the sources contains wildcards // It returns a map of [src]:[files rooted at src] -func ResolveSources(srcsAndDest instructions.SourcesAndDest, root, cwd string) (map[string][]string, error) { +func ResolveSources(srcsAndDest instructions.SourcesAndDest, root string) (map[string][]string, error) { srcs := srcsAndDest[:len(srcsAndDest)-1] // If sources contain wildcards, we first need to resolve them to actual paths - wildcard := ContainsWildcards(srcs) - if wildcard { - files, err := Files("", root) + if ContainsWildcards(srcs) { + logrus.Debugf("Resolving srcs %v...", srcs) + files, err := RelativeFiles("", root) if err != nil { return nil, err } - srcs, err = matchSources(srcs, files, cwd) + srcs, err = matchSources(srcs, files) if err != nil { return nil, err } + logrus.Debugf("Resolved sources to %v", srcs) } // Now, get a map of [src]:[files rooted at src] srcMap, err := SourcesToFilesMap(srcs, root) @@ -63,8 +65,8 @@ func ResolveSources(srcsAndDest instructions.SourcesAndDest, root, cwd string) ( return srcMap, IsSrcsValid(srcsAndDest, srcMap) } -// matchSources returns a map of [src]:[matching filepaths], used to resolve wildcards -func matchSources(srcs, files []string, cwd string) ([]string, error) { +// matchSources returns a list of sources that match wildcards +func matchSources(srcs, files []string) ([]string, error) { var matchedSources []string for _, src := range srcs { src = filepath.Clean(src) @@ -73,12 +75,7 @@ func matchSources(srcs, files []string, cwd string) ([]string, error) { if err != nil { return nil, err } - // Check cwd - matchedRoot, err := filepath.Match(filepath.Join(cwd, src), file) - if err != nil { - return nil, err - } - if !(matched || matchedRoot) { + if !matched { continue } matchedSources = append(matchedSources, file) @@ -91,13 +88,17 @@ func IsDestDir(path string) bool { return strings.HasSuffix(path, "/") } -// RelativeFilepath returns the relative filepath -// If source is a file: -// If dest is a dir, copy it to /cwd/dest/relpath -// If dest is a file, copy directly to /cwd/dest +func IsAbsoluteFilepath(path string) bool { + return strings.HasPrefix(path, "/") +} +// RelativeFilepath returns the relative 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 /cwd/dest/relpath +// 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) { fi, err := os.Stat(filepath.Join(buildcontext, filename)) if err != nil { @@ -115,9 +116,15 @@ func RelativeFilepath(filename, srcName, dest, cwd, buildcontext string) (string if relPath == "." && !fi.IsDir() { relPath = filepath.Base(filename) } - destPath := filepath.Join(cwd, dest, relPath) + destPath := filepath.Join(dest, relPath) + if !IsAbsoluteFilepath(dest) { + destPath = filepath.Join(cwd, destPath) + } return destPath, nil } + if IsAbsoluteFilepath(dest) { + return dest, nil + } return filepath.Join(cwd, dest), nil } @@ -126,7 +133,7 @@ func SourcesToFilesMap(srcs []string, root string) (map[string][]string, error) srcMap := make(map[string][]string) for _, src := range srcs { src = filepath.Clean(src) - files, err := Files(src, root) + files, err := RelativeFiles(src, root) if err != nil { return nil, err } diff --git a/pkg/util/command_util_test.go b/pkg/util/command_util_test.go index ed89d182f0..4585ef8c9e 100644 --- a/pkg/util/command_util_test.go +++ b/pkg/util/command_util_test.go @@ -79,7 +79,7 @@ var relativeFilepathTests = []struct { filename: "context/empty", cwd: "/dir", dest: "/empty", - expectedFilepath: "/dir/empty", + expectedFilepath: "/empty", }, { srcName: "./", @@ -121,7 +121,6 @@ func Test_RelativeFilepath(t *testing.T) { var matchSourcesTests = []struct { srcs []string files []string - cwd string expectedFiles []string }{ { @@ -135,18 +134,16 @@ var matchSourcesTests = []struct { "pkg/b/d/", "dir/", }, - cwd: "/", expectedFiles: []string{ "pkg/a", "pkg/b", - "/pkg/d", }, }, } func Test_MatchSources(t *testing.T) { for _, test := range matchSourcesTests { - actualFiles, err := matchSources(test.srcs, test.files, test.cwd) + actualFiles, err := matchSources(test.srcs, test.files) sort.Strings(actualFiles) sort.Strings(test.expectedFiles) testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedFiles, actualFiles) @@ -253,7 +250,6 @@ func Test_IsSrcsValid(t *testing.T) { var testResolveSources = []struct { srcsAndDest []string - cwd string expectedMap map[string][]string }{ { @@ -262,7 +258,6 @@ var testResolveSources = []struct { "context/b*", "dest/", }, - cwd: "/", expectedMap: map[string][]string{ "context/foo": { "context/foo", @@ -280,7 +275,7 @@ var testResolveSources = []struct { func Test_ResolveSources(t *testing.T) { for _, test := range testResolveSources { - actualMap, err := ResolveSources(test.srcsAndDest, buildContextPath, test.cwd) + actualMap, err := ResolveSources(test.srcsAndDest, buildContextPath) testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedMap, actualMap) } } diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index 3b56c6cce7..995e7c0035 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -98,8 +98,8 @@ func fileSystemWhitelist(path string) ([]string, error) { return whitelist, nil } -// Files returns a list of all files at the filepath relative to root -func Files(fp string, root string) ([]string, error) { +// RelativeFiles returns a list of all files at the filepath relative to root +func RelativeFiles(fp string, root string) ([]string, error) { var files []string fullPath := filepath.Join(root, fp) logrus.Debugf("Getting files and contents at root %s", fullPath) @@ -112,7 +112,7 @@ func Files(fp string, root string) ([]string, error) { return err } files = append(files, relPath) - return err + return nil }) return files, err } diff --git a/pkg/util/fs_util_test.go b/pkg/util/fs_util_test.go index f21c6f788e..c8ebc88cf3 100644 --- a/pkg/util/fs_util_test.go +++ b/pkg/util/fs_util_test.go @@ -114,7 +114,7 @@ var tests = []struct { }, } -func Test_Files(t *testing.T) { +func Test_RelativeFiles(t *testing.T) { for _, test := range tests { testDir, err := ioutil.TempDir("", "") if err != nil { @@ -124,7 +124,7 @@ func Test_Files(t *testing.T) { if err := testutil.SetupFiles(testDir, test.files); err != nil { t.Fatalf("err setting up files: %v", err) } - actualFiles, err := Files(test.directory, testDir) + actualFiles, err := RelativeFiles(test.directory, testDir) sort.Strings(actualFiles) sort.Strings(test.expectedFiles) testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedFiles, actualFiles)