9 "git.curoverse.com/arvados.git/sdk/go/arvados"
10 "gopkg.in/src-d/go-billy.v3/osfs"
11 git "gopkg.in/src-d/go-git.v4"
12 git_config "gopkg.in/src-d/go-git.v4/config"
13 git_plumbing "gopkg.in/src-d/go-git.v4/plumbing"
14 git_http "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
15 "gopkg.in/src-d/go-git.v4/storage/memory"
18 type gitMount arvados.Mount
21 sha1re = regexp.MustCompile(`^[0-9a-f]{40}$`)
22 repoUUIDre = regexp.MustCompile(`^[0-9a-z]{5}-s0uqq-[0-9a-z]{15}$`)
25 func (gm gitMount) validate() error {
26 if gm.Path != "" && gm.Path != "/" {
27 return fmt.Errorf("cannot mount git_tree with path %q -- only \"/\" is supported", gm.Path)
29 if !sha1re.MatchString(gm.Commit) {
30 return fmt.Errorf("cannot mount git_tree with commit %q -- must be a 40-char SHA1", gm.Commit)
32 if gm.RepositoryName != "" || gm.GitURL != "" {
33 return fmt.Errorf("cannot mount git_tree -- repository_name and git_url must be empty")
35 if !repoUUIDre.MatchString(gm.UUID) {
36 return fmt.Errorf("cannot mount git_tree with uuid %q -- must be a repository UUID", gm.UUID)
41 // ExtractTree extracts the specified tree into dir, which is an
42 // existing empty local directory.
43 func (gm gitMount) extractTree(ac IArvadosClient, dir string, token string) error {
48 baseURL, err := ac.Discovery("gitUrl")
50 return fmt.Errorf("discover gitUrl from API: %s", err)
51 } else if _, ok := baseURL.(string); !ok {
52 return fmt.Errorf("discover gitUrl from API: expected string, found %T", baseURL)
55 u, err := url.Parse(baseURL.(string))
57 return fmt.Errorf("parse gitUrl %q: %s", baseURL, err)
59 u, err = u.Parse("/" + gm.UUID + ".git")
61 return fmt.Errorf("build git url from %q, %q: %s", baseURL, gm.UUID, err)
63 store := memory.NewStorage()
64 repo, err := git.Init(store, osfs.New(dir))
66 return fmt.Errorf("init repo: %s", err)
68 _, err = repo.CreateRemote(&git_config.RemoteConfig{
70 URLs: []string{u.String()},
73 return fmt.Errorf("create remote %q: %s", u.String(), err)
75 err = repo.Fetch(&git.FetchOptions{
77 Auth: git_http.NewBasicAuth("none", token),
80 return fmt.Errorf("git fetch %q: %s", u.String(), err)
82 wt, err := repo.Worktree()
84 return fmt.Errorf("worktree failed: %s", err)
86 err = wt.Checkout(&git.CheckoutOptions{
87 Hash: git_plumbing.NewHash(gm.Commit),
90 return fmt.Errorf("checkout failed: %s", err)
92 err = os.Chmod(dir, 0755)
94 return fmt.Errorf("chmod %o %q: %s", 0755, dir, err)