1package remoterepo 2 3import ( 4 "context" 5 "fmt" 6 7 "gitlab.com/gitlab-org/gitaly/v14/client" 8 "gitlab.com/gitlab-org/gitaly/v14/internal/git" 9 "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/storage" 10 "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" 11 "google.golang.org/grpc" 12) 13 14// Repo represents a Git repository on a different Gitaly storage 15type Repo struct { 16 *gitalypb.Repository 17 conn *grpc.ClientConn 18} 19 20// New creates a new remote Repository from its protobuf representation. 21func New(ctx context.Context, repo *gitalypb.Repository, pool *client.Pool) (*Repo, error) { 22 server, err := storage.ExtractGitalyServer(ctx, repo.GetStorageName()) 23 if err != nil { 24 return nil, fmt.Errorf("remote repository: %w", err) 25 } 26 27 cc, err := pool.Dial(ctx, server.Address, server.Token) 28 if err != nil { 29 return nil, fmt.Errorf("dial: %w", err) 30 } 31 32 return &Repo{ 33 Repository: repo, 34 conn: cc, 35 }, nil 36} 37 38// ResolveRevision will dial to the remote repository and attempt to resolve the 39// revision string via the gRPC interface. 40func (rr *Repo) ResolveRevision(ctx context.Context, revision git.Revision) (git.ObjectID, error) { 41 cli := gitalypb.NewCommitServiceClient(rr.conn) 42 resp, err := cli.FindCommit(ctx, &gitalypb.FindCommitRequest{ 43 Repository: rr.Repository, 44 Revision: []byte(revision.String()), 45 }) 46 if err != nil { 47 return "", err 48 } 49 50 oidHex := resp.GetCommit().GetId() 51 if oidHex == "" { 52 return "", git.ErrReferenceNotFound 53 } 54 55 oid, err := git.NewObjectIDFromHex(oidHex) 56 if err != nil { 57 return "", err 58 } 59 60 return oid, nil 61} 62 63// HasBranches will dial to the remote repository and check whether the repository has any branches. 64func (rr *Repo) HasBranches(ctx context.Context) (bool, error) { 65 resp, err := gitalypb.NewRepositoryServiceClient(rr.conn).HasLocalBranches( 66 ctx, &gitalypb.HasLocalBranchesRequest{Repository: rr.Repository}) 67 if err != nil { 68 return false, fmt.Errorf("has local branches: %w", err) 69 } 70 71 return resp.Value, nil 72} 73 74// GetDefaultBranch returns the default branch for the remote repository. It does so by invoking 75// `FindDefaultBranchName()`, which itself is a wrapper around `localrepo.GetDefaultBranch()`. 76// Semantics of this function thus match the localrepo semantics. 77func (rr *Repo) GetDefaultBranch(ctx context.Context) (git.ReferenceName, error) { 78 resp, err := gitalypb.NewRefServiceClient(rr.conn).FindDefaultBranchName( 79 ctx, &gitalypb.FindDefaultBranchNameRequest{Repository: rr.Repository}) 80 if err != nil { 81 return "", err 82 } 83 84 return git.ReferenceName(resp.Name), nil 85} 86