1// Command fetch_repo is similar to "go get -d" but it works even if the given 2// repository path is not a buildable Go package and it checks out a specific 3// revision rather than the latest revision. 4// 5// The difference between fetch_repo and "git clone" or {new_,}git_repository is 6// that fetch_repo recognizes import redirection of Go and it supports other 7// version control systems than git. 8// 9// These differences help us to manage external Go repositories in the manner of 10// Bazel. 11package main 12 13import ( 14 "flag" 15 "fmt" 16 "log" 17 18 "golang.org/x/tools/go/vcs" 19) 20 21var ( 22 remote = flag.String("remote", "", "The URI of the remote repository. Must be used with the --vcs flag.") 23 cmd = flag.String("vcs", "", "Version control system to use to fetch the repository. Should be one of: git,hg,svn,bzr. Must be used with the --remote flag.") 24 rev = flag.String("rev", "", "target revision") 25 dest = flag.String("dest", "", "destination directory") 26 importpath = flag.String("importpath", "", "Go importpath to the repository fetch") 27 28 // Used for overriding in tests to disable network calls. 29 repoRootForImportPath = vcs.RepoRootForImportPath 30) 31 32func getRepoRoot(remote, cmd, importpath string) (*vcs.RepoRoot, error) { 33 if (cmd == "") != (remote == "") { 34 return nil, fmt.Errorf("--remote should be used with the --vcs flag. If this is an import path, use --importpath instead.") 35 } 36 37 if cmd != "" && remote != "" { 38 v := vcs.ByCmd(cmd) 39 if v == nil { 40 return nil, fmt.Errorf("invalid VCS type: %s", cmd) 41 } 42 return &vcs.RepoRoot{ 43 VCS: v, 44 Repo: remote, 45 Root: importpath, 46 }, nil 47 } 48 49 // User did not give us complete information for VCS / Remote. 50 // Try to figure out the information from the import path. 51 r, err := repoRootForImportPath(importpath, true) 52 if err != nil { 53 return nil, err 54 } 55 if importpath != r.Root { 56 return nil, fmt.Errorf("not a root of a repository: %s", importpath) 57 } 58 return r, nil 59} 60 61func run() error { 62 r, err := getRepoRoot(*remote, *cmd, *importpath) 63 if err != nil { 64 return err 65 } 66 return r.VCS.CreateAtRev(*dest, r.Repo, *rev) 67} 68 69func main() { 70 flag.Parse() 71 72 if err := run(); err != nil { 73 log.Fatal(err) 74 } 75} 76