Merge pull request #909 from ceh/hg-local-win-path

config/module: fix HgGetter test failures on Windows
This commit is contained in:
Mitchell Hashimoto 2015-02-02 20:33:19 +01:00
commit c18b01fa2a
2 changed files with 35 additions and 9 deletions

View File

@ -5,6 +5,7 @@ import (
"net/url" "net/url"
"os" "os"
"os/exec" "os/exec"
"runtime"
) )
// HgGetter is a Getter implementation that will download a module from // HgGetter is a Getter implementation that will download a module from
@ -16,34 +17,40 @@ func (g *HgGetter) Get(dst string, u *url.URL) error {
return fmt.Errorf("hg must be available and on the PATH") return fmt.Errorf("hg must be available and on the PATH")
} }
newURL, err := urlParse(u.String())
if err != nil {
return err
}
if fixWindowsDrivePath(newURL) {
// See valid file path form on http://www.selenic.com/hg/help/urls
newURL.Path = fmt.Sprintf("/%s", newURL.Path)
}
// Extract some query parameters we use // Extract some query parameters we use
var rev string var rev string
q := u.Query() q := newURL.Query()
if len(q) > 0 { if len(q) > 0 {
rev = q.Get("rev") rev = q.Get("rev")
q.Del("rev") q.Del("rev")
// Copy the URL newURL.RawQuery = q.Encode()
var newU url.URL = *u
u = &newU
u.RawQuery = q.Encode()
} }
_, err := os.Stat(dst) _, err = os.Stat(dst)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
return err return err
} }
if err != nil { if err != nil {
if err := g.clone(dst, u); err != nil { if err := g.clone(dst, newURL); err != nil {
return err return err
} }
} }
if err := g.pull(dst, u); err != nil { if err := g.pull(dst, newURL); err != nil {
return err return err
} }
return g.update(dst, u, rev) return g.update(dst, newURL, rev)
} }
func (g *HgGetter) clone(dst string, u *url.URL) error { func (g *HgGetter) clone(dst string, u *url.URL) error {
@ -67,3 +74,14 @@ func (g *HgGetter) update(dst string, u *url.URL, rev string) error {
cmd.Dir = dst cmd.Dir = dst
return getRunCommand(cmd) return getRunCommand(cmd)
} }
func fixWindowsDrivePath(u *url.URL) bool {
// hg assumes a file:/// prefix for Windows drive letter file paths.
// (e.g. file:///c:/foo/bar)
// If the URL Path does not begin with a '/' character, the resulting URL
// path will have a file:// prefix. (e.g. file://c:/foo/bar)
// See http://www.selenic.com/hg/help/urls and the examples listed in
// http://selenic.com/repo/hg-stable/file/1265a3a71d75/mercurial/util.py#l1936
return runtime.GOOS == "windows" && u.Scheme == "file" &&
len(u.Path) > 1 && u.Path[0] != '/' && u.Path[1] == ':'
}

View File

@ -5,6 +5,7 @@ import (
"net/url" "net/url"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
) )
func urlParse(rawURL string) (*url.URL, error) { func urlParse(rawURL string) (*url.URL, error) {
@ -30,6 +31,13 @@ func urlParse(rawURL string) (*url.URL, error) {
u.Scheme = "" u.Scheme = ""
} }
if len(u.Host) > 1 && u.Host[1] == ':' && strings.HasPrefix(rawURL, "file://") {
// Assume we're dealing with a drive letter file path on Windows
// where the drive letter has been parsed into the URL Host.
u.Path = fmt.Sprintf("%s%s", u.Host, u.Path)
u.Host = ""
}
// Remove leading slash for absolute file paths on Windows. // Remove leading slash for absolute file paths on Windows.
// For example, url.Parse yields u.Path = "/C:/Users/user" for // For example, url.Parse yields u.Path = "/C:/Users/user" for
// rawURL = "file:///C:/Users/user", which is an incorrect syntax. // rawURL = "file:///C:/Users/user", which is an incorrect syntax.