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)
39 return fmt.Errorf("writable git_tree mount is not supported")
44 // ExtractTree extracts the specified tree into dir, which is an
45 // existing empty local directory.
46 func (gm gitMount) extractTree(ac IArvadosClient, dir string, token string) error {
51 baseURL, err := ac.Discovery("gitUrl")
53 return fmt.Errorf("discover gitUrl from API: %s", err)
54 } else if _, ok := baseURL.(string); !ok {
55 return fmt.Errorf("discover gitUrl from API: expected string, found %T", baseURL)
58 u, err := url.Parse(baseURL.(string))
60 return fmt.Errorf("parse gitUrl %q: %s", baseURL, err)
62 u, err = u.Parse("/" + gm.UUID + ".git")
64 return fmt.Errorf("build git url from %q, %q: %s", baseURL, gm.UUID, err)
66 store := memory.NewStorage()
67 repo, err := git.Init(store, osfs.New(dir))
69 return fmt.Errorf("init repo: %s", err)
71 _, err = repo.CreateRemote(&git_config.RemoteConfig{
73 URLs: []string{u.String()},
76 return fmt.Errorf("create remote %q: %s", u.String(), err)
78 err = repo.Fetch(&git.FetchOptions{
80 Auth: git_http.NewBasicAuth("none", token),
83 return fmt.Errorf("git fetch %q: %s", u.String(), err)
85 wt, err := repo.Worktree()
87 return fmt.Errorf("worktree failed: %s", err)
89 err = wt.Checkout(&git.CheckoutOptions{
90 Hash: git_plumbing.NewHash(gm.Commit),
93 return fmt.Errorf("checkout failed: %s", err)
95 err = os.Chmod(dir, 0755)
97 return fmt.Errorf("chmod %o %q: %s", 0755, dir, err)