diff options
Diffstat (limited to 'vendor/github.com/hashicorp/go-getter/get_hg.go')
-rw-r--r-- | vendor/github.com/hashicorp/go-getter/get_hg.go | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-getter/get_hg.go b/vendor/github.com/hashicorp/go-getter/get_hg.go new file mode 100644 index 0000000..820bdd4 --- /dev/null +++ b/vendor/github.com/hashicorp/go-getter/get_hg.go | |||
@@ -0,0 +1,131 @@ | |||
1 | package getter | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "io/ioutil" | ||
6 | "net/url" | ||
7 | "os" | ||
8 | "os/exec" | ||
9 | "path/filepath" | ||
10 | "runtime" | ||
11 | |||
12 | urlhelper "github.com/hashicorp/go-getter/helper/url" | ||
13 | ) | ||
14 | |||
15 | // HgGetter is a Getter implementation that will download a module from | ||
16 | // a Mercurial repository. | ||
17 | type HgGetter struct{} | ||
18 | |||
19 | func (g *HgGetter) ClientMode(_ *url.URL) (ClientMode, error) { | ||
20 | return ClientModeDir, nil | ||
21 | } | ||
22 | |||
23 | func (g *HgGetter) Get(dst string, u *url.URL) error { | ||
24 | if _, err := exec.LookPath("hg"); err != nil { | ||
25 | return fmt.Errorf("hg must be available and on the PATH") | ||
26 | } | ||
27 | |||
28 | newURL, err := urlhelper.Parse(u.String()) | ||
29 | if err != nil { | ||
30 | return err | ||
31 | } | ||
32 | if fixWindowsDrivePath(newURL) { | ||
33 | // See valid file path form on http://www.selenic.com/hg/help/urls | ||
34 | newURL.Path = fmt.Sprintf("/%s", newURL.Path) | ||
35 | } | ||
36 | |||
37 | // Extract some query parameters we use | ||
38 | var rev string | ||
39 | q := newURL.Query() | ||
40 | if len(q) > 0 { | ||
41 | rev = q.Get("rev") | ||
42 | q.Del("rev") | ||
43 | |||
44 | newURL.RawQuery = q.Encode() | ||
45 | } | ||
46 | |||
47 | _, err = os.Stat(dst) | ||
48 | if err != nil && !os.IsNotExist(err) { | ||
49 | return err | ||
50 | } | ||
51 | if err != nil { | ||
52 | if err := g.clone(dst, newURL); err != nil { | ||
53 | return err | ||
54 | } | ||
55 | } | ||
56 | |||
57 | if err := g.pull(dst, newURL); err != nil { | ||
58 | return err | ||
59 | } | ||
60 | |||
61 | return g.update(dst, newURL, rev) | ||
62 | } | ||
63 | |||
64 | // GetFile for Hg doesn't support updating at this time. It will download | ||
65 | // the file every time. | ||
66 | func (g *HgGetter) GetFile(dst string, u *url.URL) error { | ||
67 | td, err := ioutil.TempDir("", "getter-hg") | ||
68 | if err != nil { | ||
69 | return err | ||
70 | } | ||
71 | if err := os.RemoveAll(td); err != nil { | ||
72 | return err | ||
73 | } | ||
74 | |||
75 | // Get the filename, and strip the filename from the URL so we can | ||
76 | // just get the repository directly. | ||
77 | filename := filepath.Base(u.Path) | ||
78 | u.Path = filepath.ToSlash(filepath.Dir(u.Path)) | ||
79 | |||
80 | // If we're on Windows, we need to set the host to "localhost" for hg | ||
81 | if runtime.GOOS == "windows" { | ||
82 | u.Host = "localhost" | ||
83 | } | ||
84 | |||
85 | // Get the full repository | ||
86 | if err := g.Get(td, u); err != nil { | ||
87 | return err | ||
88 | } | ||
89 | |||
90 | // Copy the single file | ||
91 | u, err = urlhelper.Parse(fmtFileURL(filepath.Join(td, filename))) | ||
92 | if err != nil { | ||
93 | return err | ||
94 | } | ||
95 | |||
96 | fg := &FileGetter{Copy: true} | ||
97 | return fg.GetFile(dst, u) | ||
98 | } | ||
99 | |||
100 | func (g *HgGetter) clone(dst string, u *url.URL) error { | ||
101 | cmd := exec.Command("hg", "clone", "-U", u.String(), dst) | ||
102 | return getRunCommand(cmd) | ||
103 | } | ||
104 | |||
105 | func (g *HgGetter) pull(dst string, u *url.URL) error { | ||
106 | cmd := exec.Command("hg", "pull") | ||
107 | cmd.Dir = dst | ||
108 | return getRunCommand(cmd) | ||
109 | } | ||
110 | |||
111 | func (g *HgGetter) update(dst string, u *url.URL, rev string) error { | ||
112 | args := []string{"update"} | ||
113 | if rev != "" { | ||
114 | args = append(args, rev) | ||
115 | } | ||
116 | |||
117 | cmd := exec.Command("hg", args...) | ||
118 | cmd.Dir = dst | ||
119 | return getRunCommand(cmd) | ||
120 | } | ||
121 | |||
122 | func fixWindowsDrivePath(u *url.URL) bool { | ||
123 | // hg assumes a file:/// prefix for Windows drive letter file paths. | ||
124 | // (e.g. file:///c:/foo/bar) | ||
125 | // If the URL Path does not begin with a '/' character, the resulting URL | ||
126 | // path will have a file:// prefix. (e.g. file://c:/foo/bar) | ||
127 | // See http://www.selenic.com/hg/help/urls and the examples listed in | ||
128 | // http://selenic.com/repo/hg-stable/file/1265a3a71d75/mercurial/util.py#l1936 | ||
129 | return runtime.GOOS == "windows" && u.Scheme == "file" && | ||
130 | len(u.Path) > 1 && u.Path[0] != '/' && u.Path[1] == ':' | ||
131 | } | ||