github.com/nicgrayson/terraform@v0.4.3-0.20150415203910-c4de50829380/config/module/get_hg.go (about) 1 package module 2 3 import ( 4 "fmt" 5 "net/url" 6 "os" 7 "os/exec" 8 "runtime" 9 10 urlhelper "github.com/hashicorp/terraform/helper/url" 11 ) 12 13 // HgGetter is a Getter implementation that will download a module from 14 // a Mercurial repository. 15 type HgGetter struct{} 16 17 func (g *HgGetter) Get(dst string, u *url.URL) error { 18 if _, err := exec.LookPath("hg"); err != nil { 19 return fmt.Errorf("hg must be available and on the PATH") 20 } 21 22 newURL, err := urlhelper.Parse(u.String()) 23 if err != nil { 24 return err 25 } 26 if fixWindowsDrivePath(newURL) { 27 // See valid file path form on http://www.selenic.com/hg/help/urls 28 newURL.Path = fmt.Sprintf("/%s", newURL.Path) 29 } 30 31 // Extract some query parameters we use 32 var rev string 33 q := newURL.Query() 34 if len(q) > 0 { 35 rev = q.Get("rev") 36 q.Del("rev") 37 38 newURL.RawQuery = q.Encode() 39 } 40 41 _, err = os.Stat(dst) 42 if err != nil && !os.IsNotExist(err) { 43 return err 44 } 45 if err != nil { 46 if err := g.clone(dst, newURL); err != nil { 47 return err 48 } 49 } 50 51 if err := g.pull(dst, newURL); err != nil { 52 return err 53 } 54 55 return g.update(dst, newURL, rev) 56 } 57 58 func (g *HgGetter) clone(dst string, u *url.URL) error { 59 cmd := exec.Command("hg", "clone", "-U", u.String(), dst) 60 return getRunCommand(cmd) 61 } 62 63 func (g *HgGetter) pull(dst string, u *url.URL) error { 64 cmd := exec.Command("hg", "pull") 65 cmd.Dir = dst 66 return getRunCommand(cmd) 67 } 68 69 func (g *HgGetter) update(dst string, u *url.URL, rev string) error { 70 args := []string{"update"} 71 if rev != "" { 72 args = append(args, rev) 73 } 74 75 cmd := exec.Command("hg", args...) 76 cmd.Dir = dst 77 return getRunCommand(cmd) 78 } 79 80 func fixWindowsDrivePath(u *url.URL) bool { 81 // hg assumes a file:/// prefix for Windows drive letter file paths. 82 // (e.g. file:///c:/foo/bar) 83 // If the URL Path does not begin with a '/' character, the resulting URL 84 // path will have a file:// prefix. (e.g. file://c:/foo/bar) 85 // See http://www.selenic.com/hg/help/urls and the examples listed in 86 // http://selenic.com/repo/hg-stable/file/1265a3a71d75/mercurial/util.py#l1936 87 return runtime.GOOS == "windows" && u.Scheme == "file" && 88 len(u.Path) > 1 && u.Path[0] != '/' && u.Path[1] == ':' 89 }