mirror of https://github.com/harness/drone.git
241 lines
5.7 KiB
Go
241 lines
5.7 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 git
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
)
|
|
|
|
// TreeNodeType specifies the different types of nodes in a git tree.
|
|
// IMPORTANT: has to be consistent with rpc.TreeNodeType (proto).
|
|
type TreeNodeType string
|
|
|
|
const (
|
|
TreeNodeTypeTree TreeNodeType = "tree"
|
|
TreeNodeTypeBlob TreeNodeType = "blob"
|
|
TreeNodeTypeCommit TreeNodeType = "commit"
|
|
)
|
|
|
|
// TreeNodeMode specifies the different modes of a node in a git tree.
|
|
// IMPORTANT: has to be consistent with rpc.TreeNodeMode (proto).
|
|
type TreeNodeMode string
|
|
|
|
const (
|
|
TreeNodeModeFile TreeNodeMode = "file"
|
|
TreeNodeModeSymlink TreeNodeMode = "symlink"
|
|
TreeNodeModeExec TreeNodeMode = "exec"
|
|
TreeNodeModeTree TreeNodeMode = "tree"
|
|
TreeNodeModeCommit TreeNodeMode = "commit"
|
|
)
|
|
|
|
type TreeNode struct {
|
|
Type TreeNodeType
|
|
Mode TreeNodeMode
|
|
SHA string // TODO: make sha.SHA
|
|
Name string
|
|
Path string
|
|
}
|
|
|
|
type ListTreeNodeParams struct {
|
|
ReadParams
|
|
// GitREF is a git reference (branch / tag / commit SHA)
|
|
GitREF string
|
|
Path string
|
|
IncludeLatestCommit bool
|
|
}
|
|
|
|
type ListTreeNodeOutput struct {
|
|
Nodes []TreeNode
|
|
}
|
|
|
|
type GetTreeNodeParams struct {
|
|
ReadParams
|
|
// GitREF is a git reference (branch / tag / commit SHA)
|
|
GitREF string
|
|
Path string
|
|
IncludeLatestCommit bool
|
|
}
|
|
|
|
type GetTreeNodeOutput struct {
|
|
Node TreeNode
|
|
Commit *Commit
|
|
}
|
|
|
|
func (s *Service) GetTreeNode(ctx context.Context, params *GetTreeNodeParams) (*GetTreeNodeOutput, error) {
|
|
if err := params.Validate(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
repoPath := getFullPathForRepo(s.reposRoot, params.RepoUID)
|
|
|
|
gitNode, err := s.git.GetTreeNode(ctx, repoPath, params.GitREF, params.Path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to find node '%s' in '%s': %w", params.Path, params.GitREF, err)
|
|
}
|
|
|
|
node, err := mapTreeNode(gitNode)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to map rpc node: %w", err)
|
|
}
|
|
|
|
if !params.IncludeLatestCommit {
|
|
return &GetTreeNodeOutput{
|
|
Node: node,
|
|
}, nil
|
|
}
|
|
|
|
pathDetails, err := s.git.PathsDetails(ctx, repoPath, params.GitREF, []string{params.Path})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get path details for '%s' in '%s': %w", params.Path, params.GitREF, err)
|
|
}
|
|
|
|
if len(pathDetails) != 1 || pathDetails[0].LastCommit == nil {
|
|
return nil, fmt.Errorf("failed to get details for the path %s", params.Path)
|
|
}
|
|
var commit *Commit
|
|
if pathDetails[0].LastCommit != nil {
|
|
commit, err = mapCommit(pathDetails[0].LastCommit)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to map rpc commit: %w", err)
|
|
}
|
|
}
|
|
|
|
return &GetTreeNodeOutput{
|
|
Node: node,
|
|
Commit: commit,
|
|
}, nil
|
|
}
|
|
|
|
func (s *Service) ListTreeNodes(ctx context.Context, params *ListTreeNodeParams) (*ListTreeNodeOutput, error) {
|
|
if err := params.Validate(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
repoPath := getFullPathForRepo(s.reposRoot, params.RepoUID)
|
|
|
|
res, err := s.git.ListTreeNodes(
|
|
ctx,
|
|
repoPath,
|
|
params.GitREF,
|
|
params.Path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list tree nodes: %w", err)
|
|
}
|
|
|
|
nodes := make([]TreeNode, len(res))
|
|
for i := range res {
|
|
n, err := mapTreeNode(&res[i])
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to map rpc node: %w", err)
|
|
}
|
|
|
|
nodes[i] = n
|
|
}
|
|
|
|
return &ListTreeNodeOutput{
|
|
Nodes: nodes,
|
|
}, nil
|
|
}
|
|
|
|
type ListPathsParams struct {
|
|
ReadParams
|
|
// GitREF is a git reference (branch / tag / commit SHA)
|
|
GitREF string
|
|
IncludeDirectories bool
|
|
}
|
|
|
|
type ListPathsOutput struct {
|
|
Files []string
|
|
Directories []string
|
|
}
|
|
|
|
func (s *Service) ListPaths(ctx context.Context, params *ListPathsParams) (*ListPathsOutput, error) {
|
|
if err := params.Validate(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
repoPath := getFullPathForRepo(s.reposRoot, params.RepoUID)
|
|
|
|
files, dirs, err := s.git.ListPaths(
|
|
ctx,
|
|
repoPath,
|
|
params.GitREF,
|
|
params.IncludeDirectories,
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list paths: %w", err)
|
|
}
|
|
|
|
return &ListPathsOutput{
|
|
Files: files,
|
|
Directories: dirs,
|
|
},
|
|
nil
|
|
}
|
|
|
|
type PathsDetailsParams struct {
|
|
ReadParams
|
|
GitREF string
|
|
Paths []string
|
|
}
|
|
|
|
type PathsDetailsOutput struct {
|
|
Details []PathDetails
|
|
}
|
|
|
|
type PathDetails struct {
|
|
Path string `json:"path"`
|
|
LastCommit *Commit `json:"last_commit,omitempty"`
|
|
}
|
|
|
|
func (s *Service) PathsDetails(ctx context.Context, params PathsDetailsParams) (PathsDetailsOutput, error) {
|
|
if err := params.Validate(); err != nil {
|
|
return PathsDetailsOutput{}, err
|
|
}
|
|
|
|
repoPath := getFullPathForRepo(s.reposRoot, params.RepoUID)
|
|
|
|
pathsDetails, err := s.git.PathsDetails(
|
|
ctx,
|
|
repoPath,
|
|
params.GitREF,
|
|
params.Paths)
|
|
if err != nil {
|
|
return PathsDetailsOutput{}, fmt.Errorf("failed to get path details in '%s': %w", params.GitREF, err)
|
|
}
|
|
|
|
details := make([]PathDetails, len(pathsDetails))
|
|
for i, pathDetail := range pathsDetails {
|
|
var lastCommit *Commit
|
|
|
|
if pathDetail.LastCommit != nil {
|
|
lastCommit, err = mapCommit(pathDetail.LastCommit)
|
|
if err != nil {
|
|
return PathsDetailsOutput{}, fmt.Errorf("failed to map last commit: %w", err)
|
|
}
|
|
}
|
|
|
|
details[i] = PathDetails{
|
|
Path: pathDetail.Path,
|
|
LastCommit: lastCommit,
|
|
}
|
|
}
|
|
|
|
return PathsDetailsOutput{
|
|
Details: details,
|
|
}, nil
|
|
}
|