Quellcode durchsuchen

Support whitespaces in ADD and COPY continued

Add tests and documentation for this new feature.

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
Arnaud Porterie vor 10 Jahren
Ursprung
Commit
cf455017e0
3 geänderte Dateien mit 99 neuen und 14 gelöschten Zeilen
  1. 10 2
      docs/man/Dockerfile.5.md
  2. 10 2
      docs/sources/reference/builder.md
  3. 79 10
      integration-cli/docker_cli_build_test.go

+ 10 - 2
docs/man/Dockerfile.5.md

@@ -131,7 +131,11 @@ or
  interactively, as with the following command: **docker run -t -i image bash**
  interactively, as with the following command: **docker run -t -i image bash**
 
 
 **ADD**
 **ADD**
- --**ADD <src>... <dest>** The ADD instruction copies new files, directories
+ --ADD has two forms:
+ **ADD <src>... <dest>**
+ **ADD ["<src>"... "<dest>"]** This form is required for paths containing
+ whitespace.
+ The ADD instruction copies new files, directories
  or remote file URLs to the filesystem of the container at path <dest>.
  or remote file URLs to the filesystem of the container at path <dest>.
  Mutliple <src> resources may be specified but if they are files or directories
  Mutliple <src> resources may be specified but if they are files or directories
  then they must be relative to the source directory that is being built
  then they must be relative to the source directory that is being built
@@ -141,7 +145,11 @@ or
  and gid of 0.
  and gid of 0.
 
 
 **COPY**
 **COPY**
- --**COPY <src> <dest>** The COPY instruction copies new files from <src> and
+ --COPY has two forms:
+ **COPY <src>... <dest>**
+ **COPY ["<src>"... "<dest>"]** This form is required for paths containing
+ whitespace.
+ The COPY instruction copies new files from <src> and
  adds them to the filesystem of the container at path <dest>. The <src> must be
  adds them to the filesystem of the container at path <dest>. The <src> must be
  the path to a file or directory relative to the source directory that is
  the path to a file or directory relative to the source directory that is
  being built (the context of the build) or a remote file URL. The `<dest>` is an
  being built (the context of the build) or a remote file URL. The `<dest>` is an

+ 10 - 2
docs/sources/reference/builder.md

@@ -381,7 +381,11 @@ change them using `docker run --env <key>=<value>`.
 
 
 ## ADD
 ## ADD
 
 
-    ADD <src>... <dest>
+ADD has two forms:
+
+- `ADD <src>... <dest>`
+- `ADD ["<src>"... "<dest>"]` (this form is required for paths containing
+whitespace)
 
 
 The `ADD` instruction copies new files, directories or remote file URLs from `<src>`
 The `ADD` instruction copies new files, directories or remote file URLs from `<src>`
 and adds them to the filesystem of the container at the path `<dest>`.  
 and adds them to the filesystem of the container at the path `<dest>`.  
@@ -481,7 +485,11 @@ The copy obeys the following rules:
 
 
 ## COPY
 ## COPY
 
 
-    COPY <src>... <dest>
+COPY has two forms:
+
+- `COPY <src>... <dest>`
+- `COPY ["<src>"... "<dest>"]` (this form is required for paths containing
+whitespace)
 
 
 The `COPY` instruction copies new files or directories from `<src>`
 The `COPY` instruction copies new files or directories from `<src>`
 and adds them to the filesystem of the container at the path `<dest>`.
 and adds them to the filesystem of the container at the path `<dest>`.

+ 79 - 10
integration-cli/docker_cli_build_test.go

@@ -762,7 +762,7 @@ RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio'
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	logDone("build - mulitple file copy/add tests")
+	logDone("build - multiple file copy/add tests")
 }
 }
 
 
 func TestBuildAddMultipleFilesToFile(t *testing.T) {
 func TestBuildAddMultipleFilesToFile(t *testing.T) {
@@ -770,7 +770,7 @@ func TestBuildAddMultipleFilesToFile(t *testing.T) {
 	defer deleteImages(name)
 	defer deleteImages(name)
 	ctx, err := fakeContext(`FROM scratch
 	ctx, err := fakeContext(`FROM scratch
 	ADD file1.txt file2.txt test
 	ADD file1.txt file2.txt test
-        `,
+	`,
 		map[string]string{
 		map[string]string{
 			"file1.txt": "test1",
 			"file1.txt": "test1",
 			"file2.txt": "test1",
 			"file2.txt": "test1",
@@ -782,18 +782,41 @@ func TestBuildAddMultipleFilesToFile(t *testing.T) {
 
 
 	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
 	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
-		t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
+		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
 	}
 	}
 
 
 	logDone("build - multiple add files to file")
 	logDone("build - multiple add files to file")
 }
 }
 
 
+func TestBuildJSONAddMultipleFilesToFile(t *testing.T) {
+	name := "testjsonaddmultiplefilestofile"
+	defer deleteImages(name)
+	ctx, err := fakeContext(`FROM scratch
+	ADD ["file1.txt", "file2.txt", "test"]
+	`,
+		map[string]string{
+			"file1.txt": "test1",
+			"file2.txt": "test1",
+		})
+	defer ctx.Close()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
+	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
+		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
+	}
+
+	logDone("build - multiple add files to file json syntax")
+}
+
 func TestBuildAddMultipleFilesToFileWild(t *testing.T) {
 func TestBuildAddMultipleFilesToFileWild(t *testing.T) {
 	name := "testaddmultiplefilestofilewild"
 	name := "testaddmultiplefilestofilewild"
 	defer deleteImages(name)
 	defer deleteImages(name)
 	ctx, err := fakeContext(`FROM scratch
 	ctx, err := fakeContext(`FROM scratch
 	ADD file*.txt test
 	ADD file*.txt test
-        `,
+	`,
 		map[string]string{
 		map[string]string{
 			"file1.txt": "test1",
 			"file1.txt": "test1",
 			"file2.txt": "test1",
 			"file2.txt": "test1",
@@ -805,18 +828,41 @@ func TestBuildAddMultipleFilesToFileWild(t *testing.T) {
 
 
 	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
 	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
-		t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
+		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
 	}
 	}
 
 
 	logDone("build - multiple add files to file wild")
 	logDone("build - multiple add files to file wild")
 }
 }
 
 
+func TestBuildJSONAddMultipleFilesToFileWild(t *testing.T) {
+	name := "testjsonaddmultiplefilestofilewild"
+	defer deleteImages(name)
+	ctx, err := fakeContext(`FROM scratch
+	ADD ["file*.txt", "test"]
+	`,
+		map[string]string{
+			"file1.txt": "test1",
+			"file2.txt": "test1",
+		})
+	defer ctx.Close()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
+	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
+		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
+	}
+
+	logDone("build - multiple add files to file wild json syntax")
+}
+
 func TestBuildCopyMultipleFilesToFile(t *testing.T) {
 func TestBuildCopyMultipleFilesToFile(t *testing.T) {
 	name := "testcopymultiplefilestofile"
 	name := "testcopymultiplefilestofile"
 	defer deleteImages(name)
 	defer deleteImages(name)
 	ctx, err := fakeContext(`FROM scratch
 	ctx, err := fakeContext(`FROM scratch
 	COPY file1.txt file2.txt test
 	COPY file1.txt file2.txt test
-        `,
+	`,
 		map[string]string{
 		map[string]string{
 			"file1.txt": "test1",
 			"file1.txt": "test1",
 			"file2.txt": "test1",
 			"file2.txt": "test1",
@@ -828,12 +874,35 @@ func TestBuildCopyMultipleFilesToFile(t *testing.T) {
 
 
 	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
 	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
-		t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
+		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
 	}
 	}
 
 
 	logDone("build - multiple copy files to file")
 	logDone("build - multiple copy files to file")
 }
 }
 
 
+func TestBuildJSONCopyMultipleFilesToFile(t *testing.T) {
+	name := "testjsoncopymultiplefilestofile"
+	defer deleteImages(name)
+	ctx, err := fakeContext(`FROM scratch
+	COPY ["file1.txt", "file2.txt", "test"]
+	`,
+		map[string]string{
+			"file1.txt": "test1",
+			"file2.txt": "test1",
+		})
+	defer ctx.Close()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
+	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
+		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
+	}
+
+	logDone("build - multiple copy files to file json syntax")
+}
+
 func TestBuildAddFileWithWhitespace(t *testing.T) {
 func TestBuildAddFileWithWhitespace(t *testing.T) {
 	name := "testaddfilewithwhitespace"
 	name := "testaddfilewithwhitespace"
 	defer deleteImages(name)
 	defer deleteImages(name)
@@ -913,7 +982,7 @@ func TestBuildAddMultipleFilesToFileWithWhitespace(t *testing.T) {
 	defer deleteImages(name)
 	defer deleteImages(name)
 	ctx, err := fakeContext(`FROM busybox
 	ctx, err := fakeContext(`FROM busybox
 	ADD [ "test file1", "test file2", "test" ]
 	ADD [ "test file1", "test file2", "test" ]
-        `,
+    `,
 		map[string]string{
 		map[string]string{
 			"test file1": "test1",
 			"test file1": "test1",
 			"test file2": "test2",
 			"test file2": "test2",
@@ -925,7 +994,7 @@ func TestBuildAddMultipleFilesToFileWithWhitespace(t *testing.T) {
 
 
 	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
 	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
-		t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
+		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
 	}
 	}
 
 
 	logDone("build - multiple add files to file with whitespace")
 	logDone("build - multiple add files to file with whitespace")
@@ -948,7 +1017,7 @@ func TestBuildCopyMultipleFilesToFileWithWhitespace(t *testing.T) {
 
 
 	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
 	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
-		t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
+		t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
 	}
 	}
 
 
 	logDone("build - multiple copy files to file with whitespace")
 	logDone("build - multiple copy files to file with whitespace")