func (v vcHg) update(ref string) error {
	_, err := exec.Command("hg",
		"update",
		"-r", ref,
		"-R", string(v),
		"--cwd", path.Dir(string(v)),
	).Output()
	if err != nil {
		return err
	}
	return nil
}
vcHg.update updates the given hg dir to ref.
package main
import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"runtime"
	"strings"
)
const (
	DefaultThirdParty = "third_party"
)
func thirdPartyDir() string {
	root, err := os.Getwd()
	if err != nil {
		log.Fatalf("Failed to get the current working directory: %v", err)
	}
	return path.Join(root, DefaultThirdParty)
}
func srcDir() string {
	return path.Join(thirdPartyDir(), "src")
}
func binDir() string {
	root, err := os.Getwd()
	if err != nil {
		log.Fatalf("Failed to get the current working directory: %v", err)
	}
	return path.Join(root, "bin")
}
func run(name string, arg ...string) *os.ProcessState {
	cmd := exec.Command(name, arg...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	err = cmd.Start()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	go io.Copy(os.Stdout, stdout)
	go io.Copy(os.Stderr, stderr)
	cmd.Wait()
	return cmd.ProcessState
}
func setupProject(pkg string) {
	root, err := os.Getwd()
	if err != nil {
		log.Fatalf("Failed to get the current working directory: %v", err)
	}
	pkgsrc := path.Join(srcDir(), pkg)
	pkgsrcdir := path.Dir(pkgsrc)
	os.MkdirAll(pkgsrcdir, 0755)
	rel, err := filepath.Rel(pkgsrcdir, root)
	if err != nil {
		log.Fatalf("creating relative third party path: %v", err)
	}
	err = os.Symlink(rel, pkgsrc)
	if err != nil && os.IsExist(err) == false {
		log.Fatalf("creating project third party symlink: %v", err)
	}
}
func getVc(root string) versionControl {
	for _, v := range []string{".git", ".hg"} {
		r := path.Join(root, v)
		info, err := os.Stat(r)
		if err != nil || !info.IsDir() {
			continue
		}
		base := path.Base(r)
		switch base {
		case ".git":
			return vcGit(r)
		case ".hg":
			return vcHg(r)
		}
	}
	return new(vcNoop)
}
type versionControl interface {
	commit() string
	update(string) error
}
type vcNoop struct{}
func (v *vcNoop) commit() string {
	return ""
}
func (v *vcNoop) update(dir string) error {
	return nil
}
type vcHg string
func (v vcHg) commit() string {
	out, err := exec.Command("hg",
		"id",
		"-i",
		"-R", string(v),
	).Output()
	if err != nil {
		return ""
	}
	return string(out)
}