mirror of https://github.com/harness/drone.git
170 lines
5.0 KiB
Go
170 lines
5.0 KiB
Go
// Copyright 2022 Harness Inc. All rights reserved.
|
|
// Use of this source code is governed by the Polyform Free Trial License
|
|
// that can be found in the LICENSE.md file for this repository.
|
|
|
|
package service
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
|
|
"github.com/harness/gitness/gitrpc/internal/types"
|
|
"github.com/harness/gitness/gitrpc/rpc"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/metadata"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
func (s RepositoryService) GetCommit(ctx context.Context,
|
|
request *rpc.GetCommitRequest) (*rpc.GetCommitResponse, error) {
|
|
base := request.GetBase()
|
|
if base == nil {
|
|
return nil, types.ErrBaseCannotBeEmpty
|
|
}
|
|
|
|
// ensure the provided SHA is valid (and not a reference)
|
|
sha := request.GetSha()
|
|
if !isValidGitSHA(sha) {
|
|
return nil, status.Errorf(codes.InvalidArgument, "the provided commit sha '%s' is of invalid format.", sha)
|
|
}
|
|
|
|
repoPath := getFullPathForRepo(s.reposRoot, base.GetRepoUid())
|
|
|
|
gitCommit, err := s.adapter.GetCommit(ctx, repoPath, sha)
|
|
if err != nil {
|
|
return nil, processGitErrorf(err, "failed to get commit")
|
|
}
|
|
|
|
commit, err := mapGitCommit(gitCommit)
|
|
if err != nil {
|
|
return nil, status.Errorf(codes.Internal, "failed to map git commit: %v", err)
|
|
}
|
|
|
|
return &rpc.GetCommitResponse{
|
|
Commit: commit,
|
|
}, nil
|
|
}
|
|
|
|
func (s RepositoryService) ListCommits(request *rpc.ListCommitsRequest,
|
|
stream rpc.RepositoryService_ListCommitsServer) error {
|
|
base := request.GetBase()
|
|
if base == nil {
|
|
return types.ErrBaseCannotBeEmpty
|
|
}
|
|
|
|
ctx := stream.Context()
|
|
repoPath := getFullPathForRepo(s.reposRoot, base.GetRepoUid())
|
|
|
|
gitCommits, renameDetails, err := s.adapter.ListCommits(ctx, repoPath, request.GetGitRef(),
|
|
int(request.GetPage()), int(request.GetLimit()), types.CommitFilter{AfterRef: request.After,
|
|
Path: request.Path,
|
|
Since: request.Since,
|
|
Until: request.Until,
|
|
Committer: request.Committer})
|
|
if err != nil {
|
|
return processGitErrorf(err, "failed to get list of commits")
|
|
}
|
|
|
|
// try to get total commits between gitref and After refs
|
|
totalCommits := 0
|
|
if request.Page == 1 && len(gitCommits) < int(request.Limit) {
|
|
totalCommits = len(gitCommits)
|
|
} else if request.After != "" && request.GitRef != request.After {
|
|
div, err := s.adapter.GetCommitDivergences(ctx, repoPath, []types.CommitDivergenceRequest{
|
|
{From: request.GitRef, To: request.After},
|
|
}, 0)
|
|
if err != nil {
|
|
return processGitErrorf(err, "failed to get total commits")
|
|
}
|
|
if len(div) > 0 {
|
|
totalCommits = int(div[0].Ahead)
|
|
}
|
|
}
|
|
|
|
log.Ctx(ctx).Trace().Msgf("git adapter returned %d commits", len(gitCommits))
|
|
header := metadata.New(map[string]string{"total-commits": strconv.Itoa(totalCommits)})
|
|
if err := stream.SendHeader(header); err != nil {
|
|
return ErrInternalf("unable to send 'total-commits' header", err)
|
|
}
|
|
|
|
for i := range gitCommits {
|
|
var commit *rpc.Commit
|
|
commit, err = mapGitCommit(&gitCommits[i])
|
|
if err != nil {
|
|
return status.Errorf(codes.Internal, "failed to map git commit: %v", err)
|
|
}
|
|
|
|
err = stream.Send(&rpc.ListCommitsResponse{
|
|
Commit: commit,
|
|
RenameDetails: mapRenameDetails(renameDetails),
|
|
})
|
|
if err != nil {
|
|
return status.Errorf(codes.Internal, "failed to send commit: %v", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s RepositoryService) GetCommitDivergences(ctx context.Context,
|
|
request *rpc.GetCommitDivergencesRequest) (*rpc.GetCommitDivergencesResponse, error) {
|
|
base := request.GetBase()
|
|
if base == nil {
|
|
return nil, types.ErrBaseCannotBeEmpty
|
|
}
|
|
|
|
repoPath := getFullPathForRepo(s.reposRoot, base.GetRepoUid())
|
|
|
|
// map to gitea requests
|
|
requests := request.GetRequests()
|
|
if requests == nil {
|
|
return nil, status.Error(codes.InvalidArgument, "requests is nil")
|
|
}
|
|
giteaDivergenceRequests := make([]types.CommitDivergenceRequest, len(requests))
|
|
for i := range requests {
|
|
if requests[i] == nil {
|
|
return nil, status.Errorf(codes.InvalidArgument, "requests[%d] is nil", i)
|
|
}
|
|
giteaDivergenceRequests[i].From = requests[i].From
|
|
giteaDivergenceRequests[i].To = requests[i].To
|
|
}
|
|
|
|
// call gitea
|
|
giteaDivergenceResponses, err := s.adapter.GetCommitDivergences(ctx, repoPath,
|
|
giteaDivergenceRequests, request.GetMaxCount())
|
|
if err != nil {
|
|
return nil, processGitErrorf(err, "failed to get diverging commits")
|
|
}
|
|
|
|
// map to rpc response
|
|
response := &rpc.GetCommitDivergencesResponse{
|
|
Divergences: make([]*rpc.CommitDivergence, len(giteaDivergenceResponses)),
|
|
}
|
|
for i := range giteaDivergenceResponses {
|
|
response.Divergences[i] = &rpc.CommitDivergence{
|
|
Ahead: giteaDivergenceResponses[i].Ahead,
|
|
Behind: giteaDivergenceResponses[i].Behind,
|
|
}
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
func (s RepositoryService) MergeBase(ctx context.Context,
|
|
r *rpc.MergeBaseRequest,
|
|
) (*rpc.MergeBaseResponse, error) {
|
|
base := r.GetBase()
|
|
repoPath := getFullPathForRepo(s.reposRoot, base.GetRepoUid())
|
|
|
|
mergeBase, _, err := s.adapter.GetMergeBase(ctx, repoPath, "", r.Ref1, r.Ref2)
|
|
if err != nil {
|
|
return nil, processGitErrorf(err, "failed to find merge base")
|
|
}
|
|
|
|
return &rpc.MergeBaseResponse{
|
|
MergeBaseSha: mergeBase,
|
|
}, nil
|
|
}
|