refactor: make git package handle all git operations (#38543)

before: gitrepo vs git packages
after: git package fully handle all git operations

by the way, use `WithRepo(repo)` instead of `WithDir(repo.Path)` to hide
path details.

benefits:

1. remove all unnecessary wrappers, developers no need to struggle with
"which package should be used"
2. simplify code, RepositoryFacade can (will) be used everywhere, all
"path" details are (will be) hidden
This commit is contained in:
wxiaoguang
2026-07-21 00:07:38 +08:00
committed by GitHub
parent b8977eeb47
commit 9dc04289aa
214 changed files with 859 additions and 1301 deletions

View File

@@ -11,7 +11,6 @@ import (
"gitea.dev/models/db"
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/log"
repo_module "gitea.dev/modules/repository"
@@ -129,7 +128,7 @@ func runRepoSyncReleases(ctx context.Context, _ *cli.Command) error {
log.Trace("Processing next %d repos of %d", len(repos), count)
for _, repo := range repos {
log.Trace("Synchronizing repo %s", repo.FullName())
gitRepo, err := gitrepo.OpenRepository(repo)
gitRepo, err := git.OpenRepository(repo)
if err != nil {
log.Warn("OpenRepository: %v", err)
continue

View File

@@ -10,7 +10,7 @@ import (
"gitea.dev/modelmigration/base"
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/git"
"gitea.dev/modules/graceful"
"gitea.dev/modules/log"
"gitea.dev/modules/setting"
@@ -85,7 +85,7 @@ func AddCommitDivergenceToPulls(x base.EngineMigration) error {
}
repoStore := repo_model.CodeRepoByName(baseRepo.OwnerName, baseRepo.Name)
gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index)
divergence, err := gitrepo.GetDivergingCommits(graceful.GetManager().HammerContext(), repoStore, pr.BaseBranch, gitRefName)
divergence, err := git.GetDivergingCommits(graceful.GetManager().HammerContext(), repoStore, pr.BaseBranch, gitRefName)
if err != nil {
log.Warn("Could not recalculate Divergence for pull: %d", pr.ID)
pr.CommitsAhead = 0

View File

@@ -8,7 +8,7 @@ import (
"gitea.dev/modelmigration/base"
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/git"
"gitea.dev/modules/setting"
)
@@ -160,11 +160,11 @@ func migratePushMirrors(x base.EngineMigration) error {
func getRemoteAddress(ownerName, repoName, remoteName string) (string, error) {
ctx := context.Background()
repo := repo_model.CodeRepoByName(ownerName, repoName)
if exist, _ := gitrepo.IsRepositoryExist(ctx, repo); !exist {
if exist, _ := git.IsRepositoryExist(ctx, repo); !exist {
return "", nil
}
u, err := gitrepo.GitRemoteGetURL(ctx, repo, remoteName)
u, err := git.ParseRemoteAddressURL(ctx, repo, remoteName)
if err != nil {
return "", err
}

View File

@@ -10,7 +10,6 @@ import (
"gitea.dev/modelmigration/base"
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
)
func FixReleaseSha1OnReleaseTable(ctx context.Context, x base.EngineMigration) error {
@@ -87,7 +86,7 @@ func FixReleaseSha1OnReleaseTable(ctx context.Context, x base.EngineMigration) e
userCache[repo.OwnerID] = user
}
gitRepo, err = gitrepo.OpenRepository(repo_model.CodeRepoByName(user.Name, repo.Name))
gitRepo, err = git.OpenRepository(repo_model.CodeRepoByName(user.Name, repo.Name))
if err != nil {
return err
}

View File

@@ -14,7 +14,6 @@ import (
repo_model "gitea.dev/models/repo"
user_model "gitea.dev/models/user"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"xorm.io/builder"
)
@@ -67,7 +66,7 @@ func GetActivityStats(ctx context.Context, repo *repo_model.Repository, timeFrom
return nil, fmt.Errorf("FillUnresolvedIssues: %w", err)
}
if code {
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo)
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo)
if err != nil {
return nil, fmt.Errorf("OpenRepository: %w", err)
}
@@ -84,7 +83,7 @@ func GetActivityStats(ctx context.Context, repo *repo_model.Repository, timeFrom
// GetActivityStatsTopAuthors returns top author stats for git commits for all branches
func GetActivityStatsTopAuthors(ctx context.Context, repo *repo_model.Repository, timeFrom time.Time, count int) ([]*ActivityAuthorData, error) {
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo)
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo)
if err != nil {
return nil, fmt.Errorf("OpenRepository: %w", err)
}

View File

@@ -15,7 +15,7 @@ import (
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"gitea.dev/modules/commitstatus"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/git"
"github.com/stretchr/testify/assert"
)
@@ -186,7 +186,7 @@ func TestFindRepoRecentCommitStatusContexts(t *testing.T) {
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
gitRepo, err := gitrepo.OpenRepository(repo2)
gitRepo, err := git.OpenRepository(repo2)
assert.NoError(t, err)
defer gitRepo.Close()

View File

@@ -9,7 +9,6 @@ import (
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/log"
)
@@ -40,7 +39,7 @@ func (c *commitChecker) IsCommitIDExisting(commitID string) bool {
}
if c.gitRepo == nil {
r, closer, err := gitrepo.RepositoryFromContextOrOpen(c.ctx, c.repo)
r, closer, err := git.RepositoryFromContextOrOpen(c.ctx, c.repo)
if err != nil {
log.Error("Unable to open repository: %s, error: %v", c.repo.FullName(), err)
return false

View File

@@ -1,7 +1,7 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
@@ -12,13 +12,12 @@ import (
"path/filepath"
"strings"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/setting"
)
// CreateArchive create archive content to the target path
func CreateArchive(ctx context.Context, repo git.RepositoryFacade, repoName, format string, target io.Writer, commitID string, paths []string) error {
func CreateArchive(ctx context.Context, repo RepositoryFacade, repoName, format string, target io.Writer, commitID string, paths []string) error {
if format == "unknown" {
return fmt.Errorf("unknown format: %v", format)
}
@@ -38,7 +37,7 @@ func CreateArchive(ctx context.Context, repo git.RepositoryFacade, repoName, for
}
// CreateBundle create bundle content to the target path
func CreateBundle(ctx context.Context, repo git.RepositoryFacade, commit string, out io.Writer) error {
func CreateBundle(ctx context.Context, repo RepositoryFacade, commit string, out io.Writer) error {
// TODO: use the following steps instead of creating a temp file, also need to iterate and clean up outdated refs
// git update-ref refs/bundle/temp-{timestamp} {commit}
// git bundle create - refs/bundle/temp-{timestamp}
@@ -49,7 +48,7 @@ func CreateBundle(ctx context.Context, repo git.RepositoryFacade, commit string,
}
defer cleanup()
env := append(os.Environ(), "GIT_OBJECT_DIRECTORY="+filepath.Join(repoPath(repo), "objects"))
env := append(os.Environ(), "GIT_OBJECT_DIRECTORY="+filepath.Join(gitcmd.RepoLocalPath(repo), "objects"))
_, _, err = gitcmd.NewCommand("init", "--bare").WithDir(tmp).WithEnv(env).RunStdString(ctx)
if err != nil {
return err

View File

@@ -69,7 +69,7 @@ func NewBatchChecker(ctx context.Context, repo *git.Repository, treeish string,
checker.stdOut = lw
cmd.WithEnv(envs).
WithDir(repo.Path).
WithRepo(repo).
WithStdoutCopy(lw)
go func() {

View File

@@ -69,7 +69,7 @@ func CheckAttributes(ctx context.Context, gitRepo *git.Repository, treeish strin
defer cancel()
stdout, _, err := cmd.WithEnv(append(os.Environ(), envs...)).
WithDir(gitRepo.Path).
WithRepo(gitRepo).
RunStdBytes(ctx)
if err != nil {
return nil, fmt.Errorf("failed to run check-attr: %w", err)

View File

@@ -1,7 +1,7 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"bufio"
@@ -9,12 +9,11 @@ import (
"context"
"io"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/setting"
)
func LineBlame(ctx context.Context, repo git.RepositoryFacade, revision, file string, line uint) (string, error) {
func LineBlame(ctx context.Context, repo RepositoryFacade, revision, file string, line uint) (string, error) {
stdout, _, err := gitcmd.NewCommand("blame").WithRepo(repo).
AddOptionFormat("-L %d,%d", line, line).
AddOptionValues("-p", revision).
@@ -37,7 +36,7 @@ type BlameReader struct {
done chan error
lastSha *string
ignoreRevsFile string
objectFormat git.ObjectFormat
objectFormat ObjectFormat
cleanupFuncs []func()
}
@@ -139,7 +138,7 @@ func (r *BlameReader) cleanup() {
}
// CreateBlameReader creates reader for given git.RepositoryFacade, commit and file
func CreateBlameReader(ctx context.Context, objectFormat git.ObjectFormat, repo git.RepositoryFacade, gitRepo *git.Repository, commit *git.Commit, file string, bypassBlameIgnore bool) (rd *BlameReader, retErr error) {
func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repo RepositoryFacade, gitRepo *Repository, commit *Commit, file string, bypassBlameIgnore bool) (rd *BlameReader, retErr error) {
defer func() {
if retErr != nil {
rd.cleanup()
@@ -157,9 +156,9 @@ func CreateBlameReader(ctx context.Context, objectFormat git.ObjectFormat, repo
rd.bufferedReader = bufio.NewReader(stdoutReader)
rd.cleanupFuncs = append(rd.cleanupFuncs, stdoutReaderClose)
if git.DefaultFeatures().CheckVersionAtLeast("2.23") && !bypassBlameIgnore {
if DefaultFeatures().CheckVersionAtLeast("2.23") && !bypassBlameIgnore {
ignoreRevsFileName, ignoreRevsFileCleanup, err := tryCreateBlameIgnoreRevsFile(ctx, gitRepo, commit)
if err != nil && !git.IsErrNotExist(err) {
if err != nil && !IsErrNotExist(err) {
return nil, err
} else if err == nil {
rd.ignoreRevsFile = ignoreRevsFileName
@@ -180,7 +179,7 @@ func CreateBlameReader(ctx context.Context, objectFormat git.ObjectFormat, repo
return rd, nil
}
func tryCreateBlameIgnoreRevsFile(ctx context.Context, gitRepo *git.Repository, commit *git.Commit) (string, func(), error) {
func tryCreateBlameIgnoreRevsFile(ctx context.Context, gitRepo *Repository, commit *Commit) (string, func(), error) {
entry, err := commit.GetTreeEntryByPath(ctx, gitRepo, ".git-blame-ignore-revs")
if err != nil {
return "", nil, err

View File

@@ -1,13 +1,12 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
"testing"
"gitea.dev/modules/git"
"gitea.dev/modules/setting"
"github.com/stretchr/testify/assert"
@@ -18,7 +17,7 @@ func TestReadingBlameOutputSha256(t *testing.T) {
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
if git.DefaultFeatures().UsingGogit {
if DefaultFeatures().UsingGogit {
t.Skip("Skipping test since gogit does not support sha256")
return
}
@@ -49,7 +48,7 @@ func TestReadingBlameOutputSha256(t *testing.T) {
}
for _, bypass := range []bool{false, true} {
blameReader, err := CreateBlameReader(ctx, git.Sha256ObjectFormat, storage, repo, commit, "README.md", bypass)
blameReader, err := CreateBlameReader(ctx, Sha256ObjectFormat, storage, repo, commit, "README.md", bypass)
assert.NoError(t, err)
assert.NotNil(t, blameReader)
defer blameReader.Close()

View File

@@ -1,13 +1,12 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
"testing"
"gitea.dev/modules/git"
"gitea.dev/modules/setting"
"github.com/stretchr/testify/assert"
@@ -43,7 +42,7 @@ func TestReadingBlameOutput(t *testing.T) {
}
for _, bypass := range []bool{false, true} {
blameReader, err := CreateBlameReader(ctx, git.Sha1ObjectFormat, storage, repo, commit, "README.md", bypass)
blameReader, err := CreateBlameReader(ctx, Sha1ObjectFormat, storage, repo, commit, "README.md", bypass)
assert.NoError(t, err)
assert.NotNil(t, blameReader)
defer blameReader.Close()

View File

@@ -1,20 +1,19 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
"errors"
"strings"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
)
// GetBranchesByPath returns a branch by its path
// if limit = 0 it will not limit
func GetBranchesByPath(ctx context.Context, repo git.RepositoryFacade, skip, limit int) ([]string, int, error) {
func GetBranchesByPath(ctx context.Context, repo RepositoryFacade, skip, limit int) ([]string, int, error) {
gitRepo, err := OpenRepository(repo)
if err != nil {
return nil, 0, err
@@ -24,7 +23,7 @@ func GetBranchesByPath(ctx context.Context, repo git.RepositoryFacade, skip, lim
return gitRepo.GetBranchNames(ctx, skip, limit)
}
func GetBranchCommitID(ctx context.Context, repo git.RepositoryFacade, branch string) (string, error) {
func GetBranchCommitID(ctx context.Context, repo RepositoryFacade, branch string) (string, error) {
gitRepo, err := OpenRepository(repo)
if err != nil {
return "", err
@@ -35,38 +34,38 @@ func GetBranchCommitID(ctx context.Context, repo git.RepositoryFacade, branch st
}
// SetDefaultBranch sets default branch of repository.
func SetDefaultBranch(ctx context.Context, repo git.RepositoryFacade, name string) error {
func SetDefaultBranch(ctx context.Context, repo RepositoryFacade, name string) error {
_, _, err := gitcmd.NewCommand("symbolic-ref", "HEAD").
AddDynamicArguments(git.BranchPrefix + name).WithRepo(repo).RunStdString(ctx)
AddDynamicArguments(BranchPrefix + name).WithRepo(repo).RunStdString(ctx)
return err
}
// GetDefaultBranch gets default branch of repository.
func GetDefaultBranch(ctx context.Context, repo git.RepositoryFacade) (string, error) {
func GetDefaultBranch(ctx context.Context, repo RepositoryFacade) (string, error) {
stdout, _, err := gitcmd.NewCommand("symbolic-ref", "HEAD").WithRepo(repo).RunStdString(ctx)
if err != nil {
return "", err
}
stdout = strings.TrimSpace(stdout)
if !strings.HasPrefix(stdout, git.BranchPrefix) {
if !strings.HasPrefix(stdout, BranchPrefix) {
return "", errors.New("the HEAD is not a branch: " + stdout)
}
return strings.TrimPrefix(stdout, git.BranchPrefix), nil
return strings.TrimPrefix(stdout, BranchPrefix), nil
}
// IsReferenceExist returns true if given reference exists in the repository.
func IsReferenceExist(ctx context.Context, repo git.RepositoryFacade, name string) bool {
func IsReferenceExist(ctx context.Context, repo RepositoryFacade, name string) bool {
_, _, err := gitcmd.NewCommand("show-ref", "--verify").AddDashesAndList(name).WithRepo(repo).RunStdString(ctx)
return err == nil
}
// IsBranchExist returns true if given branch exists in the repository.
func IsBranchExist(ctx context.Context, repo git.RepositoryFacade, name string) bool {
return IsReferenceExist(ctx, repo, git.BranchPrefix+name)
func IsBranchExist(ctx context.Context, repo RepositoryFacade, name string) bool {
return IsReferenceExist(ctx, repo, BranchPrefix+name)
}
// DeleteBranch delete a branch by name on repository.
func DeleteBranch(ctx context.Context, repo git.RepositoryFacade, name string, force bool) error {
func DeleteBranch(ctx context.Context, repo RepositoryFacade, name string, force bool) error {
cmd := gitcmd.NewCommand("branch")
if force {
@@ -81,7 +80,7 @@ func DeleteBranch(ctx context.Context, repo git.RepositoryFacade, name string, f
}
// CreateBranch create a new branch
func CreateBranch(ctx context.Context, repo git.RepositoryFacade, branch, oldbranchOrCommit string) error {
func CreateBranch(ctx context.Context, repo RepositoryFacade, branch, oldbranchOrCommit string) error {
cmd := gitcmd.NewCommand("branch")
cmd.AddDashesAndList(branch, oldbranchOrCommit)
@@ -90,7 +89,7 @@ func CreateBranch(ctx context.Context, repo git.RepositoryFacade, branch, oldbra
}
// RenameBranch rename a branch
func RenameBranch(ctx context.Context, repo git.RepositoryFacade, from, to string) error {
func RenameBranch(ctx context.Context, repo RepositoryFacade, from, to string) error {
_, _, err := gitcmd.NewCommand("branch", "-m").AddDynamicArguments(from, to).WithRepo(repo).RunStdString(ctx)
return err
}

24
modules/git/clone.go Normal file
View File

@@ -0,0 +1,24 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package git
import (
"context"
"gitea.dev/modules/git/gitcmd"
)
// CloneExternalRepo clones an external repository to the managed repository.
func CloneExternalRepo(ctx context.Context, fromRemoteURL string, toRepo RepositoryFacade, opts CloneRepoOptions) error {
return Clone(ctx, fromRemoteURL, gitcmd.RepoLocalPath(toRepo), opts)
}
// CloneRepoToLocal clones a managed repository to a local path.
func CloneRepoToLocal(ctx context.Context, fromRepo RepositoryFacade, toLocalPath string, opts CloneRepoOptions) error {
return Clone(ctx, gitcmd.RepoLocalPath(fromRepo), toLocalPath, opts)
}
func CloneManaged(ctx context.Context, fromRepo, toRepo RepositoryFacade, opts CloneRepoOptions) error {
return Clone(ctx, gitcmd.RepoLocalPath(fromRepo), gitcmd.RepoLocalPath(toRepo), opts)
}

View File

@@ -112,7 +112,7 @@ func (c *Commit) HasPreviousCommit(ctx context.Context, gitRepo *Repository, obj
_, _, err := gitcmd.NewCommand("merge-base", "--is-ancestor").
AddDynamicArguments(that, this).
WithDir(gitRepo.Path).
WithRepo(gitRepo).
RunStdString(ctx)
if err == nil {
return true, nil
@@ -239,10 +239,10 @@ func (c *Commit) GetFileContent(ctx context.Context, gitRepo *Repository, filena
}
// GetFullCommitID returns full length (40) of commit ID by given short SHA in a repository.
func GetFullCommitID(ctx context.Context, repoPath, shortID string) (string, error) {
func GetFullCommitID(ctx context.Context, repo RepositoryFacade, shortID string) (string, error) {
commitID, _, err := gitcmd.NewCommand("rev-parse").
AddDynamicArguments(shortID).
WithDir(repoPath).
WithRepo(repo).
RunStdString(ctx)
if err != nil {
if gitcmd.IsErrorExitCode(err, 128) {

View File

@@ -1,7 +1,7 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
@@ -9,7 +9,6 @@ import (
"strings"
"time"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
)
@@ -23,7 +22,7 @@ type CommitsCountOptions struct {
}
// CommitsCount returns number of total commits of until given revision.
func CommitsCount(ctx context.Context, repo git.RepositoryFacade, opts CommitsCountOptions) (int64, error) {
func CommitsCount(ctx context.Context, repo RepositoryFacade, opts CommitsCountOptions) (int64, error) {
cmd := gitcmd.NewCommand("rev-list", "--count")
cmd.AddDynamicArguments(opts.Revision...)
@@ -53,7 +52,7 @@ func CommitsCount(ctx context.Context, repo git.RepositoryFacade, opts CommitsCo
}
// FileCommitsCount return the number of files at a revision
func FileCommitsCount(ctx context.Context, repo git.RepositoryFacade, revision, file string) (int64, error) {
func FileCommitsCount(ctx context.Context, repo RepositoryFacade, revision, file string) (int64, error) {
return CommitsCount(ctx, repo,
CommitsCountOptions{
Revision: []string{revision},
@@ -62,17 +61,17 @@ func FileCommitsCount(ctx context.Context, repo git.RepositoryFacade, revision,
}
// CommitsCountOfCommit returns number of total commits of until current revision.
func CommitsCountOfCommit(ctx context.Context, repo git.RepositoryFacade, commitID string) (int64, error) {
func CommitsCountOfCommit(ctx context.Context, repo RepositoryFacade, 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 git.RepositoryFacade, hidePRRefs bool, files ...string) (int64, error) {
func AllCommitsCount(ctx context.Context, repo RepositoryFacade, hidePRRefs bool, files ...string) (int64, error) {
cmd := gitcmd.NewCommand("rev-list")
if hidePRRefs {
cmd.AddArguments("--exclude=" + git.PullPrefix + "*")
cmd.AddArguments("--exclude=" + PullPrefix + "*")
}
cmd.AddArguments("--all", "--count")
if len(files) > 0 {
@@ -87,13 +86,9 @@ func AllCommitsCount(ctx context.Context, repo git.RepositoryFacade, hidePRRefs
return strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
}
func GetFullCommitID(ctx context.Context, repo git.RepositoryFacade, shortID string) (string, error) {
return git.GetFullCommitID(ctx, repoPath(repo), shortID)
}
// GetLatestCommitTime returns time for latest commit in repository (across all branches)
func GetLatestCommitTime(ctx context.Context, repo git.RepositoryFacade) (time.Time, error) {
stdout, _, err := gitcmd.NewCommand("for-each-ref", "--sort=-committerdate", git.BranchPrefix, "--count", "1", "--format=%(committerdate)").WithRepo(repo).RunStdString(ctx)
func GetLatestCommitTime(ctx context.Context, repo RepositoryFacade) (time.Time, error) {
stdout, _, err := gitcmd.NewCommand("for-each-ref", "--sort=-committerdate", BranchPrefix, "--count", "1", "--format=%(committerdate)").WithRepo(repo).RunStdString(ctx)
if err != nil {
return time.Time{}, err
}

View File

@@ -1,7 +1,7 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"testing"

View File

@@ -1,14 +1,13 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"bufio"
"context"
"io"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/log"
)
@@ -67,7 +66,7 @@ func parseCommitFileStatus(fileStatus *CommitFileStatus, stdout io.Reader) {
}
// GetCommitFileStatus returns file status of commit in given repository.
func GetCommitFileStatus(ctx context.Context, repo git.RepositoryFacade, commitID string) (*CommitFileStatus, error) {
func GetCommitFileStatus(ctx context.Context, repo RepositoryFacade, commitID string) (*CommitFileStatus, error) {
cmd := gitcmd.NewCommand("log", "--name-status", "-m", "--pretty=format:", "--first-parent", "--no-renames", "-z", "-1")
stdout, stdoutClose := cmd.MakeStdoutPipe()
defer stdoutClose()

View File

@@ -1,7 +1,7 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"strings"

View File

@@ -15,17 +15,13 @@ import (
)
func TestGetFullCommitIDSha256(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256")
id, err := GetFullCommitID(t.Context(), bareRepo1Path, "f004f4")
id, err := GetFullCommitID(t.Context(), mockRepository("repo1_bare_sha256"), "f004f4")
assert.NoError(t, err)
assert.Equal(t, "f004f41359117d319dedd0eaab8c5259ee2263da839dcba33637997458627fdc", id)
}
func TestGetFullCommitIDErrorSha256(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256")
id, err := GetFullCommitID(t.Context(), bareRepo1Path, "unknown")
id, err := GetFullCommitID(t.Context(), mockRepository("repo1_bare_sha256"), "unknown")
assert.Empty(t, id)
if assert.Error(t, err) {
assert.EqualError(t, err, "object does not exist [id: unknown, rel_path: ]")

View File

@@ -14,17 +14,13 @@ import (
)
func TestGetFullCommitID(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
id, err := GetFullCommitID(t.Context(), bareRepo1Path, "8006ff9a")
id, err := GetFullCommitID(t.Context(), mockRepository("repo1_bare"), "8006ff9a")
assert.NoError(t, err)
assert.Equal(t, "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0", id)
}
func TestGetFullCommitIDError(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
id, err := GetFullCommitID(t.Context(), bareRepo1Path, "unknown")
id, err := GetFullCommitID(t.Context(), mockRepository("repo1_bare"), "unknown")
assert.Empty(t, id)
if assert.Error(t, err) {
assert.EqualError(t, err, "object does not exist [id: unknown, rel_path: ]")

View File

@@ -1,7 +1,7 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
@@ -9,7 +9,6 @@ import (
"strconv"
"strings"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
)
@@ -20,7 +19,7 @@ type DivergeObject struct {
}
// GetDivergingCommits returns the number of commits a targetBranch is ahead or behind a baseBranch
func GetDivergingCommits(ctx context.Context, repo git.RepositoryFacade, baseBranch, targetBranch string) (*DivergeObject, error) {
func GetDivergingCommits(ctx context.Context, repo RepositoryFacade, baseBranch, targetBranch string) (*DivergeObject, error) {
cmd := gitcmd.NewCommand("rev-list", "--count", "--left-right").
AddDynamicArguments(baseBranch + "..." + targetBranch).AddArguments("--")
stdout, _, err1 := cmd.WithRepo(repo).RunStdString(ctx)
@@ -46,7 +45,7 @@ func GetDivergingCommits(ctx context.Context, repo git.RepositoryFacade, baseBra
// GetCommitIDsBetweenReverse returns the last commit IDs between two commits in reverse order (from old to new) with limit.
// If the result exceeds the limit, the old commits IDs will be ignored
func GetCommitIDsBetweenReverse(ctx context.Context, repo git.RepositoryFacade, startRef, endRef, notRef string, limit int) ([]string, error) {
func GetCommitIDsBetweenReverse(ctx context.Context, repo RepositoryFacade, startRef, endRef, notRef string, limit int) ([]string, error) {
genCmd := func(reversions ...string) *gitcmd.Command {
cmd := gitcmd.NewCommand("rev-list", "--reverse").
AddArguments("-n").AddDynamicArguments(strconv.Itoa(limit)).

View File

@@ -1,7 +1,7 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"path/filepath"

View File

@@ -1,18 +1,17 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
)
// ManagedConfigAdd add a git configuration key to a specific value for the given repository.
func ManagedConfigAdd(ctx context.Context, repo git.RepositoryFacade, key, value string) error {
return git.LockConfigAndDo(ctx, repo, func(ctx context.Context) error {
func ManagedConfigAdd(ctx context.Context, repo RepositoryFacade, key, value string) error {
return LockConfigAndDo(ctx, repo, func(ctx context.Context) error {
_, _, err := gitcmd.NewCommand("config", "--add").
AddDynamicArguments(key, value).WithRepo(repo).RunStdString(ctx)
return err
@@ -22,8 +21,8 @@ func ManagedConfigAdd(ctx context.Context, repo git.RepositoryFacade, key, value
// ManagedConfigSet updates a git configuration key to a specific value for the given repository.
// If the key does not exist, it will be created.
// If the key exists, it will be updated to the new value.
func ManagedConfigSet(ctx context.Context, repo git.RepositoryFacade, key, value string) error {
return git.LockConfigAndDo(ctx, repo, func(ctx context.Context) error {
func ManagedConfigSet(ctx context.Context, repo RepositoryFacade, key, value string) error {
return LockConfigAndDo(ctx, repo, func(ctx context.Context) error {
_, _, err := gitcmd.NewCommand("config").
AddDynamicArguments(key, value).WithRepo(repo).RunStdString(ctx)
return err

View File

@@ -65,7 +65,7 @@ func getRepoRawDiffForFileCmd(ctx context.Context, repo *Repository, startCommit
files = append(files, file)
}
cmd := gitcmd.NewCommand().WithDir(repo.Path)
cmd := gitcmd.NewCommand().WithRepo(repo)
switch diffType {
case RawDiffNormal:
if len(startCommit) != 0 {
@@ -310,7 +310,7 @@ func GetAffectedFiles(ctx context.Context, repo *Repository, branchName, oldComm
cmd := gitcmd.NewCommand("diff", "--name-only").AddDynamicArguments(oldCommitID, newCommitID)
stdoutReader, stdoutReaderClose := cmd.MakeStdoutPipe()
defer stdoutReaderClose()
err := cmd.WithEnv(env).WithDir(repo.Path).
err := cmd.WithEnv(env).WithRepo(repo).
WithPipelineFunc(func(ctx gitcmd.Context) error {
// Now scan the output from the command
scanner := bufio.NewScanner(stdoutReader)

View File

@@ -1,7 +1,7 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
@@ -10,13 +10,12 @@ import (
"regexp"
"strconv"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
)
// GetDiffShortStatByCmdArgs counts number of changed files, number of additions and deletions
// TODO: it can be merged with another "GetDiffShortStat" in the future
func GetDiffShortStatByCmdArgs(ctx context.Context, repo git.RepositoryFacade, trustedArgs gitcmd.TrustedCmdArgs, dynamicArgs ...string) (numFiles, totalAdditions, totalDeletions int, err error) {
func GetDiffShortStatByCmdArgs(ctx context.Context, repo RepositoryFacade, trustedArgs gitcmd.TrustedCmdArgs, dynamicArgs ...string) (numFiles, totalAdditions, totalDeletions int, err error) {
// Now if we call:
// $ git diff --shortstat 1ebb35b98889ff77299f24d82da426b434b0cca0...788b8b1440462d477f45b0088875
// we get:
@@ -64,7 +63,7 @@ func parseDiffStat(stdout string) (numFiles, totalAdditions, totalDeletions int,
}
// GetReverseRawDiff dumps the reverse diff results of repository in given commit ID to io.Writer.
func GetReverseRawDiff(ctx context.Context, repo git.RepositoryFacade, commitID string, writer io.Writer) error {
func GetReverseRawDiff(ctx context.Context, repo RepositoryFacade, commitID string, writer io.Writer) error {
return gitcmd.NewCommand("show", "--pretty=format:revert %H%n", "-R").
AddDynamicArguments(commitID).
WithStdoutCopy(writer).

View File

@@ -1,12 +1,11 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
)
@@ -19,10 +18,10 @@ import (
//
// This behavior is sufficient for temporary operations, such as determining the
// merge base between commits.
func FetchRemoteCommit(ctx context.Context, repo, remoteRepo git.RepositoryFacade, commitID string) error {
return git.LockWriteAndDo(ctx, repo, func(ctx context.Context) error {
func FetchRemoteCommit(ctx context.Context, repo, remoteRepo RepositoryFacade, commitID string) error {
return LockWriteAndDo(ctx, repo, func(ctx context.Context) error {
return gitcmd.NewCommand("fetch", "--no-tags").
AddDynamicArguments(repoPath(remoteRepo)).
AddDynamicArguments(gitcmd.RepoLocalPath(remoteRepo)).
AddDynamicArguments(commitID).
WithRepo(repo).Run(ctx)
})

View File

@@ -1,17 +1,16 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
"time"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
)
// Fsck verifies the connectivity and validity of the objects in the database
func Fsck(ctx context.Context, repo git.RepositoryFacade, timeout time.Duration, args gitcmd.TrustedCmdArgs) error {
func Fsck(ctx context.Context, repo RepositoryFacade, timeout time.Duration, args gitcmd.TrustedCmdArgs) error {
return gitcmd.NewCommand("fsck").AddArguments(args...).WithTimeout(timeout).WithRepo(repo).Run(ctx)
}

View File

@@ -10,12 +10,6 @@ import (
"github.com/stretchr/testify/assert"
)
const testReposDir = "tests/repos/"
func TestMain(m *testing.M) {
RunGitTests(m)
}
func TestParseGitVersion(t *testing.T) {
v, err := parseGitVersionLine("git version 2.29.3")
assert.NoError(t, err)

View File

@@ -1,20 +1,17 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
"io"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/reqctx"
"gitea.dev/modules/util"
)
var OpenRepository = git.OpenRepository // TODO: can be removed in the future
// contextKey is a value for use with context.WithValue.
type contextKey struct {
key string
@@ -22,7 +19,7 @@ type contextKey struct {
// RepositoryFromContextOrOpen attempts to get the repository from the context or just opens it
// The caller must call Closer.Close()
func RepositoryFromContextOrOpen(ctx context.Context, repo git.RepositoryFacade) (*git.Repository, io.Closer, error) {
func RepositoryFromContextOrOpen(ctx context.Context, repo RepositoryFacade) (*Repository, io.Closer, error) {
reqCtx := reqctx.FromContext(ctx)
if reqCtx != nil {
gitRepo, err := RepositoryFromRequestContextOrOpen(reqCtx, repo)
@@ -34,12 +31,12 @@ func RepositoryFromContextOrOpen(ctx context.Context, repo git.RepositoryFacade)
// RepositoryFromRequestContextOrOpen opens the repository at the given relative path in the provided request context.
// Caller shouldn't close the git repo manually, the git repo will be automatically closed when the request context is done.
func RepositoryFromRequestContextOrOpen(ctx reqctx.RequestContext, repo git.RepositoryFacade) (*git.Repository, error) {
func RepositoryFromRequestContextOrOpen(ctx reqctx.RequestContext, repo RepositoryFacade) (*Repository, error) {
ck := contextKey{key: repo.GitRepoLocation()}
if gitRepo, ok := ctx.Value(ck).(*git.Repository); ok {
if gitRepo, ok := ctx.Value(ck).(*Repository); ok {
return gitRepo, nil
}
gitRepo, err := git.OpenRepository(repo)
gitRepo, err := OpenRepository(repo)
if err != nil {
return nil, err
}
@@ -48,7 +45,7 @@ func RepositoryFromRequestContextOrOpen(ctx reqctx.RequestContext, repo git.Repo
return gitRepo, nil
}
func UpdateServerInfo(ctx context.Context, repo git.RepositoryFacade) error {
func UpdateServerInfo(ctx context.Context, repo RepositoryFacade) error {
_, _, err := gitcmd.NewCommand("update-server-info").WithRepo(repo).RunStdBytes(ctx)
return err
}

View File

@@ -80,7 +80,7 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO
stdoutReader, stdoutReaderClose := cmd.MakeStdoutPipe()
defer stdoutReaderClose()
err := cmd.WithDir(repo.Path).
err := cmd.WithRepo(repo).
WithTimeout(grepSearchTimeout).
WithPipelineFunc(func(ctx gitcmd.Context) error {
isInBlock := false

View File

@@ -7,6 +7,8 @@ import (
"path/filepath"
"testing"
"gitea.dev/modules/git/gitcmd"
"github.com/stretchr/testify/assert"
)
@@ -74,7 +76,8 @@ func TestGrepSearch(t *testing.T) {
assert.NoError(t, err)
assert.Empty(t, res)
res, err = GrepSearch(t.Context(), &Repository{RepositoryBase: RepositoryBase{Path: "no-such-git-repo"}}, "no-such-content", GrepOptions{})
nonExistingRepo := &Repository{RepositoryBase: RepositoryBase{Path: "no-such-git-repo", repoFacade: gitcmd.RepositoryUnmanaged("no-such-git-repo")}}
res, err = GrepSearch(t.Context(), nonExistingRepo, "no-such-content", GrepOptions{})
assert.Error(t, err)
assert.Empty(t, res)
}

View File

@@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
@@ -10,7 +10,7 @@ import (
"path/filepath"
"runtime"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/setting"
"gitea.dev/modules/util"
)
@@ -108,8 +108,8 @@ done
}
// CreateDelegateHooks creates all the hooks scripts for the repo
func CreateDelegateHooks(_ context.Context, repo git.RepositoryFacade) (err error) {
return createDelegateHooks(filepath.Join(repoPath(repo), "hooks"))
func CreateDelegateHooks(_ context.Context, repo RepositoryFacade) (err error) {
return createDelegateHooks(filepath.Join(gitcmd.RepoLocalPath(repo), "hooks"))
}
func createDelegateHooks(hookDir string) (err error) {
@@ -175,8 +175,8 @@ func ensureExecutable(filename string) error {
}
// CheckDelegateHooks checks the hooks scripts for the repo
func CheckDelegateHooks(_ context.Context, repo git.RepositoryFacade) ([]string, error) {
return checkDelegateHooks(filepath.Join(repoPath(repo), "hooks"))
func CheckDelegateHooks(_ context.Context, repo RepositoryFacade) ([]string, error) {
return checkDelegateHooks(filepath.Join(gitcmd.RepoLocalPath(repo), "hooks"))
}
func checkDelegateHooks(hookDir string) ([]string, error) {

View File

@@ -1,8 +1,6 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//go:build !gogit
package languagestats
import (

View File

@@ -1,182 +0,0 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//go:build gogit
package languagestats
import (
"bytes"
"context"
"io"
"gitea.dev/modules/analyze"
git_module "gitea.dev/modules/git"
"gitea.dev/modules/git/attribute"
"gitea.dev/modules/optional"
"github.com/go-enry/go-enry/v2"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
)
// GetLanguageStats calculates language stats for git repository at specified commit
func GetLanguageStats(ctx context.Context, repo *git_module.Repository, commitID string) (map[string]int64, error) {
r, err := git.PlainOpen(repo.Path)
if err != nil {
return nil, err
}
rev, err := r.ResolveRevision(plumbing.Revision(commitID))
if err != nil {
return nil, err
}
commit, err := r.CommitObject(*rev)
if err != nil {
return nil, err
}
tree, err := commit.Tree()
if err != nil {
return nil, err
}
checker, err := attribute.NewBatchChecker(ctx, repo, commitID, attribute.LinguistAttributes)
if err != nil {
return nil, err
}
defer checker.Close()
// sizes contains the current calculated size of all files by language
sizes := make(map[string]int64)
// by default we will only count the sizes of programming languages or markup languages
// unless they are explicitly set using linguist-language
includedLanguage := map[string]bool{}
// or if there's only one language in the repository
firstExcludedLanguage := ""
firstExcludedLanguageSize := int64(0)
err = tree.Files().ForEach(func(f *object.File) error {
if f.Size == 0 {
return nil
}
isVendored := optional.None[bool]()
isGenerated := optional.None[bool]()
isDocumentation := optional.None[bool]()
isDetectable := optional.None[bool]()
attrs, err := checker.CheckPath(f.Name)
if err == nil {
isVendored = attrs.GetVendored()
if isVendored.ValueOrDefault(false) {
return nil
}
isGenerated = attrs.GetGenerated()
if isGenerated.ValueOrDefault(false) {
return nil
}
isDocumentation = attrs.GetDocumentation()
if isDocumentation.ValueOrDefault(false) {
return nil
}
isDetectable = attrs.GetDetectable()
if !isDetectable.ValueOrDefault(true) {
return nil
}
hasLanguage := attrs.GetLanguage()
if hasLanguage.Value() != "" {
language := hasLanguage.Value()
// group languages, such as Pug -> HTML; SCSS -> CSS
group := enry.GetLanguageGroup(language)
if len(group) != 0 {
language = group
}
// this language will always be added to the size
sizes[language] += f.Size
return nil
}
}
if (!isVendored.Has() && analyze.IsVendor(f.Name)) ||
enry.IsDotFile(f.Name) ||
(!isDocumentation.Has() && enry.IsDocumentation(f.Name)) ||
(!isDetectable.Has() && enry.IsConfiguration(f.Name)) {
return nil
}
// If content can not be read or file is too big just do detection by filename
var content []byte
if f.Size <= bigFileSize {
content, _ = readFile(f, fileSizeLimit)
}
if !isGenerated.Has() && enry.IsGenerated(f.Name, content) {
return nil
}
language := analyze.GetCodeLanguage(f.Name, content)
if language == enry.OtherLanguage || language == "" {
return nil
}
// group languages, such as Pug -> HTML; SCSS -> CSS
group := enry.GetLanguageGroup(language)
if group != "" {
language = group
}
included, checked := includedLanguage[language]
if !checked {
langtype := enry.GetLanguageType(language)
included = langtype == enry.Programming || langtype == enry.Markup
includedLanguage[language] = included
}
if included || isDetectable.ValueOrDefault(false) {
sizes[language] += f.Size
} else if len(sizes) == 0 && (firstExcludedLanguage == "" || firstExcludedLanguage == language) {
firstExcludedLanguage = language
firstExcludedLanguageSize += f.Size
}
return nil
})
if err != nil {
return nil, err
}
// If there are no included languages add the first excluded language
if len(sizes) == 0 && firstExcludedLanguage != "" {
sizes[firstExcludedLanguage] = firstExcludedLanguageSize
}
return mergeLanguageStats(sizes), nil
}
func readFile(f *object.File, limit int64) ([]byte, error) {
r, err := f.Reader()
if err != nil {
return nil, err
}
defer r.Close()
if limit <= 0 {
return io.ReadAll(r)
}
size := f.Size
if limit > 0 && size > limit {
size = limit
}
buf := bytes.NewBuffer(nil)
buf.Grow(int(size))
_, err = io.Copy(buf, io.LimitReader(r, limit))
return buf.Bytes(), err
}

View File

@@ -1,8 +1,6 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//go:build !gogit
package languagestats
import (

71
modules/git/localfs.go Normal file
View File

@@ -0,0 +1,71 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package git
import (
"context"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/util"
)
// IsRepositoryExist returns true if the repository directory exists in the disk
func IsRepositoryExist(ctx context.Context, repo RepositoryFacade) (bool, error) {
return util.IsExist(gitcmd.RepoLocalPath(repo))
}
// DeleteRepository deletes the repository directory from the disk, it will return
// nil if the repository does not exist.
func DeleteRepository(ctx context.Context, repo RepositoryFacade) error {
return util.RemoveAll(gitcmd.RepoLocalPath(repo))
}
// RenameRepository renames a repository's name on disk
func RenameRepository(ctx context.Context, repo, newRepo RepositoryFacade) error {
dstDir := gitcmd.RepoLocalPath(newRepo)
if err := os.MkdirAll(filepath.Dir(dstDir), os.ModePerm); err != nil {
return fmt.Errorf("Failed to create dir %s: %w", filepath.Dir(dstDir), err)
}
if err := util.Rename(gitcmd.RepoLocalPath(repo), dstDir); err != nil {
return fmt.Errorf("rename repository directory: %w", err)
}
return nil
}
func InitRepository(ctx context.Context, repo RepositoryFacade, objectFormatName string) error {
return InitRepositoryLocal(ctx, gitcmd.RepoLocalPath(repo), true, objectFormatName)
}
func GetRepoFS(repo RepositoryFacade) fs.FS {
return os.DirFS(gitcmd.RepoLocalPath(repo))
}
func IsRepoFileExist(ctx context.Context, repo RepositoryFacade, relativeFilePath string) (bool, error) {
absoluteFilePath := filepath.Join(gitcmd.RepoLocalPath(repo), relativeFilePath)
return util.IsExist(absoluteFilePath)
}
func IsRepoDirExist(ctx context.Context, repo RepositoryFacade, relativeDirPath string) (bool, error) {
absoluteDirPath := filepath.Join(gitcmd.RepoLocalPath(repo), relativeDirPath)
return util.IsDir(absoluteDirPath)
}
func RemoveRepoFileOrDir(ctx context.Context, repo RepositoryFacade, relativeFileOrDirPath string) error {
absoluteFilePath := filepath.Join(gitcmd.RepoLocalPath(repo), relativeFileOrDirPath)
return util.Remove(absoluteFilePath)
}
func CreateRepoFile(ctx context.Context, repo RepositoryFacade, relativeFilePath string) (io.WriteCloser, error) {
absoluteFilePath := filepath.Join(gitcmd.RepoLocalPath(repo), relativeFilePath)
if err := os.MkdirAll(filepath.Dir(absoluteFilePath), os.ModePerm); err != nil {
return nil, err
}
return os.Create(absoluteFilePath)
}

View File

@@ -1,26 +1,25 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"path/filepath"
"testing"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/setting"
)
const testReposDir = "tests/repos/"
func mockRepository(repoPath string) gitcmd.RepositoryFacade {
if !filepath.IsAbs(repoPath) {
// resolve repository path relative to the unit test fixture directory
repoPath = filepath.Join(setting.GetGiteaTestSourceRoot(), "modules/git/tests/repos", repoPath)
repoPath, _ = filepath.Abs(filepath.Join(testReposDir, repoPath))
}
return gitcmd.RepositoryManaged(repoPath, repoPath)
return gitcmd.RepositoryUnmanaged(repoPath)
}
func TestMain(m *testing.M) {
setting.SetupGiteaTestEnv()
git.RunGitTests(m)
RunGitTests(m)
}

View File

@@ -1,20 +1,19 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
"fmt"
"strings"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/util"
)
// MergeBase checks and returns merge base of two commits.
func MergeBase(ctx context.Context, repo git.RepositoryFacade, baseCommitID, headCommitID string) (string, error) {
func MergeBase(ctx context.Context, repo RepositoryFacade, baseCommitID, headCommitID string) (string, error) {
mergeBase, stderr, err := gitcmd.NewCommand("merge-base").
AddDashesAndList(baseCommitID, headCommitID).WithRepo(repo).RunStdString(ctx)
if err != nil {

View File

@@ -1,14 +1,13 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"bufio"
"context"
"fmt"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/util"
)
@@ -18,7 +17,7 @@ const MaxConflictedDetectFiles = 10
// MergeTree performs a merge between two commits (baseRef and headRef) with an optional merge base.
// It returns the resulting tree hash, a list of conflicted files (if any), and an error if the operation fails.
// If there are no conflicts, the list of conflicted files will be nil.
func MergeTree(ctx context.Context, repo git.RepositoryFacade, baseRef, headRef, mergeBase string) (treeID string, isErrHasConflicts bool, conflictFiles []string, _ error) {
func MergeTree(ctx context.Context, repo RepositoryFacade, baseRef, headRef, mergeBase string) (treeID string, isErrHasConflicts bool, conflictFiles []string, _ error) {
cmd := gitcmd.NewCommand("merge-tree", "--write-tree", "-z", "--name-only", "--no-messages").
AddOptionFormat("--merge-base=%s", mergeBase).
AddDynamicArguments(baseRef, headRef)

View File

@@ -1,7 +1,7 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"path/filepath"

View File

@@ -10,6 +10,7 @@ import (
"strconv"
"strings"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
)
@@ -20,13 +21,13 @@ func CatFileBatchCheck(ctx context.Context, cmd *gitcmd.Command, tmpBasePath str
}
// CatFileBatchCheckAllObjects runs cat-file with --batch-check --batch-all
func CatFileBatchCheckAllObjects(ctx context.Context, cmd *gitcmd.Command, tmpBasePath string) error {
return cmd.AddArguments("cat-file", "--batch-check", "--batch-all-objects").WithDir(tmpBasePath).RunWithStderr(ctx)
func CatFileBatchCheckAllObjects(ctx context.Context, cmd *gitcmd.Command, gitRepo *git.Repository) error {
return cmd.AddArguments("cat-file", "--batch-check", "--batch-all-objects").WithRepo(gitRepo).RunWithStderr(ctx)
}
// CatFileBatch runs cat-file --batch
func CatFileBatch(ctx context.Context, cmd *gitcmd.Command, tmpBasePath string) error {
return cmd.AddArguments("cat-file", "--batch").WithDir(tmpBasePath).RunWithStderr(ctx)
func CatFileBatch(ctx context.Context, cmd *gitcmd.Command, gitRepo git.RepositoryFacade) error {
return cmd.AddArguments("cat-file", "--batch").WithRepo(gitRepo).RunWithStderr(ctx)
}
// BlobsLessThan1024FromCatFileBatchCheck reads a pipeline from cat-file --batch-check and returns the blobs <1024 in size

View File

@@ -1,8 +1,6 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//go:build !gogit
package pipeline
import (
@@ -21,7 +19,7 @@ func FindLFSFile(ctx context.Context, repo *git.Repository, objectID git.ObjectI
cmd := gitcmd.NewCommand("rev-list", "--all")
revListReader, revListReaderClose := cmd.MakeStdoutPipe()
defer revListReaderClose()
err := cmd.WithDir(repo.Path).
err := cmd.WithRepo(repo).
WithPipelineFunc(func(context gitcmd.Context) (err error) {
results, err = findLFSFileFunc(ctx, repo, objectID, revListReader)
return err
@@ -146,6 +144,6 @@ func findLFSFileFunc(ctx context.Context, repo *git.Repository, objectID git.Obj
}
sort.Sort(lfsResultSlice(results))
err = fillResultNameRev(ctx, repo.Path, results)
err = fillResultNameRev(ctx, repo, results)
return results, err
}

View File

@@ -1,86 +0,0 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//go:build gogit
package pipeline
import (
"context"
"fmt"
"io"
"sort"
"strings"
"gitea.dev/modules/git"
gogit "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
)
// FindLFSFile finds commits that contain a provided pointer file hash
func FindLFSFile(ctx context.Context, repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, error) {
resultsMap := map[string]*LFSResult{}
results := make([]*LFSResult, 0)
gogitRepo := repo.GoGitRepo()
commitsIter, err := gogitRepo.Log(&gogit.LogOptions{
Order: gogit.LogOrderCommitterTime,
All: true,
})
if err != nil {
return nil, fmt.Errorf("LFS error occurred, failed to get GoGit CommitsIter: err: %w", err)
}
err = commitsIter.ForEach(func(gitCommit *object.Commit) error {
tree, err := gitCommit.Tree()
if err != nil {
return err
}
treeWalker := object.NewTreeWalker(tree, true, nil)
defer treeWalker.Close()
for {
name, entry, err := treeWalker.Next()
if err == io.EOF {
break
}
if entry.Hash == plumbing.Hash(objectID.RawValue()) {
parents := make([]git.ObjectID, len(gitCommit.ParentHashes))
for i, parentCommitID := range gitCommit.ParentHashes {
parents[i] = git.ParseGogitHash(parentCommitID)
}
result := LFSResult{
Name: name,
SHA: gitCommit.Hash.String(),
Summary: strings.Split(strings.TrimSpace(gitCommit.Message), "\n")[0],
When: gitCommit.Author.When,
ParentHashes: parents,
}
resultsMap[gitCommit.Hash.String()+":"+name] = &result
}
}
return nil
})
if err != nil && err != io.EOF {
return nil, fmt.Errorf("LFS error occurred, failure in CommitIter.ForEach: %w", err)
}
for _, result := range resultsMap {
hasParent := false
for _, parentHash := range result.ParentHashes {
if _, hasParent = resultsMap[parentHash.String()+":"+result.Name]; hasParent {
break
}
}
if !hasParent {
results = append(results, result)
}
}
sort.Sort(lfsResultSlice(results))
err = fillResultNameRev(ctx, repo.Path, results)
return results, err
}

View File

@@ -9,15 +9,16 @@ import (
"errors"
"strings"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"golang.org/x/sync/errgroup"
)
func fillResultNameRev(ctx context.Context, basePath string, results []*LFSResult) error {
func fillResultNameRev(ctx context.Context, repo git.RepositoryFacade, results []*LFSResult) error {
// Should really use a go-git function here but name-rev is not completed and recapitulating it is not simple
wg := errgroup.Group{}
cmd := gitcmd.NewCommand("name-rev", "--stdin", "--name-only", "--always").WithDir(basePath)
cmd := gitcmd.NewCommand("name-rev", "--stdin", "--name-only", "--always").WithRepo(repo)
stdin, stdinClose := cmd.MakeStdinPipe()
stdout, stdoutClose := cmd.MakeStdoutPipe()
defer stdinClose()

27
modules/git/push.go Normal file
View File

@@ -0,0 +1,27 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package git
import (
"context"
"gitea.dev/modules/git/gitcmd"
)
// PushToExternal pushes a managed repository to an external remote.
func PushToExternal(ctx context.Context, repo RepositoryFacade, opts PushOptions) error {
return Push(ctx, gitcmd.RepoLocalPath(repo), opts)
}
// PushManaged pushes from one managed repository to another managed repository.
func PushManaged(ctx context.Context, fromRepo, toRepo RepositoryFacade, opts PushOptions) error {
opts.Remote = gitcmd.RepoLocalPath(toRepo)
return Push(ctx, gitcmd.RepoLocalPath(fromRepo), opts)
}
// PushFromLocal pushes from a local path to a managed repository.
func PushFromLocal(ctx context.Context, fromLocalPath string, toRepo RepositoryFacade, opts PushOptions) error {
opts.Remote = gitcmd.RepoLocalPath(toRepo)
return Push(ctx, fromLocalPath, opts)
}

View File

@@ -8,6 +8,7 @@ import (
"regexp"
"strings"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/setting"
"gitea.dev/modules/util"
)
@@ -242,3 +243,11 @@ func ParseRefSuffix(ref string) (refName, refSuffix string) {
}
return ref[:suffixIdx], ref[suffixIdx:]
}
func UpdateRef(ctx context.Context, repo RepositoryFacade, refName, newCommitID string) error {
return gitcmd.NewCommand("update-ref").AddDynamicArguments(refName, newCommitID).WithRepo(repo).Run(ctx)
}
func RemoveRef(ctx context.Context, repo RepositoryFacade, refName string) error {
return gitcmd.NewCommand("update-ref", "--no-deref", "-d").AddDynamicArguments(refName).WithRepo(repo).Run(ctx)
}

View File

@@ -1,13 +1,12 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"context"
"errors"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
giturl "gitea.dev/modules/git/url"
"gitea.dev/modules/util"
@@ -20,8 +19,8 @@ const (
RemoteOptionMirrorFetch RemoteOption = "--mirror=fetch"
)
func ManagedRemoteAdd(ctx context.Context, repo git.RepositoryFacade, remoteName, remoteURL string, options ...RemoteOption) error {
return git.LockConfigAndDo(ctx, repo, func(ctx context.Context) error {
func ManagedRemoteAdd(ctx context.Context, repo RepositoryFacade, remoteName, remoteURL string, options ...RemoteOption) error {
return LockConfigAndDo(ctx, repo, func(ctx context.Context) error {
cmd := gitcmd.NewCommand("remote", "add")
if len(options) > 0 {
switch options[0] {
@@ -38,17 +37,16 @@ func ManagedRemoteAdd(ctx context.Context, repo git.RepositoryFacade, remoteName
})
}
func ManagedRemoteRemove(ctx context.Context, repo git.RepositoryFacade, remoteName string) error {
return git.LockConfigAndDo(ctx, repo, func(ctx context.Context) error {
func ManagedRemoteRemove(ctx context.Context, repo RepositoryFacade, remoteName string) error {
return LockConfigAndDo(ctx, repo, func(ctx context.Context) error {
cmd := gitcmd.NewCommand("remote", "rm").AddDynamicArguments(remoteName)
_, _, err := cmd.WithRepo(repo).RunStdString(ctx)
return err
})
}
// GitRemoteGetURL returns the url of a specific remote of the repository.
func GitRemoteGetURL(ctx context.Context, repo git.RepositoryFacade, remoteName string) (*giturl.GitURL, error) {
addr, err := git.GetRemoteAddress(ctx, repo, remoteName)
func ParseRemoteAddressURL(ctx context.Context, repo RepositoryFacade, remoteName string) (*giturl.GitURL, error) {
addr, err := GetRemoteAddress(ctx, repo, remoteName)
if err != nil {
return nil, err
}

View File

@@ -13,6 +13,7 @@ import (
"path/filepath"
"strconv"
"strings"
"sync"
"time"
"gitea.dev/modules/git/gitcmd"
@@ -24,13 +25,20 @@ import (
type RepositoryFacade = gitcmd.RepositoryFacade
type RepositoryBase struct {
Path string // absolute path
// TODO: refactor it to a private field "localPath" in the future
// * for repo accessing purpose, in most causes, use "WithRepo", or RepoLocalPath(repo) if the local path must be used
// * for error handling & logging purpose, it needs to introduce a new function "git.RepoLogName()" to handle various cases
Path string
LastCommitCache *LastCommitCache
repoFacade RepositoryFacade
tagCache *ObjectCache[*Tag]
objectFormatCache ObjectFormat
mu sync.Mutex
catFileBatchCloser CatFileBatchCloser
catFileBatchInUse bool
}
var _ gitcmd.RepositoryFacade = (*Repository)(nil)
@@ -78,6 +86,14 @@ func (repo *Repository) Close() error {
}
repo.LastCommitCache = nil
repo.tagCache = nil
repo.mu.Lock()
defer repo.mu.Unlock()
if repo.catFileBatchCloser != nil {
repo.catFileBatchCloser.Close()
repo.catFileBatchCloser = nil
repo.catFileBatchInUse = false
}
return repo.closeInternal()
}
@@ -87,8 +103,8 @@ func IsRepoURLAccessible(ctx context.Context, url string) bool {
return err == nil
}
// InitRepository initializes a new Git repository.
func InitRepository(ctx context.Context, repoPath string, bare bool, objectFormatName string) error {
// InitRepositoryLocal initializes a new Git repository.
func InitRepositoryLocal(ctx context.Context, repoPath string, bare bool, objectFormatName string) error {
err := os.MkdirAll(repoPath, os.ModePerm)
if err != nil {
return err
@@ -115,7 +131,7 @@ func (repo *Repository) IsEmpty(ctx context.Context) (bool, error) {
stdout, _, err := gitcmd.NewCommand().
AddOptionFormat("--git-dir=%s", repo.Path).
AddArguments("rev-list", "-n", "1", "--all").
WithDir(repo.Path).
WithRepo(repo).
RunStdString(ctx)
if err != nil {
if (gitcmd.IsErrorExitCode(err, 1) && err.Stderr() == "") || gitcmd.IsErrorExitCode(err, 129) {
@@ -255,3 +271,41 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error {
return nil
}
// CatFileBatch obtains a "batch object provider" for this repository.
// It reuses an existing one if available, otherwise creates a new one.
func (repo *Repository) CatFileBatch(ctx context.Context) (_ CatFileBatch, closeFunc func(), err error) {
repo.mu.Lock()
defer repo.mu.Unlock()
if repo.catFileBatchCloser != nil && !repo.catFileBatchInUse {
if ctx != repo.catFileBatchCloser.Context() {
repo.catFileBatchCloser.Close()
repo.catFileBatchCloser = nil
repo.catFileBatchInUse = false
}
}
if repo.catFileBatchCloser == nil {
repo.catFileBatchCloser, err = NewBatch(ctx, repo)
if err != nil {
repo.catFileBatchCloser = nil // otherwise it is "interface(nil)" and will cause wrong logic
return nil, nil, err
}
}
if !repo.catFileBatchInUse {
repo.catFileBatchInUse = true
return CatFileBatch(repo.catFileBatchCloser), func() {
repo.mu.Lock()
defer repo.mu.Unlock()
repo.catFileBatchInUse = false
}, nil
}
tempBatch, err := NewBatch(ctx, repo)
if err != nil {
return nil, nil, err
}
return tempBatch, tempBatch.Close, nil
}

View File

@@ -6,73 +6,16 @@
package git
import (
"context"
"sync"
"gitea.dev/modules/log"
)
const isGogit = false
type Repository struct {
RepositoryBase
mu sync.Mutex
catFileBatchCloser CatFileBatchCloser
catFileBatchInUse bool
}
func openRepositoryInternal(_ *Repository) error {
return nil
}
// CatFileBatch obtains a "batch object provider" for this repository.
// It reuses an existing one if available, otherwise creates a new one.
func (repo *Repository) CatFileBatch(ctx context.Context) (_ CatFileBatch, closeFunc func(), err error) {
repo.mu.Lock()
defer repo.mu.Unlock()
if repo.catFileBatchCloser != nil && !repo.catFileBatchInUse {
if ctx != repo.catFileBatchCloser.Context() {
repo.catFileBatchCloser.Close()
repo.catFileBatchCloser = nil
repo.catFileBatchInUse = false
}
}
if repo.catFileBatchCloser == nil {
repo.catFileBatchCloser, err = NewBatch(ctx, repo)
if err != nil {
repo.catFileBatchCloser = nil // otherwise it is "interface(nil)" and will cause wrong logic
return nil, nil, err
}
}
if !repo.catFileBatchInUse {
repo.catFileBatchInUse = true
return CatFileBatch(repo.catFileBatchCloser), func() {
repo.mu.Lock()
defer repo.mu.Unlock()
repo.catFileBatchInUse = false
}, nil
}
log.Debug("Opening temporary cat file batch for: %s", repo.Path)
tempBatch, err := NewBatch(ctx, repo)
if err != nil {
return nil, nil, err
}
return tempBatch, tempBatch.Close, nil
}
func (repo *Repository) closeInternal() error {
repo.mu.Lock()
defer repo.mu.Unlock()
if repo.catFileBatchCloser != nil {
repo.catFileBatchCloser.Close()
repo.catFileBatchCloser = nil
repo.catFileBatchInUse = false
}
return nil
}

View File

@@ -20,7 +20,7 @@ func (repo *Repository) AddRemote(ctx context.Context, name, url string, fetch b
cmd.AddArguments("-f")
}
_, _, err := cmd.AddDynamicArguments(name, url).
WithDir(repo.Path).
WithRepo(repo).
RunStdString(ctx)
return err
}

View File

@@ -50,7 +50,7 @@ const prettyLogFormat = `--pretty=format:%H`
func (repo *Repository) ShowPrettyFormatLogToList(ctx context.Context, revisionRange string) ([]*Commit, error) {
// avoid: ambiguous argument 'refs/a...refs/b': unknown revision or path not in the working tree. Use '--': 'git <command> [<revision>...] -- [<file>...]'
logs, _, err := gitcmd.NewCommand("log").AddArguments(prettyLogFormat).
AddDynamicArguments(revisionRange).AddArguments("--").WithDir(repo.Path).
AddDynamicArguments(revisionRange).AddArguments("--").WithRepo(repo).
RunStdBytes(ctx)
if err != nil {
return nil, err
@@ -86,7 +86,7 @@ func (repo *Repository) getCommitByPathWithID(ctx context.Context, id ObjectID,
stdout, _, runErr := gitcmd.NewCommand("log", "-1", prettyLogFormat).
AddDynamicArguments(id.String()).
AddDashesAndList(relpath).
WithDir(repo.Path).
WithRepo(repo).
RunStdString(ctx)
if runErr != nil {
return nil, runErr
@@ -104,7 +104,7 @@ func (repo *Repository) getCommitByPathWithID(ctx context.Context, id ObjectID,
func (repo *Repository) GetCommitByPath(ctx context.Context, relpath string) (*Commit, error) {
stdout, _, runErr := gitcmd.NewCommand("log", "-1", prettyLogFormat).
AddDashesAndList(relpath).
WithDir(repo.Path).
WithRepo(repo).
RunStdBytes(ctx)
if runErr != nil {
return nil, runErr
@@ -138,7 +138,7 @@ func (repo *Repository) commitsByRangeWithTime(ctx context.Context, id ObjectID,
cmd.AddOptionFormat("--until=%s", until)
}
stdout, _, err := cmd.WithDir(repo.Path).RunStdBytes(ctx)
stdout, _, err := cmd.WithRepo(repo).RunStdBytes(ctx)
if err != nil {
return nil, err
}
@@ -192,7 +192,7 @@ func (repo *Repository) searchCommits(ctx context.Context, id ObjectID, opts Sea
// search for commits matching given constraints and keywords in commit msg
addCommonSearchArgs(cmd)
stdout, _, err := cmd.WithDir(repo.Path).RunStdBytes(ctx)
stdout, _, err := cmd.WithRepo(repo).RunStdBytes(ctx)
if err != nil {
return nil, err
}
@@ -213,7 +213,7 @@ func (repo *Repository) searchCommits(ctx context.Context, id ObjectID, opts Sea
hashCmd.AddDynamicArguments(v)
// search with given constraints for commit matching sha hash of v
hashMatching, _, err := hashCmd.WithDir(repo.Path).RunStdBytes(ctx)
hashMatching, _, err := hashCmd.WithRepo(repo).RunStdBytes(ctx)
if err != nil || bytes.Contains(stdout, hashMatching) {
continue
}
@@ -231,7 +231,7 @@ func (repo *Repository) FileChangedBetweenCommits(ctx context.Context, filename,
stdout, _, err := gitcmd.NewCommand("diff", "--name-only", "-z").
AddDynamicArguments(id1, id2).
AddDashesAndList(filename).
WithDir(repo.Path).
WithRepo(repo).
RunStdBytes(ctx)
if err != nil {
return false, err
@@ -275,7 +275,7 @@ func (repo *Repository) CommitsByFileAndRange(ctx context.Context, opts CommitsB
stdoutReader, stdoutReaderClose := gitCmd.MakeStdoutPipe()
defer stdoutReaderClose()
err := gitCmd.WithDir(repo.Path).
err := gitCmd.WithRepo(repo).
WithPipelineFunc(func(context gitcmd.Context) error {
objectFormat, err := repo.GetObjectFormat(ctx)
if err != nil {
@@ -316,7 +316,7 @@ func (repo *Repository) CommitsByFileAndRange(ctx context.Context, opts CommitsB
// If "before" and "after" are not related, it returns the all commits for the "after" commit.
func (repo *Repository) CommitsBetween(ctx context.Context, afterRef, beforeRef RefName, limit int, optSkip ...int) ([]*Commit, error) {
gitCmd := func() *gitcmd.Command {
cmd := gitcmd.NewCommand("rev-list").WithDir(repo.Path)
cmd := gitcmd.NewCommand("rev-list").WithRepo(repo)
if limit >= 0 {
cmd.AddOptionValues("--max-count", strconv.Itoa(limit))
}
@@ -351,7 +351,7 @@ func (repo *Repository) commitsBefore(ctx context.Context, id ObjectID, limit in
}
cmd.AddDynamicArguments(id.String())
stdout, _, runErr := cmd.WithDir(repo.Path).RunStdBytes(ctx)
stdout, _, runErr := cmd.WithRepo(repo).RunStdBytes(ctx)
if runErr != nil {
return nil, runErr
}
@@ -392,7 +392,7 @@ func (repo *Repository) getBranches(ctx context.Context, env []string, commitID
AddOptionValues("--contains", commitID).
AddArguments(BranchPrefix).
WithEnv(env).
WithDir(repo.Path).
WithRepo(repo).
RunStdString(ctx)
if err != nil {
return nil, err
@@ -418,7 +418,7 @@ func (repo *Repository) GetCommitsFromIDs(ctx context.Context, commitIDs []strin
func (repo *Repository) IsCommitInBranch(ctx context.Context, commitID, branch string) (r bool, err error) {
stdout, _, err := gitcmd.NewCommand("branch", "--contains").
AddDynamicArguments(commitID, branch).
WithDir(repo.Path).
WithRepo(repo).
RunStdString(ctx)
if err != nil {
return false, err
@@ -431,7 +431,7 @@ func (repo *Repository) GetCommitBranchStart(ctx context.Context, env []string,
cmd := gitcmd.NewCommand("log", prettyLogFormat)
cmd.AddDynamicArguments(endCommitID)
stdout, _, runErr := cmd.WithDir(repo.Path).
stdout, _, runErr := cmd.WithRepo(repo).
WithEnv(env).
RunStdBytes(ctx)
if runErr != nil {

View File

@@ -57,7 +57,7 @@ func (repo *Repository) ConvertToGitID(ctx context.Context, commitID string) (Ob
actualCommitID, _, err := gitcmd.NewCommand("rev-parse", "--verify").
AddDynamicArguments(commitID).
WithDir(repo.Path).
WithRepo(repo).
RunStdString(ctx)
actualCommitID = strings.TrimSpace(actualCommitID)
if err != nil {

View File

@@ -19,7 +19,7 @@ import (
func (repo *Repository) ResolveReference(ctx context.Context, name string) (string, error) {
stdout, _, err := gitcmd.NewCommand("show-ref", "--hash").
AddDynamicArguments(name).
WithDir(repo.Path).
WithRepo(repo).
RunStdString(ctx)
if err != nil {
if strings.Contains(err.Error(), "not a valid ref") {

View File

@@ -11,8 +11,6 @@ import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"regexp"
"strings"
@@ -44,7 +42,7 @@ func (repo *Repository) GetDiffNumChangedFiles(ctx context.Context, base, head s
if err := gitcmd.NewCommand("diff", "-z", "--name-only").
AddDynamicArguments(base + separator + head).
AddArguments("--").
WithDir(repo.Path).
WithRepo(repo).
WithStdoutCopy(w).
RunWithStderr(ctx); err != nil {
if gitcmd.IsStderr(err, gitcmd.StderrNoMergeBase) {
@@ -62,7 +60,7 @@ var patchCommits = regexp.MustCompile(`^From\s(\w+)\s`)
// GetDiff generates and returns patch data between given revisions, optimized for human readability
func (repo *Repository) GetDiff(ctx context.Context, compareArg string, w io.Writer) error {
return gitcmd.NewCommand("diff", "-p").AddDynamicArguments(compareArg).
WithDir(repo.Path).
WithRepo(repo).
WithStdoutCopy(w).
Run(ctx)
}
@@ -71,7 +69,7 @@ func (repo *Repository) GetDiff(ctx context.Context, compareArg string, w io.Wri
func (repo *Repository) GetDiffBinary(ctx context.Context, compareArg string, w io.Writer) error {
return gitcmd.NewCommand("diff", "-p", "--binary", "--histogram").
AddDynamicArguments(compareArg).
WithDir(repo.Path).
WithRepo(repo).
WithStdoutCopy(w).
Run(ctx)
}
@@ -79,7 +77,7 @@ func (repo *Repository) GetDiffBinary(ctx context.Context, compareArg string, w
// GetPatch generates and returns format-patch data between given revisions, able to be used with `git apply`
func (repo *Repository) GetPatch(ctx context.Context, compareArg string, w io.Writer) error {
return gitcmd.NewCommand("format-patch", "--binary", "--stdout").AddDynamicArguments(compareArg).
WithDir(repo.Path).
WithRepo(repo).
WithStdoutCopy(w).
Run(ctx)
}
@@ -98,7 +96,7 @@ func (repo *Repository) GetFilesChangedBetween(ctx context.Context, base, head s
} else {
cmd.AddDynamicArguments(base, head)
}
stdout, _, err := cmd.WithDir(repo.Path).RunStdString(ctx)
stdout, _, err := cmd.WithRepo(repo).RunStdString(ctx)
if err != nil {
return nil, err
}
@@ -115,8 +113,8 @@ func (repo *Repository) GetFilesChangedBetween(ctx context.Context, base, head s
// ReadPatchCommit will check if a diff patch exists and return stats
func (repo *Repository) ReadPatchCommit(prID int64) (commitSHA string, err error) {
// Migrated repositories download patches to "pulls" location
patchFile := fmt.Sprintf("pulls/%d.patch", prID)
loadPatch, err := os.Open(filepath.Join(repo.Path, patchFile))
repoFS := GetRepoFS(repo)
loadPatch, err := repoFS.Open(fmt.Sprintf("pulls/%d.patch", prID))
if err != nil {
return "", err
}

View File

@@ -103,7 +103,7 @@ func TestReadWritePullHead(t *testing.T) {
newCommit := "feaf4ba6bc635fec442f46ddd4512416ec43c2c2"
_, _, err = gitcmd.NewCommand("update-ref").
AddDynamicArguments(PullPrefix+"1/head", newCommit).
WithDir(repo.Path).
WithRepo(repo).
RunStdString(t.Context())
if err != nil {
assert.NoError(t, err)
@@ -123,7 +123,7 @@ func TestReadWritePullHead(t *testing.T) {
// Remove file after the test
_, _, err = gitcmd.NewCommand("update-ref", "--no-deref", "-d").
AddDynamicArguments(PullPrefix + "1/head").
WithDir(repo.Path).
WithRepo(repo).
RunStdString(t.Context())
assert.NoError(t, err)
}

View File

@@ -22,7 +22,7 @@ func (repo *Repository) ReadTreeToIndex(ctx context.Context, treeish string, ind
}
if len(treeish) != objectFormat.FullLength() {
res, _, err := gitcmd.NewCommand("rev-parse", "--verify").AddDynamicArguments(treeish).WithDir(repo.Path).RunStdString(ctx)
res, _, err := gitcmd.NewCommand("rev-parse", "--verify").AddDynamicArguments(treeish).WithRepo(repo).RunStdString(ctx)
if err != nil {
return err
}
@@ -42,7 +42,7 @@ func (repo *Repository) readTreeToIndex(ctx context.Context, id ObjectID, indexF
if len(indexFilename) > 0 {
env = append(os.Environ(), "GIT_INDEX_FILE="+indexFilename[0])
}
_, _, err := gitcmd.NewCommand("read-tree").AddDynamicArguments(id.String()).WithDir(repo.Path).WithEnv(env).RunStdString(ctx)
_, _, err := gitcmd.NewCommand("read-tree").AddDynamicArguments(id.String()).WithRepo(repo).WithEnv(env).RunStdString(ctx)
if err != nil {
return err
}
@@ -75,14 +75,14 @@ func (repo *Repository) ReadTreeToTemporaryIndex(ctx context.Context, treeish st
// EmptyIndex empties the index
func (repo *Repository) EmptyIndex(ctx context.Context) error {
_, _, err := gitcmd.NewCommand("read-tree", "--empty").WithDir(repo.Path).RunStdString(ctx)
_, _, err := gitcmd.NewCommand("read-tree", "--empty").WithRepo(repo).RunStdString(ctx)
return err
}
// LsFiles checks if the given filenames are in the index
func (repo *Repository) LsFiles(ctx context.Context, filenames ...string) ([]string, error) {
cmd := gitcmd.NewCommand("ls-files", "-z").AddDashesAndList(filenames...)
res, _, err := cmd.WithDir(repo.Path).RunStdBytes(ctx)
res, _, err := cmd.WithRepo(repo).RunStdBytes(ctx)
if err != nil {
return nil, err
}
@@ -109,7 +109,7 @@ func (repo *Repository) RemoveFilesFromIndex(ctx context.Context, filenames ...s
}
}
return cmd.
WithDir(repo.Path).
WithRepo(repo).
WithStdinBytes(input.Bytes()).
RunWithStderr(ctx)
}
@@ -129,7 +129,7 @@ func (repo *Repository) AddObjectsToIndex(ctx context.Context, objects ...IndexO
input.WriteString(object.Mode + " blob " + object.Object.String() + "\t" + object.Filename + "\000")
}
return cmd.
WithDir(repo.Path).
WithRepo(repo).
WithStdinBytes(input.Bytes()).
RunWithStderr(ctx)
}
@@ -141,7 +141,7 @@ func (repo *Repository) AddObjectToIndex(ctx context.Context, mode string, objec
// WriteTree writes the current index as a tree to the object db and returns its hash
func (repo *Repository) WriteTree(ctx context.Context) (*Tree, error) {
stdout, _, runErr := gitcmd.NewCommand("write-tree").WithDir(repo.Path).RunStdString(ctx)
stdout, _, runErr := gitcmd.NewCommand("write-tree").WithRepo(repo).RunStdString(ctx)
if runErr != nil {
return nil, runErr
}

View File

@@ -68,7 +68,7 @@ func (repo *Repository) hashObjectBytes(ctx context.Context, buf []byte, save bo
cmd = gitcmd.NewCommand("hash-object", "--stdin")
}
stdout, _, err := cmd.
WithDir(repo.Path).
WithRepo(repo).
WithStdinBytes(buf).
RunStdString(ctx)
if err != nil {

View File

@@ -30,7 +30,7 @@ func (repo *Repository) ListOccurrences(ctx context.Context, refType, commitSHA
return nil, util.NewInvalidArgumentErrorf(`can only use "branch" or "tag" for refType, but got %q`, refType)
}
stdout, _, err := cmd.AddArguments("--no-color", "--sort=-creatordate", "--contains").
AddDynamicArguments(commitSHA).WithDir(repo.Path).RunStdString(ctx)
AddDynamicArguments(commitSHA).WithRepo(repo).RunStdString(ctx)
if err != nil {
return nil, err
}

View File

@@ -20,7 +20,7 @@ func (repo *Repository) GetRefsFiltered(ctx context.Context, pattern string) ([]
cmd := gitcmd.NewCommand("for-each-ref")
stdoutReader, stdoutReaderClose := cmd.MakeStdoutPipe()
defer stdoutReaderClose()
err := cmd.WithDir(repo.Path).
err := cmd.WithRepo(repo).
WithPipelineFunc(func(context gitcmd.Context) error {
bufReader := bufio.NewReader(stdoutReader)
for {

View File

@@ -42,7 +42,7 @@ func (repo *Repository) GetCodeActivityStats(ctx context.Context, fromTime time.
stdout, _, runErr := gitcmd.NewCommand("rev-list", "--count", "--no-merges", "--branches=*", "--date=iso").
AddOptionFormat("--since=%s", since).
WithDir(repo.Path).
WithRepo(repo).
RunStdString(ctx)
if runErr != nil {
return nil, runErr
@@ -65,7 +65,7 @@ func (repo *Repository) GetCodeActivityStats(ctx context.Context, fromTime time.
stdoutReader, stdoutReaderClose := gitCmd.MakeStdoutPipe()
defer stdoutReaderClose()
err = gitCmd.
WithDir(repo.Path).
WithRepo(repo).
WithPipelineFunc(func(ctx gitcmd.Context) error {
scanner := bufio.NewScanner(stdoutReader)
scanner.Split(bufio.ScanLines)

View File

@@ -19,7 +19,7 @@ const TagPrefix = "refs/tags/"
// CreateTag create one tag in the repository
func (repo *Repository) CreateTag(ctx context.Context, name, revision string) error {
_, _, err := gitcmd.NewCommand("tag").AddDashesAndList(name, revision).WithDir(repo.Path).RunStdString(ctx)
_, _, err := gitcmd.NewCommand("tag").AddDashesAndList(name, revision).WithRepo(repo).RunStdString(ctx)
return err
}
@@ -28,7 +28,7 @@ func (repo *Repository) CreateAnnotatedTag(ctx context.Context, name, message, r
_, _, err := gitcmd.NewCommand("tag", "-a", "-m").
AddDynamicArguments(message).
AddDashesAndList(name, revision).
WithDir(repo.Path).
WithRepo(repo).
RunStdString(ctx)
return err
}
@@ -39,7 +39,7 @@ func (repo *Repository) GetTagNameBySHA(ctx context.Context, sha string) (string
return "", fmt.Errorf("SHA is too short: %s", sha)
}
stdout, _, err := gitcmd.NewCommand("show-ref", "--tags", "-d").WithDir(repo.Path).RunStdString(ctx)
stdout, _, err := gitcmd.NewCommand("show-ref", "--tags", "-d").WithRepo(repo).RunStdString(ctx)
if err != nil {
return "", err
}
@@ -62,7 +62,7 @@ func (repo *Repository) GetTagNameBySHA(ctx context.Context, sha string) (string
// GetTagID returns the object ID for a tag (annotated tags have both an object SHA AND a commit SHA)
func (repo *Repository) GetTagID(ctx context.Context, name string) (string, error) {
stdout, _, err := gitcmd.NewCommand("show-ref", "--tags").AddDashesAndList(name).WithDir(repo.Path).RunStdString(ctx)
stdout, _, err := gitcmd.NewCommand("show-ref", "--tags").AddDashesAndList(name).WithRepo(repo).RunStdString(ctx)
if err != nil {
return "", err
}
@@ -122,7 +122,7 @@ func (repo *Repository) GetTagInfos(ctx context.Context, page, pageSize int) ([]
defer stdoutReaderClose()
err := cmd.AddOptionFormat("--format=%s", forEachRefFmt.Flag()).
AddArguments("--sort", "-*creatordate", "refs/tags").
WithDir(repo.Path).
WithRepo(repo).
WithPipelineFunc(func(context gitcmd.Context) error {
parser := forEachRefFmt.Parser(stdoutReader)
for {

View File

@@ -60,7 +60,7 @@ func (repo *Repository) CommitTree(ctx context.Context, author, committer *Signa
}
stdout, _, err := cmd.WithEnv(env).
WithDir(repo.Path).
WithRepo(repo).
WithStdinBytes(messageBytes.Bytes()).
RunStdString(ctx)
if err != nil {

View File

@@ -41,7 +41,7 @@ func (repo *Repository) GetTree(ctx context.Context, idStr string) (*Tree, error
if len(idStr) != objectFormat.FullLength() {
res, _, err := gitcmd.NewCommand("rev-parse", "--verify").
AddDynamicArguments(idStr).
WithDir(repo.Path).
WithRepo(repo).
RunStdString(ctx)
if err != nil {
return nil, err

View File

@@ -1,21 +1,21 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
package git
import (
"os"
"path/filepath"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
)
const notRegularFileMode = os.ModeSymlink | os.ModeNamedPipe | os.ModeSocket | os.ModeDevice | os.ModeCharDevice | os.ModeIrregular
// CalcRepositorySize returns the disk consumption for a given path
func CalcRepositorySize(repo git.RepositoryFacade) (int64, error) {
func CalcRepositorySize(repo RepositoryFacade) (int64, error) {
var size int64
err := filepath.WalkDir(repoPath(repo), func(_ string, entry os.DirEntry, err error) error {
err := filepath.WalkDir(gitcmd.RepoLocalPath(repo), func(_ string, entry os.DirEntry, err error) error {
if os.IsNotExist(err) { // ignore the error because some files (like temp/lock file) may be deleted during traversing.
return nil
} else if err != nil {

View File

@@ -5,6 +5,7 @@ package git
import (
"bytes"
"context"
"sort"
"gitea.dev/modules/util"
@@ -114,3 +115,8 @@ func sortTagsByTime(tags []*Tag) {
sorter := tagSorter(tags)
sort.Sort(sorter)
}
// IsTagExist returns true if given tag exists in the repository.
func IsTagExist(ctx context.Context, repo RepositoryFacade, name string) bool {
return IsReferenceExist(ctx, repo, TagPrefix+name)
}

View File

@@ -53,7 +53,7 @@ func (repo *Repository) LsTree(ctx context.Context, ref string, filenames ...str
cmd := gitcmd.NewCommand("ls-tree", "-z", "--name-only").
AddDashesAndList(append([]string{ref}, filenames...)...)
res, _, err := cmd.WithDir(repo.Path).RunStdBytes(ctx)
res, _, err := cmd.WithRepo(repo).RunStdBytes(ctx)
if err != nil {
return nil, err
}
@@ -69,7 +69,7 @@ func (repo *Repository) LsTree(ctx context.Context, ref string, filenames ...str
func (repo *Repository) GetTreePathLatestCommit(ctx context.Context, refName, treePath string) (*Commit, error) {
stdout, _, err := gitcmd.NewCommand("rev-list", "-1").
AddDynamicArguments(refName).AddDashesAndList(treePath).
WithDir(repo.Path).
WithRepo(repo).
RunStdString(ctx)
if err != nil {
return nil, err

View File

@@ -61,7 +61,7 @@ func (t *Tree) ListEntries(ctx context.Context, gitRepo *Repository) (Entries, e
return nil, err
}
stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).WithDir(gitRepo.Path).RunStdBytes(ctx)
stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).WithRepo(gitRepo).RunStdBytes(ctx)
if runErr != nil {
if gitcmd.IsStderr(runErr, gitcmd.StderrNotValidObjectName) || gitcmd.IsStderr(runErr, gitcmd.StderrNotTreeObject) {
return nil, ErrNotExist{
@@ -85,7 +85,7 @@ func (t *Tree) listEntriesRecursive(ctx context.Context, gitRepo *Repository, ex
stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-t", "-r").
AddArguments(extraArgs...).
AddDynamicArguments(t.ID.String()).
WithDir(gitRepo.Path).
WithRepo(gitRepo).
RunStdBytes(ctx)
if runErr != nil {
return nil, runErr

View File

@@ -1,24 +0,0 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
import (
"context"
"gitea.dev/modules/git"
)
// CloneExternalRepo clones an external repository to the managed repository.
func CloneExternalRepo(ctx context.Context, fromRemoteURL string, toRepo git.RepositoryFacade, opts git.CloneRepoOptions) error {
return git.Clone(ctx, fromRemoteURL, repoPath(toRepo), opts)
}
// CloneRepoToLocal clones a managed repository to a local path.
func CloneRepoToLocal(ctx context.Context, fromRepo git.RepositoryFacade, toLocalPath string, opts git.CloneRepoOptions) error {
return git.Clone(ctx, repoPath(fromRepo), toLocalPath, opts)
}
func CloneManaged(ctx context.Context, fromRepo, toRepo git.RepositoryFacade, opts git.CloneRepoOptions) error {
return git.Clone(ctx, repoPath(fromRepo), repoPath(toRepo), opts)
}

View File

@@ -1,74 +0,0 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
import (
"context"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/util"
)
var repoPath = gitcmd.RepoLocalPath // some functions need to operate local filesystem directly
// IsRepositoryExist returns true if the repository directory exists in the disk
func IsRepositoryExist(ctx context.Context, repo git.RepositoryFacade) (bool, error) {
return util.IsExist(repoPath(repo))
}
// DeleteRepository deletes the repository directory from the disk, it will return
// nil if the repository does not exist.
func DeleteRepository(ctx context.Context, repo git.RepositoryFacade) error {
return util.RemoveAll(repoPath(repo))
}
// RenameRepository renames a repository's name on disk
func RenameRepository(ctx context.Context, repo, newRepo git.RepositoryFacade) error {
dstDir := repoPath(newRepo)
if err := os.MkdirAll(filepath.Dir(dstDir), os.ModePerm); err != nil {
return fmt.Errorf("Failed to create dir %s: %w", filepath.Dir(dstDir), err)
}
if err := util.Rename(repoPath(repo), dstDir); err != nil {
return fmt.Errorf("rename repository directory: %w", err)
}
return nil
}
func InitRepository(ctx context.Context, repo git.RepositoryFacade, objectFormatName string) error {
return git.InitRepository(ctx, repoPath(repo), true, objectFormatName)
}
func GetRepoFS(repo git.RepositoryFacade) fs.FS {
return os.DirFS(repoPath(repo))
}
func IsRepoFileExist(ctx context.Context, repo git.RepositoryFacade, relativeFilePath string) (bool, error) {
absoluteFilePath := filepath.Join(repoPath(repo), relativeFilePath)
return util.IsExist(absoluteFilePath)
}
func IsRepoDirExist(ctx context.Context, repo git.RepositoryFacade, relativeDirPath string) (bool, error) {
absoluteDirPath := filepath.Join(repoPath(repo), relativeDirPath)
return util.IsDir(absoluteDirPath)
}
func RemoveRepoFileOrDir(ctx context.Context, repo git.RepositoryFacade, relativeFileOrDirPath string) error {
absoluteFilePath := filepath.Join(repoPath(repo), relativeFileOrDirPath)
return util.Remove(absoluteFilePath)
}
func CreateRepoFile(ctx context.Context, repo git.RepositoryFacade, relativeFilePath string) (io.WriteCloser, error) {
absoluteFilePath := filepath.Join(repoPath(repo), relativeFilePath)
if err := os.MkdirAll(filepath.Dir(absoluteFilePath), os.ModePerm); err != nil {
return nil, err
}
return os.Create(absoluteFilePath)
}

View File

@@ -1,27 +0,0 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
import (
"context"
"gitea.dev/modules/git"
)
// PushToExternal pushes a managed repository to an external remote.
func PushToExternal(ctx context.Context, repo git.RepositoryFacade, opts git.PushOptions) error {
return git.Push(ctx, repoPath(repo), opts)
}
// PushManaged pushes from one managed repository to another managed repository.
func PushManaged(ctx context.Context, fromRepo, toRepo git.RepositoryFacade, opts git.PushOptions) error {
opts.Remote = repoPath(toRepo)
return git.Push(ctx, repoPath(fromRepo), opts)
}
// PushFromLocal pushes from a local path to a managed repository.
func PushFromLocal(ctx context.Context, fromLocalPath string, toRepo git.RepositoryFacade, opts git.PushOptions) error {
opts.Remote = repoPath(toRepo)
return git.Push(ctx, fromLocalPath, opts)
}

View File

@@ -1,19 +0,0 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
import (
"context"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
)
func UpdateRef(ctx context.Context, repo git.RepositoryFacade, refName, newCommitID string) error {
return gitcmd.NewCommand("update-ref").AddDynamicArguments(refName, newCommitID).WithRepo(repo).Run(ctx)
}
func RemoveRef(ctx context.Context, repo git.RepositoryFacade, refName string) error {
return gitcmd.NewCommand("update-ref", "--no-deref", "-d").AddDynamicArguments(refName).WithRepo(repo).Run(ctx)
}

View File

@@ -1,15 +0,0 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
import (
"context"
"gitea.dev/modules/git"
)
// IsTagExist returns true if given tag exists in the repository.
func IsTagExist(ctx context.Context, repo git.RepositoryFacade, name string) bool {
return IsReferenceExist(ctx, repo, git.TagPrefix+name)
}

View File

@@ -13,7 +13,7 @@ import (
"gitea.dev/models/db"
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/git"
"gitea.dev/modules/graceful"
"gitea.dev/modules/indexer"
"gitea.dev/modules/indexer/code/bleve"
@@ -74,7 +74,7 @@ func index(ctx context.Context, indexer internal.Indexer, repoID int64) error {
return nil
}
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo)
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo)
if err != nil {
return err
}

View File

@@ -9,7 +9,6 @@ import (
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/git"
"gitea.dev/modules/git/languagestats"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/graceful"
"gitea.dev/modules/log"
"gitea.dev/modules/process"
@@ -37,7 +36,7 @@ func (db *DBIndexer) Index(id int64) error {
return err
}
gitRepo, err := gitrepo.OpenRepository(repo)
gitRepo, err := git.OpenRepository(repo)
if err != nil {
if err.Error() == "no such file or directory" {
return nil

View File

@@ -41,7 +41,7 @@ func SearchPointerBlobs(ctx context.Context, repo *git.Repository, pointerChan c
// 3. Take the shas of the blobs and batch read them
wg.Go(func() error {
return pipeline.CatFileBatch(ctx, cmd3BatchContent, repo.Path)
return pipeline.CatFileBatch(ctx, cmd3BatchContent, repo)
})
// 2. From the provided objects restrict to blobs <=1k
@@ -51,7 +51,7 @@ func SearchPointerBlobs(ctx context.Context, repo *git.Repository, pointerChan c
// 1. Run batch-check on all objects in the repository
wg.Go(func() error {
return pipeline.CatFileBatchCheckAllObjects(ctx, cmd1AllObjs, repo.Path)
return pipeline.CatFileBatchCheckAllObjects(ctx, cmd1AllObjs, repo)
})
err := wg.Wait()
close(pointerChan)

View File

@@ -12,7 +12,6 @@ import (
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/container"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/log"
"gitea.dev/modules/timeutil"
)
@@ -33,7 +32,7 @@ func SyncRepoBranches(ctx context.Context, repoID, doerID int64) (int64, error)
log.Debug("SyncRepoBranches: in Repo[%d:%s]", repo.ID, repo.FullName())
gitRepo, err := gitrepo.OpenRepository(repo)
gitRepo, err := git.OpenRepository(repo)
if err != nil {
log.Error("OpenRepository[%s]: %w", repo.FullName(), err)
return 0, err

View File

@@ -12,7 +12,6 @@ import (
repo_model "gitea.dev/models/repo"
user_model "gitea.dev/models/user"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
api "gitea.dev/modules/structs"
)
@@ -70,7 +69,7 @@ func ToAPIPayloadCommit(ctx context.Context, emailUsers map[string]*user_model.U
committerUsername = committer.Name
}
fileStatus, err := gitrepo.GetCommitFileStatus(ctx, repo, commit.Sha1)
fileStatus, err := git.GetCommitFileStatus(ctx, repo, commit.Sha1)
if err != nil {
return nil, fmt.Errorf("FileStatus [commit_sha1: %s]: %w", commit.Sha1, err)
}

View File

@@ -9,12 +9,12 @@ import (
git_model "gitea.dev/models/git"
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/git"
)
// UpdateRepoSize updates the repository size, calculating it using getDirectorySize
func UpdateRepoSize(ctx context.Context, repo *repo_model.Repository) error {
size, err := gitrepo.CalcRepositorySize(repo)
size, err := git.CalcRepositorySize(repo)
if err != nil {
return fmt.Errorf("updateSize: %w", err)
}

View File

@@ -8,7 +8,7 @@ import (
repo_model "gitea.dev/models/repo"
"gitea.dev/models/unittest"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/git"
"github.com/stretchr/testify/assert"
)
@@ -17,7 +17,7 @@ func TestGetDirectorySize(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
repo, err := repo_model.GetRepositoryByID(t.Context(), 1)
assert.NoError(t, err)
size, err := gitrepo.CalcRepositorySize(repo)
size, err := git.CalcRepositorySize(repo)
assert.NoError(t, err)
repo.Size = 8165 // real size on the disk
assert.Equal(t, repo.Size, size)

View File

@@ -14,7 +14,6 @@ import (
git_model "gitea.dev/models/git"
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/lfs"
"gitea.dev/modules/log"
"gitea.dev/modules/setting"
@@ -47,7 +46,7 @@ func SyncRepoTags(ctx context.Context, repoID int64) error {
return err
}
gitRepo, err := gitrepo.OpenRepository(repo)
gitRepo, err := git.OpenRepository(repo)
if err != nil {
return err
}

View File

@@ -7,16 +7,18 @@ import (
"context"
"fmt"
"gitea.dev/modules/log"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/setting"
)
// CreateTemporaryPath creates a temporary path
func CreateTemporaryPath(prefix string) (string, context.CancelFunc, error) {
basePath, cleanup, err := setting.AppDataTempDir("local-repo").MkdirTempRandom(prefix + ".git")
// CreateTemporaryGitRepo creates a temporary Git repository empty directory (not initialized)
func CreateTemporaryGitRepo(prefix string) (tmpPath string, tmpRepo git.RepositoryFacade, cancel context.CancelFunc, err error) {
tmpNamePrefix := prefix + ".git"
tmpPath, cancel, err = setting.AppDataTempDir("local-repo").MkdirTempRandom(tmpNamePrefix)
if err != nil {
log.Error("Unable to create temporary directory: %s-*.git (%v)", prefix, err)
return "", nil, fmt.Errorf("failed to create dir %s-*.git: %w", prefix, err)
return "", nil, nil, fmt.Errorf("failed to create temp dir with prefix %s: %w", tmpNamePrefix, err)
}
return basePath, cleanup, nil
tmpRepo = gitcmd.RepositoryUnmanaged(tmpPath)
return tmpPath, tmpRepo, cancel, nil
}

View File

@@ -15,7 +15,7 @@ import (
activities_model "gitea.dev/models/activities"
repo_model "gitea.dev/models/repo"
user_model "gitea.dev/models/user"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/git"
"gitea.dev/modules/json"
"gitea.dev/modules/log"
"gitea.dev/modules/repository"
@@ -141,7 +141,7 @@ type remoteAddress struct {
func mirrorRemoteAddress(ctx context.Context, m *repo_model.Repository, remoteName string) remoteAddress {
ret := remoteAddress{}
u, err := gitrepo.GitRemoteGetURL(ctx, m, remoteName)
u, err := git.ParseRemoteAddressURL(ctx, m, remoteName)
if err != nil {
log.Error("GetRemoteURL %v", err)
return ret

View File

@@ -8,7 +8,7 @@ import (
repo_model "gitea.dev/models/repo"
user_model "gitea.dev/models/user"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/git"
"gitea.dev/routers/api/v1/utils"
"gitea.dev/services/context"
repo_service "gitea.dev/services/repository"
@@ -99,7 +99,7 @@ func AdoptRepository(ctx *context.APIContext) {
ctx.APIErrorInternal(err)
return
}
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, repoName))
exist, err := git.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, repoName))
if err != nil {
ctx.APIErrorInternal(err)
return
@@ -161,7 +161,7 @@ func DeleteUnadoptedRepository(ctx *context.APIContext) {
ctx.APIErrorInternal(err)
return
}
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, repoName))
exist, err := git.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, repoName))
if err != nil {
ctx.APIErrorInternal(err)
return

View File

@@ -14,7 +14,6 @@ import (
repo_model "gitea.dev/models/repo"
user_model "gitea.dev/models/user"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/optional"
repo_module "gitea.dev/modules/repository"
api "gitea.dev/modules/structs"
@@ -1169,7 +1168,7 @@ func EditBranchProtection(ctx *context.APIContext) {
} else {
if !isPlainRule {
if ctx.Repo.GitRepo == nil {
ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository)
ctx.Repo.GitRepo, err = git.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository)
if err != nil {
ctx.APIErrorInternal(err)
return

View File

@@ -13,7 +13,6 @@ import (
issues_model "gitea.dev/models/issues"
user_model "gitea.dev/models/user"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/setting"
api "gitea.dev/modules/structs"
"gitea.dev/routers/api/v1/utils"
@@ -223,7 +222,7 @@ func GetAllCommits(ctx *context.APIContext) {
}
// Total commit count
commitsCountTotal, err = gitrepo.CommitsCount(ctx, ctx.Repo.Repository, gitrepo.CommitsCountOptions{
commitsCountTotal, err = git.CommitsCount(ctx, ctx.Repo.Repository, git.CommitsCountOptions{
Not: not,
Revision: []string{baseCommit.ID.String()},
Since: since,
@@ -245,8 +244,8 @@ func GetAllCommits(ctx *context.APIContext) {
sha = ctx.Repo.Repository.DefaultBranch
}
commitsCountTotal, err = gitrepo.CommitsCount(ctx, ctx.Repo.Repository,
gitrepo.CommitsCountOptions{
commitsCountTotal, err = git.CommitsCount(ctx, ctx.Repo.Repository,
git.CommitsCountOptions{
Not: not,
Revision: []string{sha},
RelPath: []string{path},
@@ -265,8 +264,8 @@ func GetAllCommits(ctx *context.APIContext) {
return
}
// verify the path actually exists in the revision history
totalWithoutDate, err := gitrepo.CommitsCount(ctx, ctx.Repo.Repository,
gitrepo.CommitsCountOptions{
totalWithoutDate, err := git.CommitsCount(ctx, ctx.Repo.Repository,
git.CommitsCountOptions{
Not: not,
Revision: []string{sha},
RelPath: []string{path},

View File

@@ -7,7 +7,7 @@ import (
"net/http"
user_model "gitea.dev/models/user"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/git"
api "gitea.dev/modules/structs"
"gitea.dev/services/context"
"gitea.dev/services/convert"
@@ -58,7 +58,7 @@ func CompareDiff(ctx *context.APIContext) {
if ctx.Repo.GitRepo == nil {
var err error
ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository)
ctx.Repo.GitRepo, err = git.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository)
if err != nil {
ctx.APIErrorInternal(err)
return

View File

@@ -23,7 +23,6 @@ import (
"gitea.dev/modules/base"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/graceful"
"gitea.dev/modules/log"
"gitea.dev/modules/optional"
@@ -1107,7 +1106,7 @@ func parseCompareInfo(ctx *context.APIContext, compareParam string) (result *git
headGitRepo = ctx.Repo.GitRepo
closer = func() {} // no need to close the head repo because it shares the base repo
} else {
headGitRepo, err = gitrepo.OpenRepository(headRepo)
headGitRepo, err = git.OpenRepository(headRepo)
if err != nil {
ctx.APIErrorInternal(err)
return nil, nil
@@ -1426,7 +1425,7 @@ func GetPullRequestCommits(ctx *context.APIContext) {
return
}
baseGitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, pr.BaseRepo)
baseGitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.BaseRepo)
if err != nil {
ctx.APIErrorInternal(err)
return

View File

@@ -13,7 +13,7 @@ import (
"gitea.dev/models/organization"
access_model "gitea.dev/models/perm/access"
user_model "gitea.dev/models/user"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/git"
api "gitea.dev/modules/structs"
"gitea.dev/modules/web"
"gitea.dev/routers/api/v1/utils"
@@ -519,7 +519,7 @@ func CreatePullReview(ctx *context.APIContext) {
// if CommitID is empty, set it as lastCommitID
if opts.CommitID == "" {
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, pr.Issue.Repo)
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.Issue.Repo)
if err != nil {
ctx.APIErrorInternal(err)
return

View File

@@ -22,7 +22,6 @@ import (
unit_model "gitea.dev/models/unit"
user_model "gitea.dev/models/user"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/label"
"gitea.dev/modules/log"
"gitea.dev/modules/optional"
@@ -705,7 +704,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
if ctx.Repo.GitRepo == nil && !repo.IsEmpty {
var err error
ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, repo)
ctx.Repo.GitRepo, err = git.RepositoryFromRequestContextOrOpen(ctx, repo)
if err != nil {
ctx.APIErrorInternal(err)
return err
@@ -714,10 +713,10 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
// Default branch only updated if changed and exist or the repository is empty
updateRepoLicense := false
if opts.DefaultBranch != nil && repo.DefaultBranch != *opts.DefaultBranch && (repo.IsEmpty || gitrepo.IsBranchExist(ctx, ctx.Repo.Repository, *opts.DefaultBranch)) {
if opts.DefaultBranch != nil && repo.DefaultBranch != *opts.DefaultBranch && (repo.IsEmpty || git.IsBranchExist(ctx, ctx.Repo.Repository, *opts.DefaultBranch)) {
repo.DefaultBranch = *opts.DefaultBranch
if !repo.IsEmpty {
if err := gitrepo.SetDefaultBranch(ctx, repo, repo.DefaultBranch); err != nil {
if err := git.SetDefaultBranch(ctx, repo, repo.DefaultBranch); err != nil {
ctx.APIErrorInternal(err)
return err
}
@@ -1067,7 +1066,7 @@ func updateMirror(ctx *context.APIContext, opts api.EditRepoOption) error {
authUpdateRequested := opts.MirrorPassword != nil || opts.MirrorToken != nil || opts.MirrorUsername != nil
if authUpdateRequested {
remoteURL, err := gitrepo.GitRemoteGetURL(ctx, repo, mirror.GetRemoteName())
remoteURL, err := git.ParseRemoteAddressURL(ctx, repo, mirror.GetRemoteName())
if err != nil {
ctx.APIErrorInternal(err)
return err

View File

@@ -11,7 +11,6 @@ import (
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/setting"
api "gitea.dev/modules/structs"
"gitea.dev/modules/util"
@@ -193,7 +192,7 @@ func getWikiPage(ctx *context.APIContext, wikiName wiki_service.WebPath) *api.Wi
}
// get commit count - wiki revisions
commitsCount, _ := gitrepo.FileCommitsCount(ctx, ctx.Repo.Repository.WikiStorageRepo(), ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
commitsCount, _ := git.FileCommitsCount(ctx, ctx.Repo.Repository.WikiStorageRepo(), ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
// Get last change information.
lastCommit, err := wikiRepo.GetCommitByPath(ctx, pageFilename)
@@ -426,7 +425,7 @@ func ListPageRevisions(ctx *context.APIContext) {
}
// get commit count - wiki revisions
commitsCount, _ := gitrepo.FileCommitsCount(ctx, ctx.Repo.Repository.WikiStorageRepo(), ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
commitsCount, _ := git.FileCommitsCount(ctx, ctx.Repo.Repository.WikiStorageRepo(), ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
page := max(ctx.FormInt("page"), 1)
@@ -468,7 +467,7 @@ func findEntryForFile(ctx *context.APIContext, wikiRepo *git.Repository, commit
// findWikiRepoCommit opens the wiki repo and returns the latest commit, writing to context on error.
// The caller is responsible for closing the returned repo again
func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit) {
wikiRepo, err := gitrepo.OpenRepository(ctx.Repo.Repository.WikiStorageRepo())
wikiRepo, err := git.OpenRepository(ctx.Repo.Repository.WikiStorageRepo())
if err != nil {
ctx.APIErrorAuto(err)
return nil, nil

View File

@@ -9,7 +9,6 @@ import (
git_model "gitea.dev/models/git"
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/reqctx"
"gitea.dev/services/context"
)
@@ -23,14 +22,14 @@ type RefCommit struct {
// ResolveRefCommit resolve ref to a commit if exist
func ResolveRefCommit(ctx reqctx.RequestContext, repo *repo_model.Repository, inputRef string, minCommitIDLen ...int) (_ *RefCommit, err error) {
gitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, repo)
gitRepo, err := git.RepositoryFromRequestContextOrOpen(ctx, repo)
if err != nil {
return nil, err
}
refCommit := RefCommit{InputRef: inputRef}
if exist, _ := git_model.IsBranchExist(ctx, repo.ID, inputRef); exist {
refCommit.RefName = git.RefNameFromBranch(inputRef)
} else if gitrepo.IsTagExist(ctx, repo, inputRef) {
} else if git.IsTagExist(ctx, repo, inputRef) {
refCommit.RefName = git.RefNameFromTag(inputRef)
} else if git.IsStringLikelyCommitID(git.ObjectFormatFromName(repo.ObjectFormatName), inputRef, minCommitIDLen...) {
refCommit.RefName = git.RefNameFromCommit(inputRef)

View File

@@ -8,7 +8,7 @@ import (
"net/http"
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/git"
"gitea.dev/modules/private"
gitea_context "gitea.dev/services/context"
repo_service "gitea.dev/services/repository"
@@ -21,7 +21,7 @@ func SetDefaultBranch(ctx *gitea_context.PrivateContext) {
branch := ctx.PathParam("branch")
ctx.Repo.Repository.DefaultBranch = branch
if err := gitrepo.SetDefaultBranch(ctx, ctx.Repo.Repository, ctx.Repo.Repository.DefaultBranch); err != nil {
if err := git.SetDefaultBranch(ctx, ctx.Repo.Repository, ctx.Repo.Repository.DefaultBranch); err != nil {
ctx.JSON(http.StatusInternalServerError, private.Response{
Err: fmt.Sprintf("Unable to set default branch on repository: %s/%s Error: %v", ownerName, repoName, err),
})

View File

@@ -17,7 +17,6 @@ import (
"gitea.dev/modules/cache"
"gitea.dev/modules/cachegroup"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/log"
"gitea.dev/modules/private"
repo_module "gitea.dev/modules/repository"
@@ -77,7 +76,7 @@ func hookPostReceiveSyncDatabaseBranches(ctx *gitea_context.PrivateContext, opts
return true
}
gitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, repo)
gitRepo, err := git.RepositoryFromRequestContextOrOpen(ctx, repo)
if err != nil {
ctx.PrivateInternalErrorf("failed to open repository: %v", err)
return false
@@ -288,7 +287,7 @@ func hookPostReceiveSyncRepoDefaultBranch(ctx *gitea_context.PrivateContext, opt
if !hasBranch {
return
}
gitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, repo)
gitRepo, err := git.RepositoryFromRequestContextOrOpen(ctx, repo)
if err != nil {
log.Error("failed to open git repo: %v", err)
return
@@ -313,7 +312,7 @@ func hookPostReceiveSyncRepoDefaultBranch(ctx *gitea_context.PrivateContext, opt
// if default branch was pushed, always keep the HEAD ref in sync
for _, refFullName := range opts.RefFullNames {
if refFullName.IsBranch() && refFullName.BranchName() == repo.DefaultBranch {
_ = gitrepo.SetDefaultBranch(ctx, repo, repo.DefaultBranch)
_ = git.SetDefaultBranch(ctx, repo, repo.DefaultBranch)
}
}
}

View File

@@ -32,7 +32,7 @@ func verifyCommits(ctx context.Context, oldCommitID, newCommitID string, repo *g
defer stdoutReaderClose()
err := command.WithEnv(env).
WithDir(repo.Path).
WithRepo(repo).
WithPipelineFunc(func(gitCtx gitcmd.Context) error {
err := readAndVerifyCommitsFromShaReader(ctx, stdoutReader, repo, env)
return gitCtx.CancelPipeline(err)
@@ -63,7 +63,7 @@ func readAndVerifyCommit(ctx context.Context, sha string, repo *git.Repository,
defer stdoutReaderClose()
return cmd.WithEnv(env).
WithDir(repo.Path).
WithRepo(repo).
WithPipelineFunc(func(gitCtx gitcmd.Context) error {
commit, err := git.CommitFromReader(commitID, stdoutReader)
if err != nil {

View File

@@ -8,7 +8,7 @@ import (
"net/http"
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/git"
"gitea.dev/modules/log"
"gitea.dev/modules/private"
gitea_context "gitea.dev/services/context"
@@ -27,7 +27,7 @@ func RepoAssignment(ctx *gitea_context.PrivateContext) {
return
}
gitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, repo)
gitRepo, err := git.RepositoryFromRequestContextOrOpen(ctx, repo)
if err != nil {
log.Error("Failed to open repository: %s/%s Error: %v", ownerName, repoName, err)
ctx.JSON(http.StatusInternalServerError, private.Response{

View File

@@ -11,7 +11,7 @@ import (
"gitea.dev/models/db"
repo_model "gitea.dev/models/repo"
user_model "gitea.dev/models/user"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/git"
"gitea.dev/modules/log"
"gitea.dev/modules/setting"
"gitea.dev/modules/templates"
@@ -134,7 +134,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
ctx.ServerError("IsRepositoryExist", err)
return
}
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, repoName))
exist, err := git.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, repoName))
if err != nil {
ctx.ServerError("IsDir", err)
return

View File

@@ -28,7 +28,6 @@ import (
"gitea.dev/modules/base"
"gitea.dev/modules/cache"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/httplib"
"gitea.dev/modules/json"
"gitea.dev/modules/log"
@@ -1476,7 +1475,7 @@ func viewScopedWorkflowFile(ctx *context_module.Context, run *actions_model.Acti
return
}
sourceGitRepo, err := gitrepo.OpenRepository(sourceRepo)
sourceGitRepo, err := git.OpenRepository(sourceRepo)
if err != nil {
ctx.ServerError("OpenRepository", err)
return

View File

@@ -16,7 +16,6 @@ import (
"gitea.dev/modules/charset"
"gitea.dev/modules/git"
"gitea.dev/modules/git/languagestats"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/highlight"
"gitea.dev/modules/log"
"gitea.dev/modules/setting"
@@ -100,7 +99,7 @@ func RefBlame(ctx *context.Context) {
}
type blameResult struct {
Parts []*gitrepo.BlamePart
Parts []*git.BlamePart
UsesIgnoreRevs bool
FaultyIgnoreRevsFile bool
}
@@ -112,7 +111,7 @@ func performBlame(ctx *context.Context, bypassBlameIgnore bool) (*blameResult, e
file := ctx.Repo.TreePath
objectFormat := ctx.Repo.GetObjectFormat()
blameReader, err := gitrepo.CreateBlameReader(ctx, objectFormat, repo, gitRepo, commit, file, bypassBlameIgnore)
blameReader, err := git.CreateBlameReader(ctx, objectFormat, repo, gitRepo, commit, file, bypassBlameIgnore)
if err != nil {
return nil, err
}
@@ -128,7 +127,7 @@ func performBlame(ctx *context.Context, bypassBlameIgnore bool) (*blameResult, e
if len(r.Parts) == 0 && r.UsesIgnoreRevs {
// try again without ignored revs
blameReader, err = gitrepo.CreateBlameReader(ctx, objectFormat, repo, gitRepo, commit, file, true)
blameReader, err = git.CreateBlameReader(ctx, objectFormat, repo, gitRepo, commit, file, true)
if err != nil {
return nil, err
}
@@ -148,12 +147,12 @@ func performBlame(ctx *context.Context, bypassBlameIgnore bool) (*blameResult, e
return r, nil
}
func fillBlameResult(br *gitrepo.BlameReader, r *blameResult) error {
func fillBlameResult(br *git.BlameReader, r *blameResult) error {
r.UsesIgnoreRevs = br.UsesIgnoreRevs()
previousHelper := make(map[string]*gitrepo.BlamePart)
previousHelper := make(map[string]*git.BlamePart)
r.Parts = make([]*gitrepo.BlamePart, 0, 5)
r.Parts = make([]*git.BlamePart, 0, 5)
for {
blamePart, err := br.NextPart()
if err != nil {
@@ -178,7 +177,7 @@ func fillBlameResult(br *gitrepo.BlameReader, r *blameResult) error {
return nil
}
func processBlameParts(ctx *context.Context, blameParts []*gitrepo.BlamePart) map[string]*gituser.UserCommit {
func processBlameParts(ctx *context.Context, blameParts []*git.BlamePart) map[string]*gituser.UserCommit {
// store commit data by SHA to look up avatar info etc
commitNames := make(map[string]*gituser.UserCommit)
// and as blameParts can reference the same commits multiple
@@ -225,7 +224,7 @@ func processBlameParts(ctx *context.Context, blameParts []*gitrepo.BlamePart) ma
return commitNames
}
func renderBlameFillFirstBlameRow(ctx *context.Context, repoLink string, part *gitrepo.BlamePart, commit *gituser.UserCommit, br *blameRow) {
func renderBlameFillFirstBlameRow(ctx *context.Context, repoLink string, part *git.BlamePart, commit *gituser.UserCommit, br *blameRow) {
br.AvatarStackData = gituser.BuildAvatarStackData(ctx, commit.GitCommit.AllParticipantIdentities(), nil)
br.PreviousSha = part.PreviousSha
br.PreviousShaURL = fmt.Sprintf("%s/blame/commit/%s/%s", repoLink, url.PathEscape(part.PreviousSha), util.PathEscapeSegments(part.PreviousPath))
@@ -234,7 +233,7 @@ func renderBlameFillFirstBlameRow(ctx *context.Context, repoLink string, part *g
br.CommitSince = templates.TimeSince(commit.GitCommit.Author.When)
}
func renderBlame(ctx *context.Context, blameParts []*gitrepo.BlamePart, commitNames map[string]*gituser.UserCommit) {
func renderBlame(ctx *context.Context, blameParts []*git.BlamePart, commitNames map[string]*gituser.UserCommit) {
language, err := languagestats.GetFileLanguage(ctx, ctx.Repo.GitRepo, ctx.Repo.CommitID, ctx.Repo.TreePath)
if err != nil {
log.Error("Unable to get file language for %-v:%s. Error: %v", ctx.Repo.Repository, ctx.Repo.TreePath, err)

Some files were not shown because too many files have changed in this diff Show More