8 "git.curoverse.com/arvados.git/sdk/go/arvados"
9 "gopkg.in/src-d/go-billy.v3/osfs"
10 git "gopkg.in/src-d/go-git.v4"
11 git_config "gopkg.in/src-d/go-git.v4/config"
12 git_plumbing "gopkg.in/src-d/go-git.v4/plumbing"
13 git_http "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
14 "gopkg.in/src-d/go-git.v4/storage/memory"
17 type gitMount arvados.Mount
20 sha1re = regexp.MustCompile(`^[0-9a-f]{40}$`)
21 repoUUIDre = regexp.MustCompile(`^[0-9a-z]{5}-s0uqq-[0-9a-z]{15}$`)
24 func (gm gitMount) validate() error {
25 if gm.Path != "" && gm.Path != "/" {
26 return fmt.Errorf("cannot mount git_tree with path %q -- only \"/\" is supported", gm.Path)
28 if !sha1re.MatchString(gm.Commit) {
29 return fmt.Errorf("cannot mount git_tree with commit %q -- must be a 40-char SHA1", gm.Commit)
31 if gm.RepositoryName != "" || gm.GitURL != "" {
32 return fmt.Errorf("cannot mount git_tree -- repository_name and git_url must be empty")
34 if !repoUUIDre.MatchString(gm.UUID) {
35 return fmt.Errorf("cannot mount git_tree with uuid %q -- must be a repository UUID", gm.UUID)
40 // ExtractTree extracts the specified tree into dir, which is an
41 // existing empty local directory.
42 func (gm gitMount) extractTree(ac IArvadosClient, dir string, token string) error {
47 baseURL, err := ac.Discovery("gitUrl")
49 return fmt.Errorf("discover gitUrl from API: %s", err)
50 } else if _, ok := baseURL.(string); !ok {
51 return fmt.Errorf("discover gitUrl from API: expected string, found %T", baseURL)
54 u, err := url.Parse(baseURL.(string))
56 return fmt.Errorf("parse gitUrl %q: %s", baseURL, err)
58 u, err = u.Parse("/" + gm.UUID + ".git")
60 return fmt.Errorf("build git url from %q, %q: %s", baseURL, gm.UUID, err)
62 store := memory.NewStorage()
63 repo, err := git.Init(store, osfs.New(dir))
65 return fmt.Errorf("init repo: %s", err)
67 _, err = repo.CreateRemote(&git_config.RemoteConfig{
69 URLs: []string{u.String()},
72 return fmt.Errorf("create remote %q: %s", u.String(), err)
74 err = repo.Fetch(&git.FetchOptions{
76 Auth: git_http.NewBasicAuth("none", token),
79 return fmt.Errorf("git fetch %q: %s", u.String(), err)
81 wt, err := repo.Worktree()
83 return fmt.Errorf("worktree failed: %s", err)
85 err = wt.Checkout(&git.CheckoutOptions{
86 Hash: git_plumbing.NewHash(gm.Commit),
89 return fmt.Errorf("checkout failed: %s", err)