mirror of https://github.com/harness/drone.git
225 lines
6.4 KiB
Go
225 lines
6.4 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 repo
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/harness/gitness/app/api/controller"
|
|
"github.com/harness/gitness/app/auth"
|
|
"github.com/harness/gitness/app/services/protection"
|
|
"github.com/harness/gitness/git"
|
|
"github.com/harness/gitness/git/sha"
|
|
"github.com/harness/gitness/types"
|
|
"github.com/harness/gitness/types/enum"
|
|
|
|
"github.com/gotidy/ptr"
|
|
)
|
|
|
|
// ListBranches lists the branches of a repo.
|
|
func (c *Controller) ListBranches(ctx context.Context,
|
|
session *auth.Session,
|
|
repoRef string,
|
|
filter *types.BranchFilter,
|
|
) ([]types.BranchExtended, error) {
|
|
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rpcOut, err := c.git.ListBranches(ctx, &git.ListBranchesParams{
|
|
ReadParams: git.CreateReadParams(repo),
|
|
IncludeCommit: filter.IncludeCommit,
|
|
Query: filter.Query,
|
|
Sort: mapToRPCBranchSortOption(filter.Sort),
|
|
Order: mapToRPCSortOrder(filter.Order),
|
|
Page: int32(filter.Page),
|
|
PageSize: int32(filter.Size),
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("fail to get the list of branches from git: %w", err)
|
|
}
|
|
|
|
branches := rpcOut.Branches
|
|
|
|
metadata, err := c.collectBranchMetadata(ctx, repo, branches, filter.BranchMetadataOptions)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("fail to collect branch metadata: %w", err)
|
|
}
|
|
|
|
response := make([]types.BranchExtended, len(branches))
|
|
for i := range branches {
|
|
response[i].Branch, err = controller.MapBranch(branches[i])
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to map branch: %w", err)
|
|
}
|
|
|
|
response[i].IsDefault = repo.DefaultBranch == branches[i].Name
|
|
|
|
metadata.apply(i, &response[i])
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
// collectBranchMetadata collects the metadata for the provided list of branches.
|
|
// The metadata includes check, rules, pull requests, and branch divergences.
|
|
// Each of these would be returned only if the corresponding option is true.
|
|
func (c *Controller) collectBranchMetadata(
|
|
ctx context.Context,
|
|
repo *types.Repository,
|
|
branches []git.Branch,
|
|
options types.BranchMetadataOptions,
|
|
) (branchMetadataOutput, error) {
|
|
var (
|
|
checkSummary map[sha.SHA]types.CheckCountSummary
|
|
branchRuleMap map[string][]types.RuleInfo
|
|
pullReqMap map[string][]*types.PullReq
|
|
divergences *git.GetCommitDivergencesOutput
|
|
err error
|
|
)
|
|
|
|
if options.IncludeChecks {
|
|
commitSHAs := make([]string, len(branches))
|
|
for i := range branches {
|
|
commitSHAs[i] = branches[i].SHA.String()
|
|
}
|
|
|
|
checkSummary, err = c.checkStore.ResultSummary(ctx, repo.ID, commitSHAs)
|
|
if err != nil {
|
|
return branchMetadataOutput{}, fmt.Errorf("fail to fetch check summary for commits: %w", err)
|
|
}
|
|
}
|
|
|
|
if options.IncludeRules {
|
|
rules, err := c.protectionManager.ForRepository(ctx, repo.ID)
|
|
if err != nil {
|
|
return branchMetadataOutput{}, fmt.Errorf("failed to fetch protection rules for the repository: %w", err)
|
|
}
|
|
|
|
branchRuleMap = make(map[string][]types.RuleInfo)
|
|
for i := range branches {
|
|
branchName := branches[i].Name
|
|
|
|
branchRuleInfos, err := protection.GetRuleInfos(
|
|
rules,
|
|
repo.DefaultBranch,
|
|
branchName,
|
|
protection.RuleInfoFilterStatusActive,
|
|
protection.RuleInfoFilterTypeBranch)
|
|
if err != nil {
|
|
return branchMetadataOutput{}, fmt.Errorf("failed get branch rule infos: %w", err)
|
|
}
|
|
|
|
branchRuleMap[branchName] = branchRuleInfos
|
|
}
|
|
}
|
|
|
|
if options.IncludePullReqs {
|
|
branchNames := make([]string, len(branches))
|
|
for i := range branches {
|
|
branchNames[i] = branches[i].Name
|
|
}
|
|
|
|
pullReqMap, err = c.pullReqStore.ListOpenByBranchName(ctx, repo.ID, branchNames)
|
|
if err != nil {
|
|
return branchMetadataOutput{}, fmt.Errorf("fail to fetch pull requests per branch: %w", err)
|
|
}
|
|
}
|
|
|
|
if options.MaxDivergence > 0 {
|
|
readParams := git.CreateReadParams(repo)
|
|
|
|
divergenceRequests := make([]git.CommitDivergenceRequest, len(branches))
|
|
for i := range branches {
|
|
divergenceRequests[i].From = branches[i].Name
|
|
divergenceRequests[i].To = repo.DefaultBranch
|
|
}
|
|
|
|
divergences, err = c.git.GetCommitDivergences(ctx, &git.GetCommitDivergencesParams{
|
|
ReadParams: readParams,
|
|
MaxCount: int32(options.MaxDivergence),
|
|
Requests: divergenceRequests,
|
|
})
|
|
if err != nil {
|
|
return branchMetadataOutput{}, fmt.Errorf("fail to fetch commit divergences: %w", err)
|
|
}
|
|
}
|
|
|
|
return branchMetadataOutput{
|
|
checkSummary: checkSummary,
|
|
branchRuleMap: branchRuleMap,
|
|
pullReqMap: pullReqMap,
|
|
divergences: divergences,
|
|
}, nil
|
|
}
|
|
|
|
type branchMetadataOutput struct {
|
|
checkSummary map[sha.SHA]types.CheckCountSummary
|
|
branchRuleMap map[string][]types.RuleInfo
|
|
pullReqMap map[string][]*types.PullReq
|
|
divergences *git.GetCommitDivergencesOutput
|
|
}
|
|
|
|
func (metadata branchMetadataOutput) apply(
|
|
idx int,
|
|
branch *types.BranchExtended,
|
|
) {
|
|
if metadata.checkSummary != nil {
|
|
branch.CheckSummary = ptr.Of(metadata.checkSummary[branch.SHA])
|
|
}
|
|
|
|
if metadata.branchRuleMap != nil {
|
|
branch.Rules = metadata.branchRuleMap[branch.Name]
|
|
}
|
|
|
|
if metadata.pullReqMap != nil {
|
|
branch.PullRequests = metadata.pullReqMap[branch.Name]
|
|
}
|
|
|
|
if metadata.divergences != nil {
|
|
branch.CommitDivergence = ptr.Of(types.CommitDivergence(metadata.divergences.Divergences[idx]))
|
|
}
|
|
}
|
|
|
|
func mapToRPCBranchSortOption(o enum.BranchSortOption) git.BranchSortOption {
|
|
switch o {
|
|
case enum.BranchSortOptionDate:
|
|
return git.BranchSortOptionDate
|
|
case enum.BranchSortOptionName:
|
|
return git.BranchSortOptionName
|
|
case enum.BranchSortOptionDefault:
|
|
return git.BranchSortOptionDefault
|
|
default:
|
|
// no need to error out - just use default for sorting
|
|
return git.BranchSortOptionDefault
|
|
}
|
|
}
|
|
|
|
func mapToRPCSortOrder(o enum.Order) git.SortOrder {
|
|
switch o {
|
|
case enum.OrderAsc:
|
|
return git.SortOrderAsc
|
|
case enum.OrderDesc:
|
|
return git.SortOrderDesc
|
|
case enum.OrderDefault:
|
|
return git.SortOrderDefault
|
|
default:
|
|
// no need to error out - just use default for sorting
|
|
return git.SortOrderDefault
|
|
}
|
|
}
|