X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/4343e1f1035baaa22f117d119c6e6bc35b1e385b..641ef213571f793bb290a182dee3c4325bc85096:/services/crunch-run/git_mount.go diff --git a/services/crunch-run/git_mount.go b/services/crunch-run/git_mount.go index a792741ae4..c312a532e4 100644 --- a/services/crunch-run/git_mount.go +++ b/services/crunch-run/git_mount.go @@ -1,12 +1,18 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + package main import ( "fmt" "net/url" + "os" + "path/filepath" + "regexp" "git.curoverse.com/arvados.git/sdk/go/arvados" - "git.curoverse.com/arvados.git/sdk/go/arvadostest" - "gopkg.in/src-d/go-billy.v3/osfs" + "gopkg.in/src-d/go-billy.v4/osfs" git "gopkg.in/src-d/go-git.v4" git_config "gopkg.in/src-d/go-git.v4/config" git_plumbing "gopkg.in/src-d/go-git.v4/plumbing" @@ -16,16 +22,33 @@ import ( type gitMount arvados.Mount +var ( + sha1re = regexp.MustCompile(`^[0-9a-f]{40}$`) + repoUUIDre = regexp.MustCompile(`^[0-9a-z]{5}-s0uqq-[0-9a-z]{15}$`) +) + func (gm gitMount) validate() error { - if gm.Path != "/" { - return fmt.Errorf("cannot mount git_tree path %q -- only \"/\" is supported", gm.Path) + if gm.Path != "" && gm.Path != "/" { + return fmt.Errorf("cannot mount git_tree with path %q -- only \"/\" is supported", gm.Path) + } + if !sha1re.MatchString(gm.Commit) { + return fmt.Errorf("cannot mount git_tree with commit %q -- must be a 40-char SHA1", gm.Commit) + } + if gm.RepositoryName != "" || gm.GitURL != "" { + return fmt.Errorf("cannot mount git_tree -- repository_name and git_url must be empty") + } + if !repoUUIDre.MatchString(gm.UUID) { + return fmt.Errorf("cannot mount git_tree with uuid %q -- must be a repository UUID", gm.UUID) + } + if gm.Writable { + return fmt.Errorf("writable git_tree mount is not supported") } return nil } // ExtractTree extracts the specified tree into dir, which is an // existing empty local directory. -func (gm gitMount) extractTree(ac IArvadosClient, dir string) error { +func (gm gitMount) extractTree(ac IArvadosClient, dir string, token string) error { err := gm.validate() if err != nil { return err @@ -33,7 +56,10 @@ func (gm gitMount) extractTree(ac IArvadosClient, dir string) error { baseURL, err := ac.Discovery("gitUrl") if err != nil { return fmt.Errorf("discover gitUrl from API: %s", err) + } else if _, ok := baseURL.(string); !ok { + return fmt.Errorf("discover gitUrl from API: expected string, found %T", baseURL) } + u, err := url.Parse(baseURL.(string)) if err != nil { return fmt.Errorf("parse gitUrl %q: %s", baseURL, err) @@ -56,7 +82,10 @@ func (gm gitMount) extractTree(ac IArvadosClient, dir string) error { } err = repo.Fetch(&git.FetchOptions{ RemoteName: "origin", - Auth: git_http.NewBasicAuth("none", arvadostest.ActiveToken), + Auth: &git_http.BasicAuth{ + Username: "none", + Password: token, + }, }) if err != nil { return fmt.Errorf("git fetch %q: %s", u.String(), err) @@ -71,5 +100,18 @@ func (gm gitMount) extractTree(ac IArvadosClient, dir string) error { if err != nil { return fmt.Errorf("checkout failed: %s", err) } + err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + // copy user rx bits to group and other, in case + // prevailing umask is more restrictive than 022 + mode := info.Mode() + mode = mode | ((mode >> 3) & 050) | ((mode >> 6) & 5) + return os.Chmod(path, mode) + }) + if err != nil { + return fmt.Errorf("chmod -R %q: %s", dir, err) + } return nil }