Files
gitea/modules/gitrepo/commit.go

97 lines
2.7 KiB
Go

// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
import (
"context"
"strconv"
"strings"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/git/gitcmd"
)
// CommitsCountOptions the options when counting commits
type CommitsCountOptions struct {
Not string
Revision []string
RelPath []string
Since string
Until string
}
// CommitsCount returns number of total commits of until given revision.
func CommitsCount(ctx context.Context, repo Repository, opts CommitsCountOptions) (int64, error) {
cmd := gitcmd.NewCommand("rev-list", "--count")
cmd.AddDynamicArguments(opts.Revision...)
if opts.Not != "" {
cmd.AddOptionValues("--not", opts.Not)
}
if len(opts.RelPath) > 0 {
cmd.AddDashesAndList(opts.RelPath...)
}
stdout, _, err := cmd.WithDir(repoPath(repo)).RunStdString(ctx)
if err != nil {
return 0, err
}
return strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
}
// CommitsCountBetween return numbers of commits between two commits
func CommitsCountBetween(ctx context.Context, repo Repository, start, end string) (int64, error) {
count, err := CommitsCount(ctx, repo, CommitsCountOptions{
Revision: []string{start + ".." + end},
})
if err != nil && strings.Contains(err.Error(), "no merge base") {
// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
// previously it would return the results of git rev-list before last so let's try that...
return CommitsCount(ctx, repo, CommitsCountOptions{
Revision: []string{start, end},
})
}
return count, err
}
// FileCommitsCount return the number of files at a revision
func FileCommitsCount(ctx context.Context, repo Repository, revision, file string) (int64, error) {
return CommitsCount(ctx, repo,
CommitsCountOptions{
Revision: []string{revision},
RelPath: []string{file},
})
}
// CommitsCountOfCommit returns number of total commits of until current revision.
func CommitsCountOfCommit(ctx context.Context, repo Repository, commitID string) (int64, error) {
return CommitsCount(ctx, repo, CommitsCountOptions{
Revision: []string{commitID},
})
}
// AllCommitsCount returns count of all commits in repository
func AllCommitsCount(ctx context.Context, repo Repository, hidePRRefs bool, files ...string) (int64, error) {
cmd := gitcmd.NewCommand("rev-list")
if hidePRRefs {
cmd.AddArguments("--exclude=" + git.PullPrefix + "*")
}
cmd.AddArguments("--all", "--count")
if len(files) > 0 {
cmd.AddDashesAndList(files...)
}
stdout, err := RunCmdString(ctx, repo, cmd)
if err != nil {
return 0, err
}
return strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
}