Add tests and documentation for this new feature.
Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
| ... | ... |
@@ -131,7 +131,11 @@ or |
| 131 | 131 |
interactively, as with the following command: **docker run -t -i image bash** |
| 132 | 132 |
|
| 133 | 133 |
**ADD** |
| 134 |
- --**ADD <src>... <dest>** The ADD instruction copies new files, directories |
|
| 134 |
+ --ADD has two forms: |
|
| 135 |
+ **ADD <src>... <dest>** |
|
| 136 |
+ **ADD ["<src>"... "<dest>"]** This form is required for paths containing |
|
| 137 |
+ whitespace. |
|
| 138 |
+ The ADD instruction copies new files, directories |
|
| 135 | 139 |
or remote file URLs to the filesystem of the container at path <dest>. |
| 136 | 140 |
Mutliple <src> resources may be specified but if they are files or directories |
| 137 | 141 |
then they must be relative to the source directory that is being built |
| ... | ... |
@@ -141,7 +145,11 @@ or |
| 141 | 141 |
and gid of 0. |
| 142 | 142 |
|
| 143 | 143 |
**COPY** |
| 144 |
- --**COPY <src> <dest>** The COPY instruction copies new files from <src> and |
|
| 144 |
+ --COPY has two forms: |
|
| 145 |
+ **COPY <src>... <dest>** |
|
| 146 |
+ **COPY ["<src>"... "<dest>"]** This form is required for paths containing |
|
| 147 |
+ whitespace. |
|
| 148 |
+ The COPY instruction copies new files from <src> and |
|
| 145 | 149 |
adds them to the filesystem of the container at path <dest>. The <src> must be |
| 146 | 150 |
the path to a file or directory relative to the source directory that is |
| 147 | 151 |
being built (the context of the build) or a remote file URL. The `<dest>` is an |
| ... | ... |
@@ -381,7 +381,11 @@ change them using `docker run --env <key>=<value>`. |
| 381 | 381 |
|
| 382 | 382 |
## ADD |
| 383 | 383 |
|
| 384 |
- ADD <src>... <dest> |
|
| 384 |
+ADD has two forms: |
|
| 385 |
+ |
|
| 386 |
+- `ADD <src>... <dest>` |
|
| 387 |
+- `ADD ["<src>"... "<dest>"]` (this form is required for paths containing |
|
| 388 |
+whitespace) |
|
| 385 | 389 |
|
| 386 | 390 |
The `ADD` instruction copies new files, directories or remote file URLs from `<src>` |
| 387 | 391 |
and adds them to the filesystem of the container at the path `<dest>`. |
| ... | ... |
@@ -481,7 +485,11 @@ The copy obeys the following rules: |
| 481 | 481 |
|
| 482 | 482 |
## COPY |
| 483 | 483 |
|
| 484 |
- COPY <src>... <dest> |
|
| 484 |
+COPY has two forms: |
|
| 485 |
+ |
|
| 486 |
+- `COPY <src>... <dest>` |
|
| 487 |
+- `COPY ["<src>"... "<dest>"]` (this form is required for paths containing |
|
| 488 |
+whitespace) |
|
| 485 | 489 |
|
| 486 | 490 |
The `COPY` instruction copies new files or directories from `<src>` |
| 487 | 491 |
and adds them to the filesystem of the container at the path `<dest>`. |
| ... | ... |
@@ -762,7 +762,7 @@ RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio'
|
| 762 | 762 |
if _, err := buildImageFromContext(name, ctx, true); err != nil {
|
| 763 | 763 |
t.Fatal(err) |
| 764 | 764 |
} |
| 765 |
- logDone("build - mulitple file copy/add tests")
|
|
| 765 |
+ logDone("build - multiple file copy/add tests")
|
|
| 766 | 766 |
} |
| 767 | 767 |
|
| 768 | 768 |
func TestBuildAddMultipleFilesToFile(t *testing.T) {
|
| ... | ... |
@@ -770,7 +770,7 @@ func TestBuildAddMultipleFilesToFile(t *testing.T) {
|
| 770 | 770 |
defer deleteImages(name) |
| 771 | 771 |
ctx, err := fakeContext(`FROM scratch |
| 772 | 772 |
ADD file1.txt file2.txt test |
| 773 |
- `, |
|
| 773 |
+ `, |
|
| 774 | 774 |
map[string]string{
|
| 775 | 775 |
"file1.txt": "test1", |
| 776 | 776 |
"file2.txt": "test1", |
| ... | ... |
@@ -782,18 +782,41 @@ func TestBuildAddMultipleFilesToFile(t *testing.T) {
|
| 782 | 782 |
|
| 783 | 783 |
expected := "When using ADD with more than one source file, the destination must be a directory and end with a /" |
| 784 | 784 |
if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
|
| 785 |
- t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
|
|
| 785 |
+ t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
|
|
| 786 | 786 |
} |
| 787 | 787 |
|
| 788 | 788 |
logDone("build - multiple add files to file")
|
| 789 | 789 |
} |
| 790 | 790 |
|
| 791 |
+func TestBuildJSONAddMultipleFilesToFile(t *testing.T) {
|
|
| 792 |
+ name := "testjsonaddmultiplefilestofile" |
|
| 793 |
+ defer deleteImages(name) |
|
| 794 |
+ ctx, err := fakeContext(`FROM scratch |
|
| 795 |
+ ADD ["file1.txt", "file2.txt", "test"] |
|
| 796 |
+ `, |
|
| 797 |
+ map[string]string{
|
|
| 798 |
+ "file1.txt": "test1", |
|
| 799 |
+ "file2.txt": "test1", |
|
| 800 |
+ }) |
|
| 801 |
+ defer ctx.Close() |
|
| 802 |
+ if err != nil {
|
|
| 803 |
+ t.Fatal(err) |
|
| 804 |
+ } |
|
| 805 |
+ |
|
| 806 |
+ expected := "When using ADD with more than one source file, the destination must be a directory and end with a /" |
|
| 807 |
+ if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
|
|
| 808 |
+ t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
|
|
| 809 |
+ } |
|
| 810 |
+ |
|
| 811 |
+ logDone("build - multiple add files to file json syntax")
|
|
| 812 |
+} |
|
| 813 |
+ |
|
| 791 | 814 |
func TestBuildAddMultipleFilesToFileWild(t *testing.T) {
|
| 792 | 815 |
name := "testaddmultiplefilestofilewild" |
| 793 | 816 |
defer deleteImages(name) |
| 794 | 817 |
ctx, err := fakeContext(`FROM scratch |
| 795 | 818 |
ADD file*.txt test |
| 796 |
- `, |
|
| 819 |
+ `, |
|
| 797 | 820 |
map[string]string{
|
| 798 | 821 |
"file1.txt": "test1", |
| 799 | 822 |
"file2.txt": "test1", |
| ... | ... |
@@ -805,18 +828,41 @@ func TestBuildAddMultipleFilesToFileWild(t *testing.T) {
|
| 805 | 805 |
|
| 806 | 806 |
expected := "When using ADD with more than one source file, the destination must be a directory and end with a /" |
| 807 | 807 |
if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
|
| 808 |
- t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
|
|
| 808 |
+ t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
|
|
| 809 | 809 |
} |
| 810 | 810 |
|
| 811 | 811 |
logDone("build - multiple add files to file wild")
|
| 812 | 812 |
} |
| 813 | 813 |
|
| 814 |
+func TestBuildJSONAddMultipleFilesToFileWild(t *testing.T) {
|
|
| 815 |
+ name := "testjsonaddmultiplefilestofilewild" |
|
| 816 |
+ defer deleteImages(name) |
|
| 817 |
+ ctx, err := fakeContext(`FROM scratch |
|
| 818 |
+ ADD ["file*.txt", "test"] |
|
| 819 |
+ `, |
|
| 820 |
+ map[string]string{
|
|
| 821 |
+ "file1.txt": "test1", |
|
| 822 |
+ "file2.txt": "test1", |
|
| 823 |
+ }) |
|
| 824 |
+ defer ctx.Close() |
|
| 825 |
+ if err != nil {
|
|
| 826 |
+ t.Fatal(err) |
|
| 827 |
+ } |
|
| 828 |
+ |
|
| 829 |
+ expected := "When using ADD with more than one source file, the destination must be a directory and end with a /" |
|
| 830 |
+ if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
|
|
| 831 |
+ t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
|
|
| 832 |
+ } |
|
| 833 |
+ |
|
| 834 |
+ logDone("build - multiple add files to file wild json syntax")
|
|
| 835 |
+} |
|
| 836 |
+ |
|
| 814 | 837 |
func TestBuildCopyMultipleFilesToFile(t *testing.T) {
|
| 815 | 838 |
name := "testcopymultiplefilestofile" |
| 816 | 839 |
defer deleteImages(name) |
| 817 | 840 |
ctx, err := fakeContext(`FROM scratch |
| 818 | 841 |
COPY file1.txt file2.txt test |
| 819 |
- `, |
|
| 842 |
+ `, |
|
| 820 | 843 |
map[string]string{
|
| 821 | 844 |
"file1.txt": "test1", |
| 822 | 845 |
"file2.txt": "test1", |
| ... | ... |
@@ -828,12 +874,35 @@ func TestBuildCopyMultipleFilesToFile(t *testing.T) {
|
| 828 | 828 |
|
| 829 | 829 |
expected := "When using COPY with more than one source file, the destination must be a directory and end with a /" |
| 830 | 830 |
if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
|
| 831 |
- t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
|
|
| 831 |
+ t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
|
|
| 832 | 832 |
} |
| 833 | 833 |
|
| 834 | 834 |
logDone("build - multiple copy files to file")
|
| 835 | 835 |
} |
| 836 | 836 |
|
| 837 |
+func TestBuildJSONCopyMultipleFilesToFile(t *testing.T) {
|
|
| 838 |
+ name := "testjsoncopymultiplefilestofile" |
|
| 839 |
+ defer deleteImages(name) |
|
| 840 |
+ ctx, err := fakeContext(`FROM scratch |
|
| 841 |
+ COPY ["file1.txt", "file2.txt", "test"] |
|
| 842 |
+ `, |
|
| 843 |
+ map[string]string{
|
|
| 844 |
+ "file1.txt": "test1", |
|
| 845 |
+ "file2.txt": "test1", |
|
| 846 |
+ }) |
|
| 847 |
+ defer ctx.Close() |
|
| 848 |
+ if err != nil {
|
|
| 849 |
+ t.Fatal(err) |
|
| 850 |
+ } |
|
| 851 |
+ |
|
| 852 |
+ expected := "When using COPY with more than one source file, the destination must be a directory and end with a /" |
|
| 853 |
+ if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
|
|
| 854 |
+ t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
|
|
| 855 |
+ } |
|
| 856 |
+ |
|
| 857 |
+ logDone("build - multiple copy files to file json syntax")
|
|
| 858 |
+} |
|
| 859 |
+ |
|
| 837 | 860 |
func TestBuildAddFileWithWhitespace(t *testing.T) {
|
| 838 | 861 |
name := "testaddfilewithwhitespace" |
| 839 | 862 |
defer deleteImages(name) |
| ... | ... |
@@ -913,7 +982,7 @@ func TestBuildAddMultipleFilesToFileWithWhitespace(t *testing.T) {
|
| 913 | 913 |
defer deleteImages(name) |
| 914 | 914 |
ctx, err := fakeContext(`FROM busybox |
| 915 | 915 |
ADD [ "test file1", "test file2", "test" ] |
| 916 |
- `, |
|
| 916 |
+ `, |
|
| 917 | 917 |
map[string]string{
|
| 918 | 918 |
"test file1": "test1", |
| 919 | 919 |
"test file2": "test2", |
| ... | ... |
@@ -925,7 +994,7 @@ func TestBuildAddMultipleFilesToFileWithWhitespace(t *testing.T) {
|
| 925 | 925 |
|
| 926 | 926 |
expected := "When using ADD with more than one source file, the destination must be a directory and end with a /" |
| 927 | 927 |
if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
|
| 928 |
- t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
|
|
| 928 |
+ t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
|
|
| 929 | 929 |
} |
| 930 | 930 |
|
| 931 | 931 |
logDone("build - multiple add files to file with whitespace")
|
| ... | ... |
@@ -948,7 +1017,7 @@ func TestBuildCopyMultipleFilesToFileWithWhitespace(t *testing.T) {
|
| 948 | 948 |
|
| 949 | 949 |
expected := "When using COPY with more than one source file, the destination must be a directory and end with a /" |
| 950 | 950 |
if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
|
| 951 |
- t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
|
|
| 951 |
+ t.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
|
|
| 952 | 952 |
} |
| 953 | 953 |
|
| 954 | 954 |
logDone("build - multiple copy files to file with whitespace")
|