Skip to content

Commit

Permalink
Merge pull request #909 from ceh/hg-local-win-path
Browse files Browse the repository at this point in the history
config/module: fix HgGetter test failures on Windows
  • Loading branch information
mitchellh committed Feb 2, 2015
2 parents cfbf39d + a8db835 commit c18b01f
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 9 deletions.
36 changes: 27 additions & 9 deletions config/module/get_hg.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/url"
"os"
"os/exec"
"runtime"
)

// HgGetter is a Getter implementation that will download a module from
Expand All @@ -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 {
Expand All @@ -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] == ':'
}
8 changes: 8 additions & 0 deletions config/module/url_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/url"
"path/filepath"
"runtime"
"strings"
)

func urlParse(rawURL string) (*url.URL, error) {
Expand All @@ -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.
Expand Down

0 comments on commit c18b01f

Please sign in to comment.