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