github.com/lazyboychen7/engine@v17.12.1-ce-rc2+incompatible/builder/dockerfile/dispatchers_windows.go (about)

     1  package dockerfile
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"path"
     8  	"path/filepath"
     9  	"regexp"
    10  	"strings"
    11  
    12  	"github.com/docker/docker/pkg/system"
    13  )
    14  
    15  var pattern = regexp.MustCompile(`^[a-zA-Z]:\.$`)
    16  
    17  // normalizeWorkdir normalizes a user requested working directory in a
    18  // platform semantically consistent way.
    19  func normalizeWorkdir(platform string, current string, requested string) (string, error) {
    20  	if platform == "" {
    21  		platform = "windows"
    22  	}
    23  	if platform == "windows" {
    24  		return normalizeWorkdirWindows(current, requested)
    25  	}
    26  	return normalizeWorkdirUnix(current, requested)
    27  }
    28  
    29  // normalizeWorkdirUnix normalizes a user requested working directory in a
    30  // platform semantically consistent way.
    31  func normalizeWorkdirUnix(current string, requested string) (string, error) {
    32  	if requested == "" {
    33  		return "", errors.New("cannot normalize nothing")
    34  	}
    35  	current = strings.Replace(current, string(os.PathSeparator), "/", -1)
    36  	requested = strings.Replace(requested, string(os.PathSeparator), "/", -1)
    37  	if !path.IsAbs(requested) {
    38  		return path.Join(`/`, current, requested), nil
    39  	}
    40  	return requested, nil
    41  }
    42  
    43  // normalizeWorkdirWindows normalizes a user requested working directory in a
    44  // platform semantically consistent way.
    45  func normalizeWorkdirWindows(current string, requested string) (string, error) {
    46  	if requested == "" {
    47  		return "", errors.New("cannot normalize nothing")
    48  	}
    49  
    50  	// `filepath.Clean` will replace "" with "." so skip in that case
    51  	if current != "" {
    52  		current = filepath.Clean(current)
    53  	}
    54  	if requested != "" {
    55  		requested = filepath.Clean(requested)
    56  	}
    57  
    58  	// If either current or requested in Windows is:
    59  	// C:
    60  	// C:.
    61  	// then an error will be thrown as the definition for the above
    62  	// refers to `current directory on drive C:`
    63  	// Since filepath.Clean() will automatically normalize the above
    64  	// to `C:.`, we only need to check the last format
    65  	if pattern.MatchString(current) {
    66  		return "", fmt.Errorf("%s is not a directory. If you are specifying a drive letter, please add a trailing '\\'", current)
    67  	}
    68  	if pattern.MatchString(requested) {
    69  		return "", fmt.Errorf("%s is not a directory. If you are specifying a drive letter, please add a trailing '\\'", requested)
    70  	}
    71  
    72  	// Target semantics is C:\somefolder, specifically in the format:
    73  	// UPPERCASEDriveLetter-Colon-Backslash-FolderName. We are already
    74  	// guaranteed that `current`, if set, is consistent. This allows us to
    75  	// cope correctly with any of the following in a Dockerfile:
    76  	//	WORKDIR a                       --> C:\a
    77  	//	WORKDIR c:\\foo                 --> C:\foo
    78  	//	WORKDIR \\foo                   --> C:\foo
    79  	//	WORKDIR /foo                    --> C:\foo
    80  	//	WORKDIR c:\\foo \ WORKDIR bar   --> C:\foo --> C:\foo\bar
    81  	//	WORKDIR C:/foo \ WORKDIR bar    --> C:\foo --> C:\foo\bar
    82  	//	WORKDIR C:/foo \ WORKDIR \\bar  --> C:\foo --> C:\bar
    83  	//	WORKDIR /foo \ WORKDIR c:/bar   --> C:\foo --> C:\bar
    84  	if len(current) == 0 || system.IsAbs(requested) {
    85  		if (requested[0] == os.PathSeparator) ||
    86  			(len(requested) > 1 && string(requested[1]) != ":") ||
    87  			(len(requested) == 1) {
    88  			requested = filepath.Join(`C:\`, requested)
    89  		}
    90  	} else {
    91  		requested = filepath.Join(current, requested)
    92  	}
    93  	// Upper-case drive letter
    94  	return (strings.ToUpper(string(requested[0])) + requested[1:]), nil
    95  }
    96  
    97  // equalEnvKeys compare two strings and returns true if they are equal. On
    98  // Windows this comparison is case insensitive.
    99  func equalEnvKeys(from, to string) bool {
   100  	return strings.ToUpper(from) == strings.ToUpper(to)
   101  }