Signed-off-by: John Howard <jhoward@microsoft.com>
| ... | ... |
@@ -9,8 +9,6 @@ package dockerfile |
| 9 | 9 |
|
| 10 | 10 |
import ( |
| 11 | 11 |
"fmt" |
| 12 |
- "os" |
|
| 13 |
- "path/filepath" |
|
| 14 | 12 |
"regexp" |
| 15 | 13 |
"runtime" |
| 16 | 14 |
"sort" |
| ... | ... |
@@ -20,7 +18,6 @@ import ( |
| 20 | 20 |
"github.com/docker/docker/api" |
| 21 | 21 |
"github.com/docker/docker/builder" |
| 22 | 22 |
"github.com/docker/docker/pkg/signal" |
| 23 |
- "github.com/docker/docker/pkg/system" |
|
| 24 | 23 |
runconfigopts "github.com/docker/docker/runconfig/opts" |
| 25 | 24 |
"github.com/docker/engine-api/types/container" |
| 26 | 25 |
"github.com/docker/engine-api/types/strslice" |
| ... | ... |
@@ -257,45 +254,17 @@ func workdir(b *Builder, args []string, attributes map[string]bool, original str |
| 257 | 257 |
return errExactlyOneArgument("WORKDIR")
|
| 258 | 258 |
} |
| 259 | 259 |
|
| 260 |
- if err := b.flags.Parse(); err != nil {
|
|
| 260 |
+ err := b.flags.Parse() |
|
| 261 |
+ if err != nil {
|
|
| 261 | 262 |
return err |
| 262 | 263 |
} |
| 263 | 264 |
|
| 264 | 265 |
// This is from the Dockerfile and will not necessarily be in platform |
| 265 | 266 |
// specific semantics, hence ensure it is converted. |
| 266 |
- workdir := filepath.FromSlash(args[0]) |
|
| 267 |
- current := filepath.FromSlash(b.runConfig.WorkingDir) |
|
| 268 |
- if runtime.GOOS == "windows" {
|
|
| 269 |
- // Windows is a little more complicated than Linux. This code ensures |
|
| 270 |
- // we end up with a workdir which is consistent in terms of platform |
|
| 271 |
- // semantics. This means C:\somefolder, specifically in the format: |
|
| 272 |
- // UPPERCASEDriveLetter-Colon-Backslash-FolderName. We are already |
|
| 273 |
- // guaranteed that `current`, if set, is consistent. This allows us to |
|
| 274 |
- // cope correctly with any of the following in a Dockerfile: |
|
| 275 |
- // WORKDIR a --> C:\a |
|
| 276 |
- // WORKDIR c:\\foo --> C:\foo |
|
| 277 |
- // WORKDIR \\foo --> C:\foo |
|
| 278 |
- // WORKDIR /foo --> C:\foo |
|
| 279 |
- // WORKDIR c:\\foo \ WORKDIR bar --> C:\foo --> C:\foo\bar |
|
| 280 |
- // WORKDIR C:/foo \ WORKDIR bar --> C:\foo --> C:\foo\bar |
|
| 281 |
- // WORKDIR C:/foo \ WORKDIR \\bar --> C:\foo --> C:\bar |
|
| 282 |
- // WORKDIR /foo \ WORKDIR c:/bar --> C:\foo --> C:\bar |
|
| 283 |
- if len(current) == 0 || system.IsAbs(workdir) {
|
|
| 284 |
- if (workdir[0] == os.PathSeparator) || |
|
| 285 |
- (len(workdir) > 1 && string(workdir[1]) != ":") || |
|
| 286 |
- (len(workdir) == 1) {
|
|
| 287 |
- workdir = filepath.Join(`C:\`, workdir) |
|
| 288 |
- } |
|
| 289 |
- } else {
|
|
| 290 |
- workdir = filepath.Join(current, workdir) |
|
| 291 |
- } |
|
| 292 |
- workdir = strings.ToUpper(string(workdir[0])) + workdir[1:] // Upper-case drive letter |
|
| 293 |
- } else {
|
|
| 294 |
- if !filepath.IsAbs(workdir) {
|
|
| 295 |
- workdir = filepath.Join(string(os.PathSeparator), current, workdir) |
|
| 296 |
- } |
|
| 267 |
+ b.runConfig.WorkingDir, err = normaliseWorkdir(b.runConfig.WorkingDir, args[0]) |
|
| 268 |
+ if err != nil {
|
|
| 269 |
+ return err |
|
| 297 | 270 |
} |
| 298 |
- b.runConfig.WorkingDir = workdir |
|
| 299 | 271 |
|
| 300 | 272 |
return b.commit("", b.runConfig.Cmd, fmt.Sprintf("WORKDIR %v", workdir))
|
| 301 | 273 |
} |
| 302 | 274 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,23 @@ |
| 0 |
+// +build !windows |
|
| 1 |
+ |
|
| 2 |
+package dockerfile |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "os" |
|
| 7 |
+ "path/filepath" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// normaliseWorkdir normalises a user requested working directory in a |
|
| 11 |
+// platform sematically consistent way. |
|
| 12 |
+func normaliseWorkdir(current string, requested string) (string, error) {
|
|
| 13 |
+ if requested == "" {
|
|
| 14 |
+ return "", fmt.Errorf("cannot normalise nothing")
|
|
| 15 |
+ } |
|
| 16 |
+ current = filepath.FromSlash(current) |
|
| 17 |
+ requested = filepath.FromSlash(requested) |
|
| 18 |
+ if !filepath.IsAbs(requested) {
|
|
| 19 |
+ return filepath.Join(string(os.PathSeparator), current, requested), nil |
|
| 20 |
+ } |
|
| 21 |
+ return requested, nil |
|
| 22 |
+} |
| 0 | 23 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,45 @@ |
| 0 |
+package dockerfile |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "os" |
|
| 5 |
+ "path/filepath" |
|
| 6 |
+ "strings" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/docker/docker/pkg/system" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+// normaliseWorkdir normalises a user requested working directory in a |
|
| 12 |
+// platform sematically consistent way. |
|
| 13 |
+func normaliseWorkdir(current string, requested string) (string, error) {
|
|
| 14 |
+ if requested == "" {
|
|
| 15 |
+ return "", fmt.Errorf("cannot normalise nothing")
|
|
| 16 |
+ } |
|
| 17 |
+ |
|
| 18 |
+ current = filepath.FromSlash(current) |
|
| 19 |
+ requested = filepath.FromSlash(requested) |
|
| 20 |
+ |
|
| 21 |
+ // Target semantics is C:\somefolder, specifically in the format: |
|
| 22 |
+ // UPPERCASEDriveLetter-Colon-Backslash-FolderName. We are already |
|
| 23 |
+ // guaranteed that `current`, if set, is consistent. This allows us to |
|
| 24 |
+ // cope correctly with any of the following in a Dockerfile: |
|
| 25 |
+ // WORKDIR a --> C:\a |
|
| 26 |
+ // WORKDIR c:\\foo --> C:\foo |
|
| 27 |
+ // WORKDIR \\foo --> C:\foo |
|
| 28 |
+ // WORKDIR /foo --> C:\foo |
|
| 29 |
+ // WORKDIR c:\\foo \ WORKDIR bar --> C:\foo --> C:\foo\bar |
|
| 30 |
+ // WORKDIR C:/foo \ WORKDIR bar --> C:\foo --> C:\foo\bar |
|
| 31 |
+ // WORKDIR C:/foo \ WORKDIR \\bar --> C:\foo --> C:\bar |
|
| 32 |
+ // WORKDIR /foo \ WORKDIR c:/bar --> C:\foo --> C:\bar |
|
| 33 |
+ if len(current) == 0 || system.IsAbs(requested) {
|
|
| 34 |
+ if (requested[0] == os.PathSeparator) || |
|
| 35 |
+ (len(requested) > 1 && string(requested[1]) != ":") || |
|
| 36 |
+ (len(requested) == 1) {
|
|
| 37 |
+ requested = filepath.Join(`C:\`, requested) |
|
| 38 |
+ } |
|
| 39 |
+ } else {
|
|
| 40 |
+ requested = filepath.Join(current, requested) |
|
| 41 |
+ } |
|
| 42 |
+ // Upper-case drive letter |
|
| 43 |
+ return (strings.ToUpper(string(requested[0])) + requested[1:]), nil |
|
| 44 |
+} |
| 0 | 45 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,34 @@ |
| 0 |
+// +build windows |
|
| 1 |
+ |
|
| 2 |
+package dockerfile |
|
| 3 |
+ |
|
| 4 |
+import "testing" |
|
| 5 |
+ |
|
| 6 |
+func TestNormaliseWorkdir(t *testing.T) {
|
|
| 7 |
+ tests := []struct{ current, requested, expected, etext string }{
|
|
| 8 |
+ {``, ``, ``, `cannot normalise nothing`},
|
|
| 9 |
+ {``, `a`, `C:\a`, ``},
|
|
| 10 |
+ {``, `c:\foo`, `C:\foo`, ``},
|
|
| 11 |
+ {``, `\foo`, `C:\foo`, ``},
|
|
| 12 |
+ {``, `/foo`, `C:\foo`, ``},
|
|
| 13 |
+ {``, `C:/foo`, `C:\foo`, ``},
|
|
| 14 |
+ {`C:\foo`, `bar`, `C:\foo\bar`, ``},
|
|
| 15 |
+ {`C:\foo`, `/bar`, `C:\bar`, ``},
|
|
| 16 |
+ {`C:\foo`, `\bar`, `C:\bar`, ``},
|
|
| 17 |
+ } |
|
| 18 |
+ for _, i := range tests {
|
|
| 19 |
+ r, e := normaliseWorkdir(i.current, i.requested) |
|
| 20 |
+ |
|
| 21 |
+ if i.etext != "" && e == nil {
|
|
| 22 |
+ t.Fatalf("TestNormaliseWorkingDir Expected error %s", i.etext)
|
|
| 23 |
+ } |
|
| 24 |
+ |
|
| 25 |
+ if i.etext != "" && e.Error() != i.etext {
|
|
| 26 |
+ t.Fatalf("TestNormaliseWorkingDir Expected error %s, got %s", i.etext, e.Error())
|
|
| 27 |
+ } |
|
| 28 |
+ |
|
| 29 |
+ if r != i.expected {
|
|
| 30 |
+ t.Fatalf("TestNormaliseWorkingDir Expected %s for %s %s", i.expected, i.current, i.requested)
|
|
| 31 |
+ } |
|
| 32 |
+ } |
|
| 33 |
+} |
| ... | ... |
@@ -200,60 +200,8 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD |
| 200 | 200 |
|
| 201 | 201 |
// Twiddle the destination when its a relative path - meaning, make it |
| 202 | 202 |
// relative to the WORKINGDIR |
| 203 |
- |
|
| 204 |
- endsInSlash := strings.HasSuffix(dest, string(os.PathSeparator)) |
|
| 205 |
- |
|
| 206 |
- if runtime.GOOS == "windows" {
|
|
| 207 |
- // On Windows, this is more complicated. We are guaranteed that the |
|
| 208 |
- // WorkingDir is already platform consistent meaning in the format |
|
| 209 |
- // UPPERCASEDriveLetter-Colon-Backslash-Foldername. However, Windows |
|
| 210 |
- // for now also has the limitation that ADD/COPY can only be done to |
|
| 211 |
- // the C: (system) drive, not any drives that might be present as a |
|
| 212 |
- // result of bind mounts. |
|
| 213 |
- // |
|
| 214 |
- // So... if the path specified is Linux-style absolute (/foo or \\foo), |
|
| 215 |
- // we assume it is the system drive. If it is a Windows-style absolute |
|
| 216 |
- // (DRIVE:\\foo), error if DRIVE is not C. And finally, ensure we |
|
| 217 |
- // strip any configured working directories drive letter so that it |
|
| 218 |
- // can be subsequently legitimately converted to a Windows volume-style |
|
| 219 |
- // pathname. |
|
| 220 |
- |
|
| 221 |
- // Not a typo - filepath.IsAbs, not system.IsAbs on this next check as |
|
| 222 |
- // we only want to validate where the DriveColon part has been supplied. |
|
| 223 |
- if filepath.IsAbs(dest) {
|
|
| 224 |
- if strings.ToUpper(string(dest[0])) != "C" {
|
|
| 225 |
- return fmt.Errorf("Windows does not support %s with a destinations not on the system drive (C:)", cmdName)
|
|
| 226 |
- } |
|
| 227 |
- dest = dest[2:] // Strip the drive letter |
|
| 228 |
- } |
|
| 229 |
- |
|
| 230 |
- // Cannot handle relative where WorkingDir is not the system drive. |
|
| 231 |
- if len(b.runConfig.WorkingDir) > 0 {
|
|
| 232 |
- if !system.IsAbs(b.runConfig.WorkingDir[2:]) {
|
|
| 233 |
- return fmt.Errorf("Current WorkingDir %s is not platform consistent", b.runConfig.WorkingDir)
|
|
| 234 |
- } |
|
| 235 |
- if !system.IsAbs(dest) {
|
|
| 236 |
- if string(b.runConfig.WorkingDir[0]) != "C" {
|
|
| 237 |
- return fmt.Errorf("Windows does not support %s with relative paths when WORKDIR is not the system drive", cmdName)
|
|
| 238 |
- } |
|
| 239 |
- |
|
| 240 |
- dest = filepath.Join(string(os.PathSeparator), b.runConfig.WorkingDir[2:], dest) |
|
| 241 |
- |
|
| 242 |
- // Make sure we preserve any trailing slash |
|
| 243 |
- if endsInSlash {
|
|
| 244 |
- dest += string(os.PathSeparator) |
|
| 245 |
- } |
|
| 246 |
- } |
|
| 247 |
- } |
|
| 248 |
- } else {
|
|
| 249 |
- if !system.IsAbs(dest) {
|
|
| 250 |
- dest = filepath.Join(string(os.PathSeparator), filepath.FromSlash(b.runConfig.WorkingDir), dest) |
|
| 251 |
- |
|
| 252 |
- // Make sure we preserve any trailing slash |
|
| 253 |
- if endsInSlash {
|
|
| 254 |
- dest += string(os.PathSeparator) |
|
| 255 |
- } |
|
| 256 |
- } |
|
| 203 |
+ if dest, err = normaliseDest(cmdName, b.runConfig.WorkingDir, dest); err != nil {
|
|
| 204 |
+ return err |
|
| 257 | 205 |
} |
| 258 | 206 |
|
| 259 | 207 |
for _, info := range infos {
|
| 260 | 208 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,26 @@ |
| 0 |
+// +build !windows |
|
| 1 |
+ |
|
| 2 |
+package dockerfile |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "os" |
|
| 6 |
+ "path/filepath" |
|
| 7 |
+ "strings" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/docker/docker/pkg/system" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+// normaliseDest normalises the destination of a COPY/ADD command in a |
|
| 13 |
+// platform semantically consistent way. |
|
| 14 |
+func normaliseDest(cmdName, workingDir, requested string) (string, error) {
|
|
| 15 |
+ dest := filepath.FromSlash(requested) |
|
| 16 |
+ endsInSlash := strings.HasSuffix(requested, string(os.PathSeparator)) |
|
| 17 |
+ if !system.IsAbs(requested) {
|
|
| 18 |
+ dest = filepath.Join(string(os.PathSeparator), filepath.FromSlash(workingDir), dest) |
|
| 19 |
+ // Make sure we preserve any trailing slash |
|
| 20 |
+ if endsInSlash {
|
|
| 21 |
+ dest += string(os.PathSeparator) |
|
| 22 |
+ } |
|
| 23 |
+ } |
|
| 24 |
+ return dest, nil |
|
| 25 |
+} |
| 0 | 26 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,56 @@ |
| 0 |
+package dockerfile |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "os" |
|
| 5 |
+ "path/filepath" |
|
| 6 |
+ "strings" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/docker/docker/pkg/system" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+// normaliseDest normalises the destination of a COPY/ADD command in a |
|
| 12 |
+// platform semantically consistent way. |
|
| 13 |
+func normaliseDest(cmdName, workingDir, requested string) (string, error) {
|
|
| 14 |
+ dest := filepath.FromSlash(requested) |
|
| 15 |
+ endsInSlash := strings.HasSuffix(dest, string(os.PathSeparator)) |
|
| 16 |
+ |
|
| 17 |
+ // We are guaranteed that the working directory is already consistent, |
|
| 18 |
+ // However, Windows also has, for now, the limitation that ADD/COPY can |
|
| 19 |
+ // only be done to the system drive, not any drives that might be present |
|
| 20 |
+ // as a result of a bind mount. |
|
| 21 |
+ // |
|
| 22 |
+ // So... if the path requested is Linux-style absolute (/foo or \\foo), |
|
| 23 |
+ // we assume it is the system drive. If it is a Windows-style absolute |
|
| 24 |
+ // (DRIVE:\\foo), error if DRIVE is not C. And finally, ensure we |
|
| 25 |
+ // strip any configured working directories drive letter so that it |
|
| 26 |
+ // can be subsequently legitimately converted to a Windows volume-style |
|
| 27 |
+ // pathname. |
|
| 28 |
+ |
|
| 29 |
+ // Not a typo - filepath.IsAbs, not system.IsAbs on this next check as |
|
| 30 |
+ // we only want to validate where the DriveColon part has been supplied. |
|
| 31 |
+ if filepath.IsAbs(dest) {
|
|
| 32 |
+ if strings.ToUpper(string(dest[0])) != "C" {
|
|
| 33 |
+ return "", fmt.Errorf("Windows does not support %s with a destinations not on the system drive (C:)", cmdName)
|
|
| 34 |
+ } |
|
| 35 |
+ dest = dest[2:] // Strip the drive letter |
|
| 36 |
+ } |
|
| 37 |
+ |
|
| 38 |
+ // Cannot handle relative where WorkingDir is not the system drive. |
|
| 39 |
+ if len(workingDir) > 0 {
|
|
| 40 |
+ if ((len(workingDir) > 1) && !system.IsAbs(workingDir[2:])) || (len(workingDir) == 1) {
|
|
| 41 |
+ return "", fmt.Errorf("Current WorkingDir %s is not platform consistent", workingDir)
|
|
| 42 |
+ } |
|
| 43 |
+ if !system.IsAbs(dest) {
|
|
| 44 |
+ if string(workingDir[0]) != "C" {
|
|
| 45 |
+ return "", fmt.Errorf("Windows does not support %s with relative paths when WORKDIR is not the system drive", cmdName)
|
|
| 46 |
+ } |
|
| 47 |
+ dest = filepath.Join(string(os.PathSeparator), workingDir[2:], dest) |
|
| 48 |
+ // Make sure we preserve any trailing slash |
|
| 49 |
+ if endsInSlash {
|
|
| 50 |
+ dest += string(os.PathSeparator) |
|
| 51 |
+ } |
|
| 52 |
+ } |
|
| 53 |
+ } |
|
| 54 |
+ return dest, nil |
|
| 55 |
+} |
| 0 | 56 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,51 @@ |
| 0 |
+// +build windows |
|
| 1 |
+ |
|
| 2 |
+package dockerfile |
|
| 3 |
+ |
|
| 4 |
+import "testing" |
|
| 5 |
+ |
|
| 6 |
+func TestNormaliseDest(t *testing.T) {
|
|
| 7 |
+ tests := []struct{ current, requested, expected, etext string }{
|
|
| 8 |
+ {``, `D:\`, ``, `Windows does not support TEST with a destinations not on the system drive (C:)`},
|
|
| 9 |
+ {``, `e:/`, ``, `Windows does not support TEST with a destinations not on the system drive (C:)`},
|
|
| 10 |
+ {`invalid`, `./c1`, ``, `Current WorkingDir invalid is not platform consistent`},
|
|
| 11 |
+ {`C:`, ``, ``, `Current WorkingDir C: is not platform consistent`},
|
|
| 12 |
+ {`C`, ``, ``, `Current WorkingDir C is not platform consistent`},
|
|
| 13 |
+ {`D:\`, `.`, ``, "Windows does not support TEST with relative paths when WORKDIR is not the system drive"},
|
|
| 14 |
+ {``, `D`, `D`, ``},
|
|
| 15 |
+ {``, `./a1`, `.\a1`, ``},
|
|
| 16 |
+ {``, `.\b1`, `.\b1`, ``},
|
|
| 17 |
+ {``, `/`, `\`, ``},
|
|
| 18 |
+ {``, `\`, `\`, ``},
|
|
| 19 |
+ {``, `c:/`, `\`, ``},
|
|
| 20 |
+ {``, `c:\`, `\`, ``},
|
|
| 21 |
+ {``, `.`, `.`, ``},
|
|
| 22 |
+ {`C:\wdd`, `./a1`, `\wdd\a1`, ``},
|
|
| 23 |
+ {`C:\wde`, `.\b1`, `\wde\b1`, ``},
|
|
| 24 |
+ {`C:\wdf`, `/`, `\`, ``},
|
|
| 25 |
+ {`C:\wdg`, `\`, `\`, ``},
|
|
| 26 |
+ {`C:\wdh`, `c:/`, `\`, ``},
|
|
| 27 |
+ {`C:\wdi`, `c:\`, `\`, ``},
|
|
| 28 |
+ {`C:\wdj`, `.`, `\wdj`, ``},
|
|
| 29 |
+ {`C:\wdk`, `foo/bar`, `\wdk\foo\bar`, ``},
|
|
| 30 |
+ {`C:\wdl`, `foo\bar`, `\wdl\foo\bar`, ``},
|
|
| 31 |
+ {`C:\wdm`, `foo/bar/`, `\wdm\foo\bar\`, ``},
|
|
| 32 |
+ {`C:\wdn`, `foo\bar/`, `\wdn\foo\bar\`, ``},
|
|
| 33 |
+ } |
|
| 34 |
+ for _, i := range tests {
|
|
| 35 |
+ got, err := normaliseDest("TEST", i.current, i.requested)
|
|
| 36 |
+ if err != nil && i.etext == "" {
|
|
| 37 |
+ t.Fatalf("TestNormaliseDest Got unexpected error %q for %s %s. ", err.Error(), i.current, i.requested)
|
|
| 38 |
+ } |
|
| 39 |
+ if i.etext != "" && ((err == nil) || (err != nil && err.Error() != i.etext)) {
|
|
| 40 |
+ if err == nil {
|
|
| 41 |
+ t.Fatalf("TestNormaliseDest Expected an error for %s %s but didn't get one", i.current, i.requested)
|
|
| 42 |
+ } else {
|
|
| 43 |
+ t.Fatalf("TestNormaliseDest Wrong error text for %s %s - %s", i.current, i.requested, err.Error())
|
|
| 44 |
+ } |
|
| 45 |
+ } |
|
| 46 |
+ if i.etext == "" && got != i.expected {
|
|
| 47 |
+ t.Fatalf("TestNormaliseDest Expected %q for %q and %q. Got %q", i.expected, i.current, i.requested, got)
|
|
| 48 |
+ } |
|
| 49 |
+ } |
|
| 50 |
+} |
| ... | ... |
@@ -2108,33 +2108,16 @@ func (s *DockerSuite) TestBuildRelativeWorkdir(c *check.C) {
|
| 2108 | 2108 |
} |
| 2109 | 2109 |
} |
| 2110 | 2110 |
|
| 2111 |
-// #22181 Regression test. Validates combinations of supported |
|
| 2112 |
-// WORKDIR dockerfile directives in Windows and non-Windows semantics. |
|
| 2111 |
+// #22181 Regression test. Single end-to-end test of using |
|
| 2112 |
+// Windows semantics. Most path handling verifications are in unit tests |
|
| 2113 | 2113 |
func (s *DockerSuite) TestBuildWindowsWorkdirProcessing(c *check.C) {
|
| 2114 | 2114 |
testRequires(c, DaemonIsWindows) |
| 2115 | 2115 |
name := "testbuildwindowsworkdirprocessing" |
| 2116 | 2116 |
_, err := buildImage(name, |
| 2117 | 2117 |
`FROM busybox |
| 2118 |
- WORKDIR a |
|
| 2119 |
- RUN sh -c "[ "$PWD" = "C:/a" ]" |
|
| 2120 |
- WORKDIR c:\\foo |
|
| 2121 |
- RUN sh -c "[ "$PWD" = "C:/foo" ]" |
|
| 2122 |
- WORKDIR \\foo |
|
| 2123 |
- RUN sh -c "[ "$PWD" = "C:/foo" ]" |
|
| 2124 |
- WORKDIR /foo |
|
| 2125 |
- RUN sh -c "[ "$PWD" = "C:/foo" ]" |
|
| 2126 |
- WORKDIR C:/foo |
|
| 2118 |
+ WORKDIR C:\\foo |
|
| 2127 | 2119 |
WORKDIR bar |
| 2128 | 2120 |
RUN sh -c "[ "$PWD" = "C:/foo/bar" ]" |
| 2129 |
- WORKDIR c:/foo |
|
| 2130 |
- WORKDIR bar |
|
| 2131 |
- RUN sh -c "[ "$PWD" = "C:/foo/bar" ]" |
|
| 2132 |
- WORKDIR c:/foo |
|
| 2133 |
- WORKDIR \\bar |
|
| 2134 |
- RUN sh -c "[ "$PWD" = "C:/bar" ]" |
|
| 2135 |
- WORKDIR /foo |
|
| 2136 |
- WORKDIR c:\\bar |
|
| 2137 |
- RUN sh -c "[ "$PWD" = "C:/bar" ]" |
|
| 2138 | 2121 |
`, |
| 2139 | 2122 |
true) |
| 2140 | 2123 |
if err != nil {
|
| ... | ... |
@@ -2142,8 +2125,8 @@ func (s *DockerSuite) TestBuildWindowsWorkdirProcessing(c *check.C) {
|
| 2142 | 2142 |
} |
| 2143 | 2143 |
} |
| 2144 | 2144 |
|
| 2145 |
-// #22181 Regression test. Validates combinations of supported |
|
| 2146 |
-// COPY dockerfile directives in Windows and non-Windows semantics. |
|
| 2145 |
+// #22181 Regression test. Most paths handling verifications are in unit test. |
|
| 2146 |
+// One functional test for end-to-end |
|
| 2147 | 2147 |
func (s *DockerSuite) TestBuildWindowsAddCopyPathProcessing(c *check.C) {
|
| 2148 | 2148 |
testRequires(c, DaemonIsWindows) |
| 2149 | 2149 |
name := "testbuildwindowsaddcopypathprocessing" |
| ... | ... |
@@ -2153,50 +2136,7 @@ func (s *DockerSuite) TestBuildWindowsAddCopyPathProcessing(c *check.C) {
|
| 2153 | 2153 |
// by docker on the Windows platform. |
| 2154 | 2154 |
dockerfile := ` |
| 2155 | 2155 |
FROM busybox |
| 2156 |
- # First cases with no workdir, all end up in the root directory of the system drive |
|
| 2157 |
- COPY a1 ./ |
|
| 2158 |
- ADD a2 ./ |
|
| 2159 |
- RUN sh -c "[ $(cat c:/a1) = 'helloa1' ]" |
|
| 2160 |
- RUN sh -c "[ $(cat c:/a2) = 'worlda2' ]" |
|
| 2161 |
- |
|
| 2162 |
- COPY b1 / |
|
| 2163 |
- ADD b2 / |
|
| 2164 |
- RUN sh -c "[ $(cat c:/b1) = 'hellob1' ]" |
|
| 2165 |
- RUN sh -c "[ $(cat c:/b2) = 'worldb2' ]" |
|
| 2166 |
- |
|
| 2167 |
- COPY c1 c:/ |
|
| 2168 |
- ADD c2 c:/ |
|
| 2169 |
- RUN sh -c "[ $(cat c:/c1) = 'helloc1' ]" |
|
| 2170 |
- RUN sh -c "[ $(cat c:/c2) = 'worldc2' ]" |
|
| 2171 |
- |
|
| 2172 |
- COPY d1 c:/ |
|
| 2173 |
- ADD d2 c:/ |
|
| 2174 |
- RUN sh -c "[ $(cat c:/d1) = 'hellod1' ]" |
|
| 2175 |
- RUN sh -c "[ $(cat c:/d2) = 'worldd2' ]" |
|
| 2176 |
- |
|
| 2177 |
- COPY e1 . |
|
| 2178 |
- ADD e2 . |
|
| 2179 |
- RUN sh -c "[ $(cat c:/e1) = 'helloe1' ]" |
|
| 2180 |
- RUN sh -c "[ $(cat c:/e2) = 'worlde2' ]" |
|
| 2181 |
- |
|
| 2182 |
- # Now with a workdir |
|
| 2183 |
- WORKDIR c:\\wa12 |
|
| 2184 |
- COPY wa1 ./ |
|
| 2185 |
- ADD wa2 ./ |
|
| 2186 |
- RUN sh -c "[ $(cat c:/wa12/wa1) = 'hellowa1' ]" |
|
| 2187 |
- RUN sh -c "[ $(cat c:/wa12/wa2) = 'worldwa2' ]" |
|
| 2188 |
- |
|
| 2189 |
- # No trailing slash on COPY/ADD, Linux-style path. |
|
| 2190 |
- # Results in dir being changed to a file |
|
| 2191 |
- WORKDIR /wb1 |
|
| 2192 |
- COPY wb1 . |
|
| 2193 |
- WORKDIR /wb2 |
|
| 2194 |
- ADD wb2 . |
|
| 2195 |
- WORKDIR c:/ |
|
| 2196 |
- RUN sh -c "[ $(cat c:/wb1) = 'hellowb1' ]" |
|
| 2197 |
- RUN sh -c "[ $(cat c:/wb2) = 'worldwb2' ]" |
|
| 2198 |
- |
|
| 2199 |
- # No trailing slash on COPY/ADD, Windows-style path. |
|
| 2156 |
+ # No trailing slash on COPY/ADD |
|
| 2200 | 2157 |
# Results in dir being changed to a file |
| 2201 | 2158 |
WORKDIR /wc1 |
| 2202 | 2159 |
COPY wc1 c:/wc1 |
| ... | ... |
@@ -2215,20 +2155,6 @@ func (s *DockerSuite) TestBuildWindowsAddCopyPathProcessing(c *check.C) {
|
| 2215 | 2215 |
RUN sh -c "[ $(cat c:/wd2/wd2) = 'worldwd2' ]" |
| 2216 | 2216 |
` |
| 2217 | 2217 |
ctx, err := fakeContext(dockerfile, map[string]string{
|
| 2218 |
- "a1": "helloa1", |
|
| 2219 |
- "a2": "worlda2", |
|
| 2220 |
- "b1": "hellob1", |
|
| 2221 |
- "b2": "worldb2", |
|
| 2222 |
- "c1": "helloc1", |
|
| 2223 |
- "c2": "worldc2", |
|
| 2224 |
- "d1": "hellod1", |
|
| 2225 |
- "d2": "worldd2", |
|
| 2226 |
- "e1": "helloe1", |
|
| 2227 |
- "e2": "worlde2", |
|
| 2228 |
- "wa1": "hellowa1", |
|
| 2229 |
- "wa2": "worldwa2", |
|
| 2230 |
- "wb1": "hellowb1", |
|
| 2231 |
- "wb2": "worldwb2", |
|
| 2232 | 2218 |
"wc1": "hellowc1", |
| 2233 | 2219 |
"wc2": "worldwc2", |
| 2234 | 2220 |
"wd1": "hellowd1", |
| ... | ... |
@@ -2244,96 +2170,6 @@ func (s *DockerSuite) TestBuildWindowsAddCopyPathProcessing(c *check.C) {
|
| 2244 | 2244 |
} |
| 2245 | 2245 |
} |
| 2246 | 2246 |
|
| 2247 |
-// #22181 Regression test. |
|
| 2248 |
-func (s *DockerSuite) TestBuildWindowsCopyFailsNonSystemDrive(c *check.C) {
|
|
| 2249 |
- testRequires(c, DaemonIsWindows) |
|
| 2250 |
- name := "testbuildwindowscopyfailsnonsystemdrive" |
|
| 2251 |
- dockerfile := ` |
|
| 2252 |
- FROM busybox |
|
| 2253 |
- cOpY foo d:/ |
|
| 2254 |
- ` |
|
| 2255 |
- ctx, err := fakeContext(dockerfile, map[string]string{"foo": "hello"})
|
|
| 2256 |
- if err != nil {
|
|
| 2257 |
- c.Fatal(err) |
|
| 2258 |
- } |
|
| 2259 |
- defer ctx.Close() |
|
| 2260 |
- _, err = buildImageFromContext(name, ctx, false) |
|
| 2261 |
- if err == nil {
|
|
| 2262 |
- c.Fatal(err) |
|
| 2263 |
- } |
|
| 2264 |
- if !strings.Contains(err.Error(), "Windows does not support COPY with a destinations not on the system drive (C:)") {
|
|
| 2265 |
- c.Fatal(err) |
|
| 2266 |
- } |
|
| 2267 |
-} |
|
| 2268 |
- |
|
| 2269 |
-// #22181 Regression test. |
|
| 2270 |
-func (s *DockerSuite) TestBuildWindowsCopyFailsWorkdirNonSystemDrive(c *check.C) {
|
|
| 2271 |
- testRequires(c, DaemonIsWindows) |
|
| 2272 |
- name := "testbuildwindowscopyfailsworkdirsystemdrive" |
|
| 2273 |
- dockerfile := ` |
|
| 2274 |
- FROM busybox |
|
| 2275 |
- WORKDIR d:/ |
|
| 2276 |
- cOpY foo . |
|
| 2277 |
- ` |
|
| 2278 |
- ctx, err := fakeContext(dockerfile, map[string]string{"foo": "hello"})
|
|
| 2279 |
- if err != nil {
|
|
| 2280 |
- c.Fatal(err) |
|
| 2281 |
- } |
|
| 2282 |
- defer ctx.Close() |
|
| 2283 |
- _, err = buildImageFromContext(name, ctx, false) |
|
| 2284 |
- if err == nil {
|
|
| 2285 |
- c.Fatal(err) |
|
| 2286 |
- } |
|
| 2287 |
- if !strings.Contains(err.Error(), "Windows does not support COPY with relative paths when WORKDIR is not the system drive") {
|
|
| 2288 |
- c.Fatal(err) |
|
| 2289 |
- } |
|
| 2290 |
-} |
|
| 2291 |
- |
|
| 2292 |
-// #22181 Regression test. |
|
| 2293 |
-func (s *DockerSuite) TestBuildWindowsAddFailsNonSystemDrive(c *check.C) {
|
|
| 2294 |
- testRequires(c, DaemonIsWindows) |
|
| 2295 |
- name := "testbuildwindowsaddfailsnonsystemdrive" |
|
| 2296 |
- dockerfile := ` |
|
| 2297 |
- FROM busybox |
|
| 2298 |
- AdD foo d:/ |
|
| 2299 |
- ` |
|
| 2300 |
- ctx, err := fakeContext(dockerfile, map[string]string{"foo": "hello"})
|
|
| 2301 |
- if err != nil {
|
|
| 2302 |
- c.Fatal(err) |
|
| 2303 |
- } |
|
| 2304 |
- defer ctx.Close() |
|
| 2305 |
- _, err = buildImageFromContext(name, ctx, false) |
|
| 2306 |
- if err == nil {
|
|
| 2307 |
- c.Fatal(err) |
|
| 2308 |
- } |
|
| 2309 |
- if !strings.Contains(err.Error(), "Windows does not support ADD with a destinations not on the system drive (C:)") {
|
|
| 2310 |
- c.Fatal(err) |
|
| 2311 |
- } |
|
| 2312 |
-} |
|
| 2313 |
- |
|
| 2314 |
-// #22181 Regression test. |
|
| 2315 |
-func (s *DockerSuite) TestBuildWindowsAddFailsWorkdirNonSystemDrive(c *check.C) {
|
|
| 2316 |
- testRequires(c, DaemonIsWindows) |
|
| 2317 |
- name := "testbuildwindowsaddfailsworkdirsystemdrive" |
|
| 2318 |
- dockerfile := ` |
|
| 2319 |
- FROM busybox |
|
| 2320 |
- WORKDIR d:/ |
|
| 2321 |
- AdD foo . |
|
| 2322 |
- ` |
|
| 2323 |
- ctx, err := fakeContext(dockerfile, map[string]string{"foo": "hello"})
|
|
| 2324 |
- if err != nil {
|
|
| 2325 |
- c.Fatal(err) |
|
| 2326 |
- } |
|
| 2327 |
- defer ctx.Close() |
|
| 2328 |
- _, err = buildImageFromContext(name, ctx, false) |
|
| 2329 |
- if err == nil {
|
|
| 2330 |
- c.Fatal(err) |
|
| 2331 |
- } |
|
| 2332 |
- if !strings.Contains(err.Error(), "Windows does not support ADD with relative paths when WORKDIR is not the system drive") {
|
|
| 2333 |
- c.Fatal(err) |
|
| 2334 |
- } |
|
| 2335 |
-} |
|
| 2336 |
- |
|
| 2337 | 2247 |
func (s *DockerSuite) TestBuildWorkdirWithEnvVariables(c *check.C) {
|
| 2338 | 2248 |
name := "testbuildworkdirwithenvvariables" |
| 2339 | 2249 |
|