xref: /aosp_15_r20/external/bazelbuild-rules_go/go/tools/fetch_repo/main.go (revision 9bb1b549b6a84214c53be0924760be030e66b93a)
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