config/module: fix HgGetter test failures on Windows

HgGetter tests failed on windows/amd64 using Mercurial version 3.2.4:

--- FAIL: TestHgGetter (0.11s)
        get_hg_test.go:35: err: C:\Program Files\Mercurial\hg.exe exited with 255: abort: file:// URLs can only refer to localhost
--- FAIL: TestHgGetter_branch (0.11s)
        get_hg_test.go:62: err: C:\Program Files\Mercurial\hg.exe exited with 255: abort: file:// URLs can only refer to localhost
FAIL
FAIL    github.com/hashicorp/terraform/config/module    5.615s

This commit fixes the failures by adjusting the file:// URL to a form that
Mercurial expects.
This commit is contained in:
Emil Hessman 2015-02-02 19:49:53 +01:00
parent cfbf39d1de
commit a8db835a44
2 changed files with 35 additions and 9 deletions

View File

@ -5,6 +5,7 @@ import (
"net/url"
"os"
"os/exec"
"runtime"
)
// 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")
}
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
var rev string
q := u.Query()
q := newURL.Query()
if len(q) > 0 {
rev = q.Get("rev")
q.Del("rev")
// Copy the URL
var newU url.URL = *u
u = &newU
u.RawQuery = q.Encode()
newURL.RawQuery = q.Encode()
}
_, err := os.Stat(dst)
_, err = os.Stat(dst)
if err != nil && !os.IsNotExist(err) {
return err
}
if err != nil {
if err := g.clone(dst, u); err != nil {
if err := g.clone(dst, newURL); err != nil {
return err
}
}
if err := g.pull(dst, u); err != nil {
if err := g.pull(dst, newURL); err != nil {
return err
}
return g.update(dst, u, rev)
return g.update(dst, newURL, rev)
}
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
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"
"path/filepath"
"runtime"
"strings"
)
func urlParse(rawURL string) (*url.URL, error) {
@ -30,6 +31,13 @@ func urlParse(rawURL string) (*url.URL, error) {
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.
// For example, url.Parse yields u.Path = "/C:/Users/user" for
// rawURL = "file:///C:/Users/user", which is an incorrect syntax.