github.com/vieux/docker@v0.6.3-0.20161004191708-e097c2a938c7/builder/dockerfile/dispatchers_windows.go (about) 1 package dockerfile 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "regexp" 8 "strings" 9 10 "github.com/docker/docker/pkg/system" 11 ) 12 13 // normaliseWorkdir normalises a user requested working directory in a 14 // platform sematically consistent way. 15 func normaliseWorkdir(current string, requested string) (string, error) { 16 if requested == "" { 17 return "", fmt.Errorf("cannot normalise nothing") 18 } 19 20 current = filepath.FromSlash(current) 21 requested = filepath.FromSlash(requested) 22 23 // Target semantics is C:\somefolder, specifically in the format: 24 // UPPERCASEDriveLetter-Colon-Backslash-FolderName. We are already 25 // guaranteed that `current`, if set, is consistent. This allows us to 26 // cope correctly with any of the following in a Dockerfile: 27 // WORKDIR a --> C:\a 28 // WORKDIR c:\\foo --> C:\foo 29 // WORKDIR \\foo --> C:\foo 30 // WORKDIR /foo --> C:\foo 31 // WORKDIR c:\\foo \ WORKDIR bar --> C:\foo --> C:\foo\bar 32 // WORKDIR C:/foo \ WORKDIR bar --> C:\foo --> C:\foo\bar 33 // WORKDIR C:/foo \ WORKDIR \\bar --> C:\foo --> C:\bar 34 // WORKDIR /foo \ WORKDIR c:/bar --> C:\foo --> C:\bar 35 if len(current) == 0 || system.IsAbs(requested) { 36 if (requested[0] == os.PathSeparator) || 37 (len(requested) > 1 && string(requested[1]) != ":") || 38 (len(requested) == 1) { 39 requested = filepath.Join(`C:\`, requested) 40 } 41 } else { 42 requested = filepath.Join(current, requested) 43 } 44 // Upper-case drive letter 45 return (strings.ToUpper(string(requested[0])) + requested[1:]), nil 46 } 47 48 func errNotJSON(command, original string) error { 49 // For Windows users, give a hint if it looks like it might contain 50 // a path which hasn't been escaped such as ["c:\windows\system32\prog.exe", "-param"], 51 // as JSON must be escaped. Unfortunate... 52 // 53 // Specifically looking for quote-driveletter-colon-backslash, there's no 54 // double backslash and a [] pair. No, this is not perfect, but it doesn't 55 // have to be. It's simply a hint to make life a little easier. 56 extra := "" 57 original = filepath.FromSlash(strings.ToLower(strings.Replace(strings.ToLower(original), strings.ToLower(command)+" ", "", -1))) 58 if len(regexp.MustCompile(`"[a-z]:\\.*`).FindStringSubmatch(original)) > 0 && 59 !strings.Contains(original, `\\`) && 60 strings.Contains(original, "[") && 61 strings.Contains(original, "]") { 62 extra = fmt.Sprintf(`. It looks like '%s' includes a file path without an escaped back-slash. JSON requires back-slashes to be escaped such as ["c:\\path\\to\\file.exe", "/parameter"]`, original) 63 } 64 return fmt.Errorf("%s requires the arguments to be in JSON form%s", command, extra) 65 }