drone/gitrpc/internal/service/tree.go

150 lines
4.0 KiB
Go

// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package service
import (
"context"
"fmt"
"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/status"
)
func (s RepositoryService) ListTreeNodes(
request *rpc.ListTreeNodesRequest,
stream rpc.RepositoryService_ListTreeNodesServer,
) error {
ctx := stream.Context()
base := request.GetBase()
if base == nil {
return types.ErrBaseCannotBeEmpty
}
repoPath := getFullPathForRepo(s.reposRoot, base.GetRepoUid())
gitNodes, err := s.adapter.ListTreeNodes(ctx, repoPath,
request.GetGitRef(), request.GetPath())
if err != nil {
return processGitErrorf(err, "failed to list tree nodes")
}
log.Ctx(ctx).Trace().Msgf("git adapter returned %d nodes", len(gitNodes))
for _, gitNode := range gitNodes {
err = stream.Send(&rpc.ListTreeNodesResponse{
Node: &rpc.TreeNode{
Type: mapGitNodeType(gitNode.NodeType),
Mode: mapGitMode(gitNode.Mode),
Sha: gitNode.Sha,
Name: gitNode.Name,
Path: gitNode.Path,
},
})
if err != nil {
return status.Errorf(codes.Internal, "failed to send node: %v", err)
}
}
return nil
}
func (s RepositoryService) GetTreeNode(ctx context.Context,
request *rpc.GetTreeNodeRequest,
) (*rpc.GetTreeNodeResponse, error) {
base := request.GetBase()
if base == nil {
return nil, types.ErrBaseCannotBeEmpty
}
repoPath := getFullPathForRepo(s.reposRoot, base.GetRepoUid())
gitNode, err := s.adapter.GetTreeNode(ctx, repoPath, request.GitRef, request.Path)
if err != nil {
return nil, processGitErrorf(err, "failed to find node '%s' in '%s'", request.Path, request.GitRef)
}
res := &rpc.GetTreeNodeResponse{
Node: &rpc.TreeNode{
Type: mapGitNodeType(gitNode.NodeType),
Mode: mapGitMode(gitNode.Mode),
Sha: gitNode.Sha,
Name: gitNode.Name,
Path: gitNode.Path,
},
}
if !request.GetIncludeLatestCommit() {
return res, nil
}
pathDetails, err := s.adapter.PathsDetails(ctx, repoPath, request.GitRef, []string{request.Path})
if err != nil {
return nil, processGitErrorf(err, "failed to get path details for '%s' in '%s'", request.Path, request.GitRef)
}
if len(pathDetails) != 1 || pathDetails[0].LastCommit == nil {
return nil, fmt.Errorf("failed to get details for the path %s", request.Path)
}
res.Commit, err = mapGitCommit(pathDetails[0].LastCommit)
if err != nil {
return nil, err
}
return res, nil
}
func (s RepositoryService) PathsDetails(ctx context.Context,
request *rpc.PathsDetailsRequest,
) (*rpc.PathsDetailsResponse, error) {
base := request.GetBase()
if base == nil {
return nil, types.ErrBaseCannotBeEmpty
}
repoPath := getFullPathForRepo(s.reposRoot, base.GetRepoUid())
pathsDetails, err := s.adapter.PathsDetails(ctx, repoPath, request.GetGitRef(), request.GetPaths())
if err != nil {
return nil, processGitErrorf(err, "failed to get path details in '%s'", request.GetGitRef())
}
details := make([]*rpc.PathDetails, len(pathsDetails))
for i, pathDetails := range pathsDetails {
var lastCommit *rpc.Commit
if pathDetails.LastCommit != nil {
lastCommit, err = mapGitCommit(pathDetails.LastCommit)
if err != nil {
return nil, fmt.Errorf("failed to map commit: %w", err)
}
}
details[i] = &rpc.PathDetails{
Path: pathDetails.Path,
LastCommit: lastCommit,
Size: pathDetails.Size,
}
}
return &rpc.PathsDetailsResponse{
PathDetails: details,
}, nil
}