mirror of
https://github.com/go-gitea/gitea.git
synced 2026-07-25 18:21:54 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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
24
modules/git/clone.go
Normal 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)
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package gitrepo
|
||||
package git
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -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()
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package gitrepo
|
||||
package git
|
||||
|
||||
import (
|
||||
"strings"
|
||||
@@ -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: ]")
|
||||
|
||||
@@ -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: ]")
|
||||
|
||||
@@ -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)).
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package gitrepo
|
||||
package git
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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).
|
||||
@@ -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)
|
||||
})
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build !gogit
|
||||
|
||||
package languagestats
|
||||
|
||||
import (
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
71
modules/git/localfs.go
Normal 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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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 {
|
||||
@@ -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)
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package gitrepo
|
||||
package git
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
27
modules/git/push.go
Normal 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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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") {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user