config/module: handle absolute file paths on Windows

Using url.Parse to parse an absolute file path on Windows yields
a URL type where the Path element is prefixed by a slash.

For example, parsing "file:///C:/Users/user" gives a URL type
with Path:"/C:/Users/user".

According to golang.org/issue/6027, the parsing is correct as is.

The leading slash on the Path must be eliminated before any file
operations.

This commit introduces a urlParse function which wraps the url.Parse
functionality and removes the leading slash in Path for absolute file
paths on Windows.

Fixes config/module test failures on Windows.
This commit is contained in:
Emil Hessman 2015-01-27 22:19:49 +01:00
parent 78d1fc742f
commit d5a49363d7
4 changed files with 54 additions and 16 deletions

View File

@ -21,13 +21,5 @@ func (d *FileDetector) Detect(src, pwd string) (string, bool, error) {
src = filepath.Join(pwd, src)
}
// Make sure we're using "/" even on Windows. URLs are "/"-based.
src = filepath.ToSlash(src)
// Make sure that we don't start with "/" since we add that below
if src[0] == '/' {
src = src[1:]
}
return fmt.Sprintf("file:///%s", src), true, nil
return fmtFileURL(src), true, nil
}

View File

@ -72,7 +72,7 @@ func Get(dst, src string) error {
dst = tmpDir
}
u, err := url.Parse(src)
u, err := urlParse(src)
if err != nil {
return err
}

View File

@ -39,15 +39,11 @@ func testModule(n string) string {
if err != nil {
panic(err)
}
var url url.URL
url.Scheme = "file"
url.Path = filepath.ToSlash(p)
return url.String()
return fmtFileURL(p)
}
func testModuleURL(n string) *url.URL {
u, err := url.Parse(testModule(n))
u, err := urlParse(testModule(n))
if err != nil {
panic(err)
}

View File

@ -0,0 +1,50 @@
package module
import (
"fmt"
"net/url"
"path/filepath"
"runtime"
)
func urlParse(rawURL string) (*url.URL, error) {
if runtime.GOOS == "windows" {
// Make sure we're using "/" on Windows. URLs are "/"-based.
rawURL = filepath.ToSlash(rawURL)
}
u, err := url.Parse(rawURL)
if err != nil {
return nil, err
}
if runtime.GOOS != "windows" {
return u, err
}
if u.Scheme != "file" {
return u, err
}
// Remove leading slash for absolute file paths on Windows.
// For example, url.Parse yields u.Path = "/C:/Users/user" for
// rawurl = "file:///C:/Users/user", which is an incorrect syntax.
if len(u.Path) > 2 && u.Path[0] == '/' && u.Path[2] == ':' {
u.Path = u.Path[1:]
}
return u, err
}
func fmtFileURL(path string) string {
if runtime.GOOS == "windows" {
// Make sure we're using "/" on Windows. URLs are "/"-based.
path = filepath.ToSlash(path)
}
// Make sure that we don't start with "/" since we add that below.
if path[0] == '/' {
path = path[1:]
}
return fmt.Sprintf("file:///%s", path)
}