feat: [CODE-2498]: Add time and author filter params to list commits page (#3000)

* Remove redundant consts and annotate errors
* Add a Regex bool field to the api.CommitFilter
* Add use author/commiter regex bool to list commit filter
* Merge branch 'main' into dd/commit-time-author-filter
* Add commiter IDs
* Merge branch 'main' into dd/commit-time-author-filter
* Merge branch 'main' into dd/commit-time-author-filter
* Merge branch 'main' into dd/commit-time-author-filter
* Add regex quote for author
* Add time and author filter params to list commits page
This commit is contained in:
Darko Draskovic 2024-11-21 10:31:32 +00:00 committed by Harness
parent 117cadcdcf
commit 335eaa73c1
6 changed files with 102 additions and 12 deletions

View File

@ -17,12 +17,16 @@ package repo
import (
"context"
"fmt"
"regexp"
"strings"
"github.com/harness/gitness/app/api/controller"
"github.com/harness/gitness/app/auth"
"github.com/harness/gitness/git"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"golang.org/x/exp/maps"
)
// ListCommits lists the commits of a repo.
@ -42,6 +46,16 @@ func (c *Controller) ListCommits(ctx context.Context,
gitRef = repo.DefaultBranch
}
commiterRegex, err := c.contributorsRegex(ctx, filter.Committer, filter.CommitterIDs)
if err != nil {
return types.ListCommitResponse{}, fmt.Errorf("failed create commiter regex: %w", err)
}
authorRegex, err := c.contributorsRegex(ctx, filter.Author, filter.AuthorIDs)
if err != nil {
return types.ListCommitResponse{}, fmt.Errorf("failed create author regex: %w", err)
}
rpcOut, err := c.git.ListCommits(ctx, &git.ListCommitsParams{
ReadParams: git.CreateReadParams(repo),
GitREF: gitRef,
@ -51,8 +65,10 @@ func (c *Controller) ListCommits(ctx context.Context,
Path: filter.Path,
Since: filter.Since,
Until: filter.Until,
Committer: filter.Committer,
Committer: commiterRegex,
Author: authorRegex,
IncludeStats: filter.IncludeStats,
Regex: true,
})
if err != nil {
return types.ListCommitResponse{}, err
@ -82,3 +98,42 @@ func (c *Controller) ListCommits(ctx context.Context,
TotalCommits: rpcOut.TotalCommits,
}, nil
}
func (c *Controller) contributorsRegex(
ctx context.Context,
identifier string,
ids []int64,
) (string, error) {
if identifier == "" && len(ids) == 0 {
return "", nil
}
var emailRegex string
if len(ids) > 0 {
principals, err := c.principalInfoCache.Map(ctx, ids)
if err != nil {
return "", err
}
if len(principals) > 0 {
parts := make([]string, len(principals))
for i, principal := range maps.Values(principals) {
parts[i] = regexp.QuoteMeta(principal.Email)
}
emailRegex = "\\<(" + strings.Join(parts, "|") + ")\\>"
}
}
var regex string
switch {
case identifier != "" && emailRegex != "":
regex = regexp.QuoteMeta(identifier) + "|" + emailRegex
case identifier != "":
regex = regexp.QuoteMeta(identifier)
case emailRegex != "":
regex = emailRegex
}
return regex, nil
}

View File

@ -41,10 +41,14 @@ const (
QueryParamSince = "since"
QueryParamUntil = "until"
QueryParamCommitter = "committer"
QueryParamIncludeStats = "include_stats"
QueryParamInternal = "internal"
QueryParamService = "service"
QueryParamCommitSHA = "commit_sha"
QueryParamCommitterID = "committer_id"
QueryParamAuthor = "author"
QueryParamAuthorID = "author_id"
QueryParamIncludeStats = "include_stats"
QueryParamInternal = "internal"
QueryParamService = "service"
QueryParamCommitSHA = "commit_sha"
QueryParamIncludeChecks = "include_checks"
QueryParamIncludeRules = "include_rules"
@ -182,6 +186,16 @@ func ParseCommitFilter(r *http.Request) (*types.CommitFilter, error) {
return nil, err
}
commiterIDs, err := QueryParamListAsPositiveInt64(r, QueryParamCommitterID)
if err != nil {
return nil, err
}
authorIDs, err := QueryParamListAsPositiveInt64(r, QueryParamAuthorID)
if err != nil {
return nil, err
}
return &types.CommitFilter{
After: QueryParamOrDefault(r, QueryParamAfter, ""),
PaginationFilter: types.PaginationFilter{
@ -192,6 +206,9 @@ func ParseCommitFilter(r *http.Request) (*types.CommitFilter, error) {
Since: since,
Until: until,
Committer: QueryParamOrDefault(r, QueryParamCommitter, ""),
CommitterIDs: commiterIDs,
Author: QueryParamOrDefault(r, QueryParamAuthor, ""),
AuthorIDs: authorIDs,
IncludeStats: includeStats,
}, nil
}

View File

@ -31,7 +31,6 @@ const (
PathParamSourceBranch = "source_branch"
PathParamTargetBranch = "target_branch"
QueryParamAuthorID = "author_id"
QueryParamCommenterID = "commenter_id"
QueryParamReviewerID = "reviewer_id"
QueryParamReviewDecision = "review_decision"

View File

@ -71,6 +71,8 @@ type CommitFilter struct {
Since int64
Until int64
Committer string
Author string
Regex bool
}
// CommitDivergenceRequest contains the refs for which the converging commits should be counted.
@ -175,9 +177,15 @@ func (g *Git) listCommitSHAs(
if filter.Until > 0 {
cmd.Add(command.WithFlag("--until", strconv.FormatInt(filter.Until, 10)))
}
if filter.Regex {
cmd.Add(command.WithFlag("-E"))
}
if filter.Committer != "" {
cmd.Add(command.WithFlag("--committer", filter.Committer))
}
if filter.Author != "" {
cmd.Add(command.WithFlag("--author", filter.Author))
}
output := &bytes.Buffer{}
err := cmd.Run(ctx, command.WithDir(repoPath), command.WithStdout(output))
if err != nil {

View File

@ -117,8 +117,14 @@ type ListCommitsParams struct {
// Committer allows to filter for commits based on the committer - Optional, ignored if string is empty.
Committer string
// Author allows to filter for commits based on the author - Optional, ignored if string is empty.
Author string
// IncludeStats allows to include information about inserted, deletions and status for changed files.
IncludeStats bool
// Regex allows to use regular expression in the Committer and Author fields
Regex bool
}
type RenameDetails struct {
@ -162,6 +168,8 @@ func (s *Service) ListCommits(ctx context.Context, params *ListCommitsParams) (*
Since: params.Since,
Until: params.Until,
Committer: params.Committer,
Author: params.Author,
Regex: params.Regex,
},
)
if err != nil {

View File

@ -32,12 +32,15 @@ type PaginationFilter struct {
// CommitFilter stores commit query parameters.
type CommitFilter struct {
PaginationFilter
After string `json:"after"`
Path string `json:"path"`
Since int64 `json:"since"`
Until int64 `json:"until"`
Committer string `json:"committer"`
IncludeStats bool `json:"include_stats"`
After string `json:"after"`
Path string `json:"path"`
Since int64 `json:"since"`
Until int64 `json:"until"`
Committer string `json:"committer"`
CommitterIDs []int64 `json:"committer_ids"`
Author string `json:"author"`
AuthorIDs []int64 `json:"author_ids"`
IncludeStats bool `json:"include_stats"`
}
type BranchMetadataOptions struct {