github.com/hobbeswalsh/terraform@v0.3.7-0.20150619183303-ad17cf55a0fa/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  }