github.com/kikitux/packer@v0.10.1-0.20160322154024-6237df566f9f/common/config.go (about) 1 package common 2 3 import ( 4 "fmt" 5 "net/url" 6 "os" 7 "path/filepath" 8 "runtime" 9 "strings" 10 ) 11 12 // ScrubConfig is a helper that returns a string representation of 13 // any struct with the given values stripped out. 14 func ScrubConfig(target interface{}, values ...string) string { 15 conf := fmt.Sprintf("Config: %+v", target) 16 for _, value := range values { 17 if value == "" { 18 continue 19 } 20 conf = strings.Replace(conf, value, "<Filtered>", -1) 21 } 22 return conf 23 } 24 25 // ChooseString returns the first non-empty value. 26 func ChooseString(vals ...string) string { 27 for _, el := range vals { 28 if el != "" { 29 return el 30 } 31 } 32 33 return "" 34 } 35 36 // DownloadableURL processes a URL that may also be a file path and returns 37 // a completely valid URL. For example, the original URL might be "local/file.iso" 38 // which isn't a valid URL. DownloadableURL will return "file:///local/file.iso" 39 func DownloadableURL(original string) (string, error) { 40 if runtime.GOOS == "windows" { 41 // If the distance to the first ":" is just one character, assume 42 // we're dealing with a drive letter and thus a file path. 43 idx := strings.Index(original, ":") 44 if idx == 1 { 45 original = "file:///" + original 46 } 47 } 48 49 url, err := url.Parse(original) 50 if err != nil { 51 return "", err 52 } 53 54 if url.Scheme == "" { 55 url.Scheme = "file" 56 } 57 58 if url.Scheme == "file" { 59 // Windows file handling is all sorts of tricky... 60 if runtime.GOOS == "windows" { 61 // If the path is using Windows-style slashes, URL parses 62 // it into the host field. 63 if url.Path == "" && strings.Contains(url.Host, `\`) { 64 url.Path = url.Host 65 url.Host = "" 66 } 67 68 // For Windows absolute file paths, remove leading / prior to processing 69 // since net/url turns "C:/" into "/C:/" 70 if len(url.Path) > 0 && url.Path[0] == '/' { 71 url.Path = url.Path[1:len(url.Path)] 72 } 73 } 74 75 // Only do the filepath transformations if the file appears 76 // to actually exist. 77 if _, err := os.Stat(url.Path); err == nil { 78 url.Path, err = filepath.Abs(url.Path) 79 if err != nil { 80 return "", err 81 } 82 83 url.Path, err = filepath.EvalSymlinks(url.Path) 84 if err != nil { 85 return "", err 86 } 87 88 url.Path = filepath.Clean(url.Path) 89 } 90 91 if runtime.GOOS == "windows" { 92 // Also replace all backslashes with forwardslashes since Windows 93 // users are likely to do this but the URL should actually only 94 // contain forward slashes. 95 url.Path = strings.Replace(url.Path, `\`, `/`, -1) 96 } 97 } 98 99 // Make sure it is lowercased 100 url.Scheme = strings.ToLower(url.Scheme) 101 102 // This is to work around issue #5927. This can safely be removed once 103 // we distribute with a version of Go that fixes that bug. 104 // 105 // See: https://code.google.com/p/go/issues/detail?id=5927 106 if url.Path != "" && url.Path[0] != '/' { 107 url.Path = "/" + url.Path 108 } 109 110 // Verify that the scheme is something we support in our common downloader. 111 supported := []string{"file", "http", "https"} 112 found := false 113 for _, s := range supported { 114 if url.Scheme == s { 115 found = true 116 break 117 } 118 } 119 120 if !found { 121 return "", fmt.Errorf("Unsupported URL scheme: %s", url.Scheme) 122 } 123 124 return url.String(), nil 125 }