mirror of
https://github.com/go-gitea/gitea.git
synced 2026-07-22 00:51:19 +00:00
refactor: use WithRepo instead of WithDir for most git operations, clean up model migrations (#38555)
by the way, remove some unnecessary "models" imports from model migration package, fix migration test model init bug (modelmigration/migrationtest/tests.go)
This commit is contained in:
13
modelmigration/base/git.go
Normal file
13
modelmigration/base/git.go
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package base
|
||||
|
||||
import (
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
func LocalCodeGitRepo(ownerName, repoName string) gitcmd.RepositoryFacade {
|
||||
return repo_model.CodeRepoByName(ownerName, repoName)
|
||||
}
|
||||
@@ -58,7 +58,11 @@ func PrepareTestEnv(t *testing.T, skip int, syncModels ...any) (base.EngineMigra
|
||||
}
|
||||
}
|
||||
|
||||
db.ResetModels()
|
||||
if len(syncModels) > 0 {
|
||||
for _, syncModel := range syncModels {
|
||||
db.RegisterModel(syncModel)
|
||||
}
|
||||
if err := x.Sync(syncModels...); err != nil {
|
||||
t.Errorf("error during sync: %v", err)
|
||||
return x, deferFn
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -76,24 +75,23 @@ func FixMergeBase(ctx context.Context, x base.EngineMigration) error {
|
||||
log.Error("Missing base repo with id %d for PR ID %d", pr.BaseRepoID, pr.ID)
|
||||
continue
|
||||
}
|
||||
userPath := filepath.Join(setting.RepoRootPath, strings.ToLower(baseRepo.OwnerName))
|
||||
repoPath := filepath.Join(userPath, strings.ToLower(baseRepo.Name)+".git")
|
||||
|
||||
gitRepo := base.LocalCodeGitRepo(baseRepo.OwnerName, baseRepo.Name)
|
||||
gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index)
|
||||
|
||||
if !pr.HasMerged {
|
||||
var err error
|
||||
pr.MergeBase, _, err = gitcmd.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).WithDir(repoPath).RunStdString(ctx)
|
||||
pr.MergeBase, _, err = gitcmd.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).WithRepo(gitRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
var err2 error
|
||||
pr.MergeBase, _, err2 = gitcmd.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix + pr.BaseBranch).WithDir(repoPath).RunStdString(ctx)
|
||||
pr.MergeBase, _, err2 = gitcmd.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix + pr.BaseBranch).WithRepo(gitRepo).RunStdString(ctx)
|
||||
if err2 != nil {
|
||||
log.Error("Unable to get merge base for PR ID %d, Index %d in %s/%s. Error: %v & %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err, err2)
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parentsString, _, err := gitcmd.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).WithDir(repoPath).RunStdString(ctx)
|
||||
parentsString, _, err := gitcmd.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).WithRepo(gitRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
|
||||
continue
|
||||
@@ -107,7 +105,7 @@ func FixMergeBase(ctx context.Context, x base.EngineMigration) error {
|
||||
refs = append(refs, gitRefName)
|
||||
cmd := gitcmd.NewCommand("merge-base").AddDashesAndList(refs...)
|
||||
|
||||
pr.MergeBase, _, err = cmd.WithDir(repoPath).RunStdString(ctx)
|
||||
pr.MergeBase, _, err = cmd.WithRepo(gitRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
|
||||
continue
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -74,12 +73,11 @@ func RefixMergeBase(ctx context.Context, x base.EngineMigration) error {
|
||||
log.Error("Missing base repo with id %d for PR ID %d", pr.BaseRepoID, pr.ID)
|
||||
continue
|
||||
}
|
||||
userPath := filepath.Join(setting.RepoRootPath, strings.ToLower(baseRepo.OwnerName))
|
||||
repoPath := filepath.Join(userPath, strings.ToLower(baseRepo.Name)+".git")
|
||||
|
||||
gitRepo := base.LocalCodeGitRepo(baseRepo.OwnerName, baseRepo.Name)
|
||||
gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index)
|
||||
|
||||
parentsString, _, err := gitcmd.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).WithDir(repoPath).RunStdString(ctx)
|
||||
parentsString, _, err := gitcmd.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).WithRepo(gitRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
|
||||
continue
|
||||
@@ -94,7 +92,7 @@ func RefixMergeBase(ctx context.Context, x base.EngineMigration) error {
|
||||
refs = append(refs, gitRefName)
|
||||
cmd := gitcmd.NewCommand("merge-base").AddDashesAndList(refs...)
|
||||
|
||||
pr.MergeBase, _, err = cmd.WithDir(repoPath).RunStdString(ctx)
|
||||
pr.MergeBase, _, err = cmd.WithRepo(gitRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
|
||||
continue
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"time"
|
||||
|
||||
"gitea.dev/modelmigration/base"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/graceful"
|
||||
"gitea.dev/modules/log"
|
||||
@@ -83,7 +82,7 @@ func AddCommitDivergenceToPulls(x base.EngineMigration) error {
|
||||
log.Error("Missing base repo with id %d for PR ID %d", pr.BaseRepoID, pr.ID)
|
||||
continue
|
||||
}
|
||||
repoStore := repo_model.CodeRepoByName(baseRepo.OwnerName, baseRepo.Name)
|
||||
repoStore := base.LocalCodeGitRepo(baseRepo.OwnerName, baseRepo.Name)
|
||||
gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index)
|
||||
divergence, err := git.GetDivergingCommits(graceful.GetManager().HammerContext(), repoStore, pr.BaseBranch, gitRefName)
|
||||
if err != nil {
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"gitea.dev/modelmigration/base"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/log"
|
||||
)
|
||||
@@ -98,7 +97,7 @@ func FixPublisherIDforTagReleases(ctx context.Context, x base.EngineMigration) e
|
||||
return err
|
||||
}
|
||||
}
|
||||
gitRepo, err = git.OpenRepository(repo_model.CodeRepoByName(repo.OwnerName, repo.Name))
|
||||
gitRepo, err = git.OpenRepository(base.LocalCodeGitRepo(repo.OwnerName, repo.Name))
|
||||
if err != nil {
|
||||
log.Error("Error whilst opening git repo for [%d]%s/%s. Error: %v", repo.ID, repo.OwnerName, repo.Name, err)
|
||||
return err
|
||||
|
||||
@@ -5,18 +5,17 @@ package v1_17
|
||||
|
||||
import (
|
||||
"gitea.dev/modelmigration/base"
|
||||
"gitea.dev/models/pull"
|
||||
"gitea.dev/modules/timeutil"
|
||||
)
|
||||
|
||||
func AddReviewViewedFiles(x base.EngineMigration) error {
|
||||
type ReviewState struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"NOT NULL UNIQUE(pull_commit_user)"`
|
||||
PullID int64 `xorm:"NOT NULL INDEX UNIQUE(pull_commit_user) DEFAULT 0"`
|
||||
CommitSHA string `xorm:"NOT NULL VARCHAR(40) UNIQUE(pull_commit_user)"`
|
||||
UpdatedFiles map[string]pull.ViewedState `xorm:"NOT NULL LONGTEXT JSON"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"NOT NULL UNIQUE(pull_commit_user)"`
|
||||
PullID int64 `xorm:"NOT NULL INDEX UNIQUE(pull_commit_user) DEFAULT 0"`
|
||||
CommitSHA string `xorm:"NOT NULL VARCHAR(40) UNIQUE(pull_commit_user)"`
|
||||
UpdatedFiles map[string]uint8 `xorm:"NOT NULL LONGTEXT JSON"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
|
||||
}
|
||||
|
||||
return x.Sync(new(ReviewState))
|
||||
|
||||
@@ -7,15 +7,13 @@ import (
|
||||
"time"
|
||||
|
||||
"gitea.dev/modelmigration/base"
|
||||
"gitea.dev/models/repo"
|
||||
"gitea.dev/modules/timeutil"
|
||||
)
|
||||
|
||||
func AddSyncOnCommitColForPushMirror(x base.EngineMigration) error {
|
||||
type PushMirror struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"INDEX"`
|
||||
Repo *repo.Repository `xorm:"-"`
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"INDEX"`
|
||||
RemoteName string
|
||||
|
||||
SyncOnCommit bool `xorm:"NOT NULL DEFAULT true"`
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"context"
|
||||
|
||||
"gitea.dev/modelmigration/base"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/setting"
|
||||
)
|
||||
@@ -159,7 +158,7 @@ func migratePushMirrors(x base.EngineMigration) error {
|
||||
|
||||
func getRemoteAddress(ownerName, repoName, remoteName string) (string, error) {
|
||||
ctx := context.Background()
|
||||
repo := repo_model.CodeRepoByName(ownerName, repoName)
|
||||
repo := base.LocalCodeGitRepo(ownerName, repoName)
|
||||
if exist, _ := git.IsRepositoryExist(ctx, repo); !exist {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -5,12 +5,11 @@ package v1_22
|
||||
|
||||
import (
|
||||
"gitea.dev/modelmigration/base"
|
||||
"gitea.dev/models/perm"
|
||||
)
|
||||
|
||||
func AddRepoUnitEveryoneAccessMode(x base.EngineMigration) error {
|
||||
type RepoUnit struct { //revive:disable-line:exported
|
||||
EveryoneAccessMode perm.AccessMode `xorm:"NOT NULL DEFAULT 0"`
|
||||
EveryoneAccessMode int `xorm:"NOT NULL DEFAULT 0"`
|
||||
}
|
||||
return x.Sync(&RepoUnit{})
|
||||
}
|
||||
|
||||
@@ -5,14 +5,13 @@ package v1_24
|
||||
|
||||
import (
|
||||
"gitea.dev/modelmigration/base"
|
||||
"gitea.dev/models/perm"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func AddRepoUnitAnonymousAccessMode(x base.EngineMigration) error {
|
||||
type RepoUnit struct { //revive:disable-line:exported
|
||||
AnonymousAccessMode perm.AccessMode `xorm:"NOT NULL DEFAULT 0"`
|
||||
AnonymousAccessMode int `xorm:"NOT NULL DEFAULT 0"`
|
||||
}
|
||||
_, err := x.SyncWithOptions(xorm.SyncOptions{
|
||||
IgnoreConstrains: true,
|
||||
|
||||
@@ -11,10 +11,6 @@ import (
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/test"
|
||||
|
||||
_ "gitea.dev/models/actions"
|
||||
_ "gitea.dev/models/git"
|
||||
_ "gitea.dev/models/repo"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
"gitea.dev/modelmigration/base"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/modules/git"
|
||||
)
|
||||
|
||||
@@ -86,7 +85,7 @@ func FixReleaseSha1OnReleaseTable(ctx context.Context, x base.EngineMigration) e
|
||||
userCache[repo.OwnerID] = user
|
||||
}
|
||||
|
||||
gitRepo, err = git.OpenRepository(repo_model.CodeRepoByName(user.Name, repo.Name))
|
||||
gitRepo, err = git.OpenRepository(base.LocalCodeGitRepo(user.Name, repo.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -116,6 +116,10 @@ func RegisterModel(bean any, initFunc ...func() error) {
|
||||
}
|
||||
}
|
||||
|
||||
func ResetModels() {
|
||||
registeredModels, registeredInitFuncs = nil, nil
|
||||
}
|
||||
|
||||
// SyncAllTables sync the schemas of all tables, is required by unit test code
|
||||
func SyncAllTables() error {
|
||||
_, err := xormEngine.StoreEngine("InnoDB").SyncWithOptions(xorm.SyncOptions{
|
||||
|
||||
15
models/init.go
Normal file
15
models/init.go
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gitea.dev/models/unit"
|
||||
)
|
||||
|
||||
// Init initialize model
|
||||
func Init(ctx context.Context) error {
|
||||
return unit.LoadUnitConfig()
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package models
|
||||
package repostats
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -2,7 +2,7 @@
|
||||
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package models
|
||||
package repostats
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"gitea.dev/models/db"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unit"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/log"
|
||||
|
||||
@@ -21,11 +20,6 @@ import (
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
// Init initialize model
|
||||
func Init(ctx context.Context) error {
|
||||
return unit.LoadUnitConfig()
|
||||
}
|
||||
|
||||
type repoChecker struct {
|
||||
querySQL func(ctx context.Context) ([]int64, error)
|
||||
correctSQL func(ctx context.Context, id int64) error
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package models
|
||||
package repostats
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -42,30 +42,34 @@ func CreateBundle(ctx context.Context, repo RepositoryFacade, commit string, out
|
||||
// git update-ref refs/bundle/temp-{timestamp} {commit}
|
||||
// git bundle create - refs/bundle/temp-{timestamp}
|
||||
// git update-ref -d refs/bundle/temp-{timestamp}
|
||||
tmp, cleanup, err := setting.AppDataTempDir("git-repo-content").MkdirTempRandom("gitea-bundle")
|
||||
tmpDir, cleanup, err := setting.AppDataTempDir("git-repo-content").MkdirTempRandom("gitea-bundle")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
env := append(os.Environ(), "GIT_OBJECT_DIRECTORY="+filepath.Join(gitcmd.RepoLocalPath(repo), "objects"))
|
||||
_, _, err = gitcmd.NewCommand("init", "--bare").WithDir(tmp).WithEnv(env).RunStdString(ctx)
|
||||
gitTmpCmd := func() *gitcmd.Command {
|
||||
return gitcmd.NewCommand().WithDir(tmpDir).WithEnv(env)
|
||||
}
|
||||
|
||||
_, _, err = gitTmpCmd().AddArguments("init", "--bare").RunStdString(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = gitcmd.NewCommand("reset", "--soft").AddDynamicArguments(commit).WithDir(tmp).WithEnv(env).RunStdString(ctx)
|
||||
_, _, err = gitTmpCmd().AddArguments("reset", "--soft").AddDynamicArguments(commit).RunStdString(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = gitcmd.NewCommand("branch", "-m", "bundle").WithDir(tmp).WithEnv(env).RunStdString(ctx)
|
||||
_, _, err = gitTmpCmd().AddArguments("branch", "-m", "bundle").RunStdString(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tmpFile := filepath.Join(tmp, "bundle")
|
||||
_, _, err = gitcmd.NewCommand("bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").WithDir(tmp).WithEnv(env).RunStdString(ctx)
|
||||
tmpFile := filepath.Join(tmpDir, "bundle")
|
||||
_, _, err = gitTmpCmd().AddArguments("bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").RunStdString(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@ package git
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
"gitea.dev/modules/util"
|
||||
)
|
||||
|
||||
type BufferedReader interface {
|
||||
@@ -49,8 +51,11 @@ type CatFileBatchCloser interface {
|
||||
// The CatFileBatch and the readers create by it should only be used in the same goroutine.
|
||||
func NewBatch(ctx context.Context, repo RepositoryFacade) (CatFileBatchCloser, error) {
|
||||
repoPath := gitcmd.RepoLocalPath(repo)
|
||||
if DefaultFeatures().SupportCatFileBatchCommand {
|
||||
return newCatFileBatchCommand(ctx, repoPath)
|
||||
if _, err := os.Stat(repoPath); err != nil {
|
||||
return nil, util.NewNotExistErrorf("repo %q doesn't exist", repo.LogString())
|
||||
}
|
||||
return newCatFileBatchLegacy(ctx, repoPath)
|
||||
if DefaultFeatures().SupportCatFileBatchCommand {
|
||||
return newCatFileBatchCommand(ctx, repo), nil
|
||||
}
|
||||
return newCatFileBatchLegacy(ctx, repo), nil
|
||||
}
|
||||
|
||||
@@ -5,38 +5,32 @@ package git
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/util"
|
||||
)
|
||||
|
||||
// catFileBatchCommand implements the CatFileBatch interface using the "cat-file --batch-command" command
|
||||
// for git version >= 2.36
|
||||
// ref: https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch-command
|
||||
type catFileBatchCommand struct {
|
||||
ctx context.Context
|
||||
repoPath string
|
||||
batch *catFileBatchCommunicator
|
||||
ctx context.Context
|
||||
repo RepositoryFacade
|
||||
batch *catFileBatchCommunicator
|
||||
}
|
||||
|
||||
var _ CatFileBatch = (*catFileBatchCommand)(nil)
|
||||
|
||||
func newCatFileBatchCommand(ctx context.Context, repoPath string) (*catFileBatchCommand, error) {
|
||||
if _, err := os.Stat(repoPath); err != nil {
|
||||
return nil, util.NewNotExistErrorf("repo %q doesn't exist", filepath.Base(repoPath))
|
||||
}
|
||||
return &catFileBatchCommand{ctx: ctx, repoPath: repoPath}, nil
|
||||
func newCatFileBatchCommand(ctx context.Context, repo RepositoryFacade) *catFileBatchCommand {
|
||||
return &catFileBatchCommand{ctx: ctx, repo: repo}
|
||||
}
|
||||
|
||||
func (b *catFileBatchCommand) getBatch() *catFileBatchCommunicator {
|
||||
if b.batch != nil {
|
||||
return b.batch
|
||||
}
|
||||
b.batch = newCatFileBatch(b.ctx, b.repoPath, gitcmd.NewCommand("cat-file", "--batch-command"))
|
||||
b.batch = newCatFileBatch(b.ctx, b.repo, gitcmd.NewCommand("cat-file", "--batch-command"))
|
||||
return b.batch
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,10 @@ package git
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/util"
|
||||
)
|
||||
|
||||
// catFileBatchLegacy implements the CatFileBatch interface using the "cat-file --batch" command and "cat-file --batch-check" command
|
||||
@@ -21,25 +18,22 @@ import (
|
||||
// ref: https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch
|
||||
type catFileBatchLegacy struct {
|
||||
ctx context.Context
|
||||
repoPath string
|
||||
repo RepositoryFacade
|
||||
batchContent *catFileBatchCommunicator
|
||||
batchCheck *catFileBatchCommunicator
|
||||
}
|
||||
|
||||
var _ CatFileBatchCloser = (*catFileBatchLegacy)(nil)
|
||||
|
||||
func newCatFileBatchLegacy(ctx context.Context, repoPath string) (*catFileBatchLegacy, error) {
|
||||
if _, err := os.Stat(repoPath); err != nil {
|
||||
return nil, util.NewNotExistErrorf("repo %q doesn't exist", filepath.Base(repoPath))
|
||||
}
|
||||
return &catFileBatchLegacy{ctx: ctx, repoPath: repoPath}, nil
|
||||
func newCatFileBatchLegacy(ctx context.Context, repo RepositoryFacade) *catFileBatchLegacy {
|
||||
return &catFileBatchLegacy{ctx: ctx, repo: repo}
|
||||
}
|
||||
|
||||
func (b *catFileBatchLegacy) getBatchContent() *catFileBatchCommunicator {
|
||||
if b.batchContent != nil {
|
||||
return b.batchContent
|
||||
}
|
||||
b.batchContent = newCatFileBatch(b.ctx, b.repoPath, gitcmd.NewCommand("cat-file", "--batch"))
|
||||
b.batchContent = newCatFileBatch(b.ctx, b.repo, gitcmd.NewCommand("cat-file", "--batch"))
|
||||
return b.batchContent
|
||||
}
|
||||
|
||||
@@ -47,7 +41,7 @@ func (b *catFileBatchLegacy) getBatchCheck() *catFileBatchCommunicator {
|
||||
if b.batchCheck != nil {
|
||||
return b.batchCheck
|
||||
}
|
||||
b.batchCheck = newCatFileBatch(b.ctx, b.repoPath, gitcmd.NewCommand("cat-file", "--batch-check"))
|
||||
b.batchCheck = newCatFileBatch(b.ctx, b.repo, gitcmd.NewCommand("cat-file", "--batch-check"))
|
||||
return b.batchCheck
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ func (b *catFileBatchCommunicator) Close(err ...error) {
|
||||
}
|
||||
|
||||
// newCatFileBatch opens git cat-file --batch/--batch-check/--batch-command command and prepares the stdin/stdout pipes for communication.
|
||||
func newCatFileBatch(ctx context.Context, repoPath string, cmdCatFile *gitcmd.Command) *catFileBatchCommunicator {
|
||||
func newCatFileBatch(ctx context.Context, repo RepositoryFacade, cmdCatFile *gitcmd.Command) *catFileBatchCommunicator {
|
||||
ctx, ctxCancel := context.WithCancelCause(ctx)
|
||||
stdinWriter, stdoutReader, stdPipeClose := cmdCatFile.MakeStdinStdoutPipe()
|
||||
ret := &catFileBatchCommunicator{
|
||||
@@ -47,7 +47,7 @@ func newCatFileBatch(ctx context.Context, repoPath string, cmdCatFile *gitcmd.Co
|
||||
stdPipeClose()
|
||||
}))
|
||||
|
||||
err := cmdCatFile.WithDir(repoPath).StartWithStderr(ctx)
|
||||
err := cmdCatFile.WithRepo(repo).StartWithStderr(ctx)
|
||||
if err != nil {
|
||||
log.Error("Unable to start git command %v: %v", cmdCatFile.LogString(), err)
|
||||
// ideally here it should return the error, but it would require refactoring all callers
|
||||
@@ -59,7 +59,7 @@ func newCatFileBatch(ctx context.Context, repoPath string, cmdCatFile *gitcmd.Co
|
||||
go func() {
|
||||
err := cmdCatFile.WaitWithStderr()
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
log.Error("cat-file --batch command failed in repo %s, error: %v", repoPath, err)
|
||||
log.Error("cat-file --batch command failed in repo %s, error: %v", repo.LogString(), err)
|
||||
}
|
||||
ret.Close(err)
|
||||
}()
|
||||
|
||||
@@ -35,7 +35,14 @@ type Command struct {
|
||||
args []string
|
||||
preErrors []error
|
||||
configArgs []string
|
||||
opts runOpts
|
||||
|
||||
// Dir is the working dir for the git command, however:
|
||||
// FIXME: this could be incorrect in many cases, for example:
|
||||
// * /some/path/.git
|
||||
// * /some/path/.git/gitea-data/data/repositories/user/repo.git
|
||||
// If "user/repo.git" is invalid/broken, then running git command in it will use "/some/path/.git", and produce unexpected results
|
||||
// The correct approach is to use `--git-dir" global argument or "GIT_DIR=..." environment variable.
|
||||
gitDir string
|
||||
|
||||
cmd *exec.Cmd
|
||||
|
||||
@@ -44,10 +51,15 @@ type Command struct {
|
||||
cmdFinished process.FinishedFunc
|
||||
cmdStartTime time.Time
|
||||
|
||||
pipelineFunc func(Context) error
|
||||
|
||||
parentPipeFiles []*os.File
|
||||
parentPipeReaders []*os.File
|
||||
childrenPipeFiles []*os.File
|
||||
|
||||
cmdEnv []string
|
||||
cmdTimeout time.Duration
|
||||
|
||||
// only os.Pipe and in-memory buffers can work with Stdin safely, see https://github.com/golang/go/issues/77227 if the command would exit unexpectedly
|
||||
cmdStdin io.Reader
|
||||
cmdStdout io.Writer
|
||||
@@ -204,23 +216,6 @@ func ToTrustedCmdArgs(args []string) TrustedCmdArgs {
|
||||
return ret
|
||||
}
|
||||
|
||||
type runOpts struct {
|
||||
// TODO: this struct should be removed, the fields can be just merged into the command
|
||||
|
||||
Env []string
|
||||
Timeout time.Duration
|
||||
|
||||
// Dir is the working dir for the git command, however:
|
||||
// FIXME: this could be incorrect in many cases, for example:
|
||||
// * /some/path/.git
|
||||
// * /some/path/.git/gitea-data/data/repositories/user/repo.git
|
||||
// If "user/repo.git" is invalid/broken, then running git command in it will use "/some/path/.git", and produce unexpected results
|
||||
// The correct approach is to use `--git-dir" global argument or "GIT_DIR=..." environment variable.
|
||||
Dir string
|
||||
|
||||
PipelineFunc func(Context) error
|
||||
}
|
||||
|
||||
func commonBaseEnvs() []string {
|
||||
envs := []string{
|
||||
// Make Gitea use internal git config only, to prevent conflicts with user's git config
|
||||
@@ -262,17 +257,17 @@ func CommonCmdServEnvs() []string {
|
||||
var ErrBrokenCommand = errors.New("git command is broken")
|
||||
|
||||
func (c *Command) WithDir(dir string) *Command {
|
||||
c.opts.Dir = dir
|
||||
c.gitDir = dir
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Command) WithEnv(env []string) *Command {
|
||||
c.opts.Env = env
|
||||
c.cmdEnv = env
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Command) WithTimeout(timeout time.Duration) *Command {
|
||||
c.opts.Timeout = timeout
|
||||
c.cmdTimeout = timeout
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -361,7 +356,7 @@ func (c *Command) WithStdoutCopy(w io.Writer) *Command {
|
||||
// The returned error of Run / Wait can be joined errors from the pipeline function, context cause, and command exit error.
|
||||
// Caller can get the pipeline function's error (if any) by UnwrapPipelineError.
|
||||
func (c *Command) WithPipelineFunc(f func(ctx Context) error) *Command {
|
||||
c.opts.PipelineFunc = f
|
||||
c.pipelineFunc = f
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -418,7 +413,7 @@ func (c *Command) Start(ctx context.Context) (retErr error) {
|
||||
c.WithParentCallerInfo()
|
||||
}
|
||||
// these logs are for debugging purposes only, so no guarantee of correctness or stability
|
||||
desc := fmt.Sprintf("git.Run(by:%s, repo:%s): %s", c.callerInfo, logArgSanitize(c.opts.Dir), cmdLogString)
|
||||
desc := fmt.Sprintf("git.Run(by:%s, repo:%s): %s", c.callerInfo, logArgSanitize(c.gitDir), cmdLogString)
|
||||
log.Debug("git.Command: %s", desc)
|
||||
|
||||
_, span := gtprof.GetTracer().Start(ctx, gtprof.TraceSpanGitRun)
|
||||
@@ -426,24 +421,24 @@ func (c *Command) Start(ctx context.Context) (retErr error) {
|
||||
span.SetAttributeString(gtprof.TraceAttrFuncCaller, c.callerInfo)
|
||||
span.SetAttributeString(gtprof.TraceAttrGitCommand, cmdLogString)
|
||||
|
||||
if c.opts.Timeout <= 0 {
|
||||
if c.cmdTimeout <= 0 {
|
||||
c.cmdCtx, c.cmdCancel, c.cmdFinished = process.GetManager().AddContext(ctx, desc)
|
||||
} else {
|
||||
c.cmdCtx, c.cmdCancel, c.cmdFinished = process.GetManager().AddContextTimeout(ctx, c.opts.Timeout, desc)
|
||||
c.cmdCtx, c.cmdCancel, c.cmdFinished = process.GetManager().AddContextTimeout(ctx, c.cmdTimeout, desc)
|
||||
}
|
||||
|
||||
c.cmdStartTime = time.Now()
|
||||
|
||||
c.cmd = exec.CommandContext(c.cmdCtx, c.prog, append(c.configArgs, c.args...)...)
|
||||
if c.opts.Env == nil {
|
||||
if c.cmdEnv == nil {
|
||||
c.cmd.Env = os.Environ()
|
||||
} else {
|
||||
c.cmd.Env = c.opts.Env
|
||||
c.cmd.Env = c.cmdEnv
|
||||
}
|
||||
|
||||
process.SetSysProcAttribute(c.cmd)
|
||||
c.cmd.Env = append(c.cmd.Env, CommonGitCmdEnvs()...)
|
||||
c.cmd.Dir = c.opts.Dir
|
||||
c.cmd.Dir = c.gitDir
|
||||
c.cmd.Stdout = c.cmdStdout
|
||||
c.cmd.Stdin = c.cmdStdin
|
||||
c.cmd.Stderr = c.cmdStderr
|
||||
@@ -481,8 +476,8 @@ func (c *Command) Wait() error {
|
||||
c.cmdFinished()
|
||||
}()
|
||||
|
||||
if c.opts.PipelineFunc != nil {
|
||||
errPipeline := c.opts.PipelineFunc(&cmdContext{Context: c.cmdCtx, cmd: c})
|
||||
if c.pipelineFunc != nil {
|
||||
errPipeline := c.pipelineFunc(&cmdContext{Context: c.cmdCtx, cmd: c})
|
||||
|
||||
if context.Cause(c.cmdCtx) == nil {
|
||||
// if the context is not canceled explicitly, we need to discard the unread data,
|
||||
|
||||
@@ -25,7 +25,7 @@ type RepositoryFacade interface {
|
||||
}
|
||||
|
||||
func (c *Command) WithRepo(repo RepositoryFacade) *Command {
|
||||
c.opts.Dir = RepoLocalPath(repo)
|
||||
c.gitDir = RepoLocalPath(repo)
|
||||
return c
|
||||
}
|
||||
|
||||
|
||||
@@ -15,19 +15,19 @@ import (
|
||||
)
|
||||
|
||||
// CatFileBatchCheck runs cat-file with --batch-check
|
||||
func CatFileBatchCheck(ctx context.Context, cmd *gitcmd.Command, tmpBasePath string) error {
|
||||
func CatFileBatchCheck(ctx context.Context, cmd *gitcmd.Command, repo git.RepositoryFacade) error {
|
||||
cmd.AddArguments("cat-file", "--batch-check")
|
||||
return cmd.WithDir(tmpBasePath).RunWithStderr(ctx)
|
||||
return cmd.WithRepo(repo).RunWithStderr(ctx)
|
||||
}
|
||||
|
||||
// CatFileBatchCheckAllObjects runs cat-file with --batch-check --batch-all
|
||||
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)
|
||||
func CatFileBatchCheckAllObjects(ctx context.Context, cmd *gitcmd.Command, repo git.RepositoryFacade) error {
|
||||
return cmd.AddArguments("cat-file", "--batch-check", "--batch-all-objects").WithRepo(repo).RunWithStderr(ctx)
|
||||
}
|
||||
|
||||
// CatFileBatch runs cat-file --batch
|
||||
func CatFileBatch(ctx context.Context, cmd *gitcmd.Command, gitRepo git.RepositoryFacade) error {
|
||||
return cmd.AddArguments("cat-file", "--batch").WithRepo(gitRepo).RunWithStderr(ctx)
|
||||
func CatFileBatch(ctx context.Context, cmd *gitcmd.Command, repo git.RepositoryFacade) error {
|
||||
return cmd.AddArguments("cat-file", "--batch").WithRepo(repo).RunWithStderr(ctx)
|
||||
}
|
||||
|
||||
// BlobsLessThan1024FromCatFileBatchCheck reads a pipeline from cat-file --batch-check and returns the blobs <1024 in size
|
||||
|
||||
@@ -9,16 +9,17 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// RevListObjects run rev-list --objects from headSHA to baseSHA
|
||||
func RevListObjects(ctx context.Context, cmd *gitcmd.Command, tmpBasePath, headSHA, baseSHA string) error {
|
||||
func RevListObjects(ctx context.Context, cmd *gitcmd.Command, repo git.RepositoryFacade, headSHA, baseSHA string) error {
|
||||
cmd.AddArguments("rev-list", "--objects").AddDynamicArguments(headSHA)
|
||||
if baseSHA != "" {
|
||||
cmd = cmd.AddArguments("--not").AddDynamicArguments(baseSHA)
|
||||
}
|
||||
return cmd.WithDir(tmpBasePath).RunWithStderr(ctx)
|
||||
return cmd.WithRepo(repo).RunWithStderr(ctx)
|
||||
}
|
||||
|
||||
// BlobsFromRevListObjects reads a RevListAllObjects and only selects blobs
|
||||
|
||||
@@ -105,8 +105,8 @@ func IsRepoURLAccessible(ctx context.Context, url string) bool {
|
||||
}
|
||||
|
||||
// InitRepositoryLocal initializes a new Git repository.
|
||||
func InitRepositoryLocal(ctx context.Context, repoPath string, bare bool, objectFormatName string) error {
|
||||
err := os.MkdirAll(repoPath, os.ModePerm)
|
||||
func InitRepositoryLocal(ctx context.Context, localRepoPath string, bare bool, objectFormatName string) error {
|
||||
err := os.MkdirAll(localRepoPath, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -123,7 +123,7 @@ func InitRepositoryLocal(ctx context.Context, repoPath string, bare bool, object
|
||||
if bare {
|
||||
cmd.AddArguments("--bare")
|
||||
}
|
||||
_, _, err = cmd.WithDir(repoPath).RunStdString(ctx)
|
||||
_, _, err = cmd.WithDir(localRepoPath).RunStdString(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ type PushOptions struct {
|
||||
}
|
||||
|
||||
// Push pushs local commits to given remote branch.
|
||||
func Push(ctx context.Context, repoPath string, opts PushOptions) error {
|
||||
func Push(ctx context.Context, localRepoPath string, opts PushOptions) error {
|
||||
cmd := gitcmd.NewCommand("push")
|
||||
if opts.ForceWithLease != "" {
|
||||
cmd.AddOptionFormat("--force-with-lease=%s", opts.ForceWithLease)
|
||||
@@ -256,7 +256,7 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error {
|
||||
}
|
||||
cmd.AddDashesAndList(remoteBranchArgs...)
|
||||
|
||||
stdout, stderr, err := cmd.WithEnv(opts.Env).WithTimeout(opts.Timeout).WithDir(repoPath).RunStdString(ctx)
|
||||
stdout, stderr, err := cmd.WithEnv(opts.Env).WithTimeout(opts.Timeout).WithDir(localRepoPath).RunStdString(ctx)
|
||||
if err != nil {
|
||||
if strings.Contains(stderr, "non-fast-forward") {
|
||||
return &ErrPushOutOfDate{StdOut: stdout, StdErr: stderr, Err: err}
|
||||
|
||||
@@ -19,11 +19,11 @@ type TemplateSubmoduleCommit struct {
|
||||
|
||||
// GetTemplateSubmoduleCommits returns a list of submodules paths and their commits from a repository
|
||||
// This function is only for generating new repos based on existing template, the template couldn't be too large.
|
||||
func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submoduleCommits []TemplateSubmoduleCommit, _ error) {
|
||||
func GetTemplateSubmoduleCommits(ctx context.Context, repo gitcmd.RepositoryFacade) (submoduleCommits []TemplateSubmoduleCommit, _ error) {
|
||||
cmd := gitcmd.NewCommand("ls-tree", "-r", "--", "HEAD")
|
||||
stdoutReader, stdoutReaderClose := cmd.MakeStdoutPipe()
|
||||
defer stdoutReaderClose()
|
||||
err := cmd.WithDir(repoPath).
|
||||
err := cmd.WithRepo(repo).
|
||||
WithPipelineFunc(func(ctx gitcmd.Context) error {
|
||||
scanner := bufio.NewScanner(stdoutReader)
|
||||
for scanner.Scan() {
|
||||
@@ -46,11 +46,11 @@ func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submodul
|
||||
|
||||
// AddTemplateSubmoduleIndexes Adds the given submodules to the git index.
|
||||
// It is only for generating new repos based on existing template, requires the .gitmodules file to be already present in the work dir.
|
||||
func AddTemplateSubmoduleIndexes(ctx context.Context, repoPath string, submodules []TemplateSubmoduleCommit) error {
|
||||
func AddTemplateSubmoduleIndexes(ctx context.Context, tmpRepoPath string, submodules []TemplateSubmoduleCommit) error {
|
||||
for _, submodule := range submodules {
|
||||
cmd := gitcmd.NewCommand("update-index", "--add", "--cacheinfo", "160000").AddDynamicArguments(submodule.Commit, submodule.Path)
|
||||
if stdout, _, err := cmd.WithDir(repoPath).RunStdString(ctx); err != nil {
|
||||
log.Error("Unable to add %s as submodule to repo %s: stdout %s\nError: %v", submodule.Path, repoPath, stdout, err)
|
||||
if stdout, _, err := cmd.WithDir(tmpRepoPath).RunStdString(ctx); err != nil {
|
||||
log.Error("Unable to add %s as submodule to repo %s: stdout %s\nError: %v", submodule.Path, tmpRepoPath, stdout, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func TestGetTemplateSubmoduleCommits(t *testing.T) {
|
||||
testRepoPath := filepath.Join(testReposDir, "repo4_submodules")
|
||||
testRepoPath := mockRepository("repo4_submodules")
|
||||
submodules, err := GetTemplateSubmoduleCommits(t.Context(), testRepoPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -41,7 +41,7 @@ func TestAddTemplateSubmoduleIndexes(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
_, _, err = gitcmd.NewCommand("-c", "user.name=a", "-c", "user.email=b", "commit", "-m=test").WithDir(tmpDir).RunStdString(ctx)
|
||||
require.NoError(t, err)
|
||||
submodules, err := GetTemplateSubmoduleCommits(t.Context(), tmpDir)
|
||||
submodules, err := GetTemplateSubmoduleCommits(t.Context(), mockRepository(tmpDir))
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, submodules, 1)
|
||||
assert.Equal(t, "new-dir", submodules[0].Path)
|
||||
|
||||
@@ -265,20 +265,20 @@ var (
|
||||
|
||||
func dummyInfoRefs(ctx *context.Context) {
|
||||
infoRefsOnce.Do(func() {
|
||||
tmpDir, cleanup, err := setting.AppDataTempDir("git-repo-content").MkdirTempRandom("gitea-info-refs-cache")
|
||||
tmpEmptyRepoDir, cleanup, err := setting.AppDataTempDir("git-repo-content").MkdirTempRandom("gitea-info-refs-cache")
|
||||
if err != nil {
|
||||
log.Error("Failed to create temp dir for git-receive-pack cache: %v", err)
|
||||
return
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
if err := git.InitRepositoryLocal(ctx, tmpDir, true, git.Sha1ObjectFormat.Name()); err != nil {
|
||||
if err := git.InitRepositoryLocal(ctx, tmpEmptyRepoDir, true, git.Sha1ObjectFormat.Name()); err != nil {
|
||||
log.Error("Failed to init bare repo for git-receive-pack cache: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
refs, _, err := gitcmd.NewCommand("receive-pack", "--stateless-rpc", "--advertise-refs", ".").
|
||||
WithDir(tmpDir).
|
||||
WithDir(tmpEmptyRepoDir).
|
||||
RunStdBytes(ctx)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("%v - %s", err, string(refs)))
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"gitea.dev/models"
|
||||
git_model "gitea.dev/models/git"
|
||||
"gitea.dev/models/repostats"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/models/webhook"
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
@@ -69,7 +69,7 @@ func registerCheckRepoStats() {
|
||||
RunAtStart: true,
|
||||
Schedule: "@midnight",
|
||||
}, func(ctx context.Context, _ *user_model.User, _ Config) error {
|
||||
return models.CheckRepoStats(ctx)
|
||||
return repostats.CheckRepoStats(ctx)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"gitea.dev/models"
|
||||
"gitea.dev/models/db"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/repostats"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/log"
|
||||
@@ -57,7 +57,7 @@ func checkHooks(ctx context.Context, logger log.Logger, autofix bool) error {
|
||||
|
||||
func checkUserStarNum(ctx context.Context, logger log.Logger, autofix bool) error {
|
||||
if autofix {
|
||||
if err := models.DoctorUserStarNum(ctx); err != nil {
|
||||
if err := repostats.DoctorUserStarNum(ctx); err != nil {
|
||||
logger.Critical("Unable update User Stars numbers")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.dev/models"
|
||||
"gitea.dev/models/db"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/repostats"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
@@ -965,7 +965,7 @@ func (g *GiteaLocalUploader) Finish(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := models.UpdateRepoStats(ctx, g.repo.ID); err != nil {
|
||||
if err := repostats.UpdateRepoStats(ctx, g.repo.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ func LFSPush(ctx context.Context, tmpBasePath string, tmpRepo git.RepositoryFaca
|
||||
|
||||
// 3. Run batch-check on the objects retrieved from rev-list
|
||||
wg.Go(func() error {
|
||||
return pipeline.CatFileBatchCheck(ctx, cmd3BathCheck, tmpBasePath)
|
||||
return pipeline.CatFileBatchCheck(ctx, cmd3BathCheck, tmpRepo)
|
||||
})
|
||||
|
||||
// 2. Check each object retrieved rejecting those without names as they will be commits or trees
|
||||
@@ -74,7 +74,7 @@ func LFSPush(ctx context.Context, tmpBasePath string, tmpRepo git.RepositoryFaca
|
||||
|
||||
// 1. Run rev-list objects from mergeHead to mergeBase
|
||||
wg.Go(func() error {
|
||||
return pipeline.RevListObjects(ctx, cmd1RevList, tmpBasePath, mergeHeadSHA, mergeBaseSHA)
|
||||
return pipeline.RevListObjects(ctx, cmd1RevList, tmpRepo, mergeHeadSHA, mergeBaseSHA)
|
||||
})
|
||||
|
||||
return wg.Wait()
|
||||
|
||||
@@ -38,7 +38,7 @@ type mergeContext struct {
|
||||
func (ctx *mergeContext) PrepareGitCmd(cmd *gitcmd.Command) *gitcmd.Command {
|
||||
ctx.outbuf.Reset()
|
||||
return cmd.WithEnv(ctx.env).
|
||||
WithDir(ctx.tmpBasePath).
|
||||
WithRepo(ctx.tmpRepo).
|
||||
WithParentCallerInfo().
|
||||
WithStdoutBuffer(ctx.outbuf)
|
||||
}
|
||||
@@ -77,7 +77,7 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque
|
||||
trackingCommitID, _, err := gitcmd.NewCommand("show-ref", "--hash").
|
||||
AddDynamicArguments(git.BranchPrefix + tmpRepoTrackingBranch).
|
||||
WithEnv(mergeCtx.env).
|
||||
WithDir(mergeCtx.tmpBasePath).
|
||||
WithRepo(mergeCtx.tmpRepo).
|
||||
RunStdString(ctx)
|
||||
if err != nil {
|
||||
defer cancel()
|
||||
@@ -154,7 +154,7 @@ func prepareTemporaryRepoForMerge(ctx *mergeContext) error {
|
||||
}
|
||||
defer sparseCheckoutListFile.Close() // we will close it earlier but we need to ensure it is closed if there is an error
|
||||
|
||||
if err := getDiffTree(ctx, ctx.tmpBasePath, tmpRepoBaseBranch, tmpRepoTrackingBranch, sparseCheckoutListFile); err != nil {
|
||||
if err := getDiffTree(ctx, ctx.tmpRepo, tmpRepoBaseBranch, tmpRepoTrackingBranch, sparseCheckoutListFile); err != nil {
|
||||
log.Error("%-v getDiffTree(%s, %s, %s): %v", ctx.pr, ctx.tmpBasePath, tmpRepoBaseBranch, tmpRepoTrackingBranch, err)
|
||||
return fmt.Errorf("getDiffTree: %w", err)
|
||||
}
|
||||
@@ -206,13 +206,13 @@ func prepareTemporaryRepoForMerge(ctx *mergeContext) error {
|
||||
}
|
||||
|
||||
// getDiffTree returns a string containing all the files that were changed between headBranch and baseBranch
|
||||
// the filenames are escaped so as to fit the format required for .git/info/sparse-checkout
|
||||
func getDiffTree(ctx context.Context, repoPath, baseBranch, headBranch string, out io.Writer) error {
|
||||
// the filenames are escaped to fit the format required for .git/info/sparse-checkout
|
||||
func getDiffTree(ctx context.Context, repo git.RepositoryFacade, baseBranch, headBranch string, out io.Writer) error {
|
||||
cmd := gitcmd.NewCommand("diff-tree", "--no-commit-id", "--name-only", "-r", "-r", "-z", "--root")
|
||||
diffOutReader, diffOutReaderClose := cmd.MakeStdoutPipe()
|
||||
defer diffOutReaderClose()
|
||||
err := cmd.AddDynamicArguments(baseBranch, headBranch).
|
||||
WithDir(repoPath).
|
||||
WithRepo(repo).
|
||||
WithPipelineFunc(func(ctx gitcmd.Context) error {
|
||||
// Now scan the output from the command
|
||||
scanner := bufio.NewScanner(diffOutReader)
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
// getRebaseAmendMessage composes the message to amend commits in rebase merge of a pull request.
|
||||
func getRebaseAmendMessage(ctx *mergeContext, baseGitRepo *git.Repository) (message string, err error) {
|
||||
// Get existing commit message.
|
||||
commitMessage, _, err := gitcmd.NewCommand("show", "--format=%B", "-s").WithDir(ctx.tmpBasePath).RunStdString(ctx)
|
||||
commitMessage, _, err := gitcmd.NewCommand("show", "--format=%B", "-s").WithRepo(ctx.tmpRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -76,7 +76,7 @@ func doMergeRebaseFastForward(ctx *mergeContext) error {
|
||||
cmdCommit := gitcmd.NewCommand("commit", "--amend").
|
||||
AddOptionFormat("--message=%s", newMessage)
|
||||
addCommitSigningOptions(cmdCommit, ctx.signKey)
|
||||
if err := cmdCommit.WithDir(ctx.tmpBasePath).Run(ctx); err != nil {
|
||||
if err := cmdCommit.WithRepo(ctx.tmpRepo).Run(ctx); err != nil {
|
||||
log.Error("Unable to amend commit message: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -73,23 +73,23 @@ func checkPullRequestMergeableByTmpRepo(ctx context.Context, pr *issues_model.Pu
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
gitRepo, err := git.OpenRepositoryLocal(prCtx.tmpBasePath)
|
||||
tmpGitRepo, err := git.OpenRepositoryLocal(prCtx.tmpBasePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("OpenRepository: %w", err)
|
||||
}
|
||||
defer gitRepo.Close()
|
||||
defer tmpGitRepo.Close()
|
||||
|
||||
// 1. update merge base
|
||||
pr.MergeBase, _, err = gitcmd.NewCommand("merge-base", "--", tmpRepoBaseBranch, tmpRepoTrackingBranch).WithDir(prCtx.tmpBasePath).RunStdString(ctx)
|
||||
pr.MergeBase, _, err = gitcmd.NewCommand("merge-base", "--", tmpRepoBaseBranch, tmpRepoTrackingBranch).WithRepo(prCtx.tmpRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
var err2 error
|
||||
pr.MergeBase, err2 = gitRepo.GetRefCommitID(ctx, git.BranchPrefix+tmpRepoBaseBranch)
|
||||
pr.MergeBase, err2 = tmpGitRepo.GetRefCommitID(ctx, git.BranchPrefix+tmpRepoBaseBranch)
|
||||
if err2 != nil {
|
||||
return fmt.Errorf("GetMergeBase: %v and can't find commit ID for base: %w", err, err2)
|
||||
}
|
||||
}
|
||||
pr.MergeBase = strings.TrimSpace(pr.MergeBase)
|
||||
if pr.HeadCommitID, err = gitRepo.GetRefCommitID(ctx, git.BranchPrefix+tmpRepoTrackingBranch); err != nil {
|
||||
if pr.HeadCommitID, err = tmpGitRepo.GetRefCommitID(ctx, git.BranchPrefix+tmpRepoTrackingBranch); err != nil {
|
||||
return fmt.Errorf("GetBranchCommitID: can't find commit ID for head: %w", err)
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ func checkPullRequestMergeableByTmpRepo(ctx context.Context, pr *issues_model.Pu
|
||||
}
|
||||
|
||||
// 2. Check for conflicts
|
||||
conflicts, err := checkConflictsByTmpRepo(ctx, pr, gitRepo, prCtx.tmpBasePath)
|
||||
conflicts, err := checkConflictsByTmpRepo(ctx, pr, tmpGitRepo, prCtx.tmpBasePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -110,7 +110,7 @@ func checkPullRequestMergeableByTmpRepo(ctx context.Context, pr *issues_model.Pu
|
||||
}
|
||||
|
||||
// 3. Check for protected files changes
|
||||
if err = checkPullFilesProtection(ctx, pr, gitRepo, tmpRepoTrackingBranch); err != nil {
|
||||
if err = checkPullFilesProtection(ctx, pr, tmpGitRepo, tmpRepoTrackingBranch); err != nil {
|
||||
return fmt.Errorf("pr.CheckPullFilesProtection(): %w", err)
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ func (e *errMergeConflict) Error() string {
|
||||
return "conflict detected at: " + e.filename
|
||||
}
|
||||
|
||||
func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, filesToRemove *[]string, filesToAdd *[]git.IndexObjectInfo) error {
|
||||
func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, tmpGitRepo *git.Repository, filesToRemove *[]string, filesToAdd *[]git.IndexObjectInfo) error {
|
||||
log.Trace("Attempt to merge:\n%v", file)
|
||||
|
||||
switch {
|
||||
@@ -182,7 +182,7 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, f
|
||||
}
|
||||
|
||||
// Need to get the objects from the object db to attempt to merge
|
||||
root, _, err := gitcmd.NewCommand("unpack-file").AddDynamicArguments(file.stage1.sha).WithDir(tmpBasePath).RunStdString(ctx)
|
||||
root, _, err := gitcmd.NewCommand("unpack-file").AddDynamicArguments(file.stage1.sha).WithRepo(tmpGitRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get root object: %s at path: %s for merging. Error: %w", file.stage1.sha, file.stage1.path, err)
|
||||
}
|
||||
@@ -191,7 +191,7 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, f
|
||||
_ = util.Remove(filepath.Join(tmpBasePath, root))
|
||||
}()
|
||||
|
||||
base, _, err := gitcmd.NewCommand("unpack-file").AddDynamicArguments(file.stage2.sha).WithDir(tmpBasePath).RunStdString(ctx)
|
||||
base, _, err := gitcmd.NewCommand("unpack-file").AddDynamicArguments(file.stage2.sha).WithRepo(tmpGitRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get base object: %s at path: %s for merging. Error: %w", file.stage2.sha, file.stage2.path, err)
|
||||
}
|
||||
@@ -199,7 +199,7 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, f
|
||||
defer func() {
|
||||
_ = util.Remove(base)
|
||||
}()
|
||||
head, _, err := gitcmd.NewCommand("unpack-file").AddDynamicArguments(file.stage3.sha).WithDir(tmpBasePath).RunStdString(ctx)
|
||||
head, _, err := gitcmd.NewCommand("unpack-file").AddDynamicArguments(file.stage3.sha).WithRepo(tmpGitRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get head object:%s at path: %s for merging. Error: %w", file.stage3.sha, file.stage3.path, err)
|
||||
}
|
||||
@@ -209,13 +209,13 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, f
|
||||
}()
|
||||
|
||||
// now git merge-file annoyingly takes a different order to the merge-tree ...
|
||||
_, _, conflictErr := gitcmd.NewCommand("merge-file").AddDynamicArguments(base, root, head).WithDir(tmpBasePath).RunStdString(ctx)
|
||||
_, _, conflictErr := gitcmd.NewCommand("merge-file").AddDynamicArguments(base, root, head).WithRepo(tmpGitRepo).RunStdString(ctx)
|
||||
if conflictErr != nil {
|
||||
return &errMergeConflict{file.stage2.path}
|
||||
}
|
||||
|
||||
// base now contains the merged data
|
||||
hash, _, err := gitcmd.NewCommand("hash-object", "-w", "--path").AddDynamicArguments(file.stage2.path, base).WithDir(tmpBasePath).RunStdString(ctx)
|
||||
hash, _, err := gitcmd.NewCommand("hash-object", "-w", "--path").AddDynamicArguments(file.stage2.path, base).WithRepo(tmpGitRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -240,7 +240,7 @@ func AttemptThreeWayMerge(ctx context.Context, gitPath string, gitRepo *git.Repo
|
||||
defer cancel()
|
||||
|
||||
// First we use read-tree to do a simple three-way merge
|
||||
if err := gitcmd.NewCommand("read-tree", "-m").AddDynamicArguments(base, ours, theirs).WithDir(gitPath).RunWithStderr(ctx); err != nil {
|
||||
if err := gitcmd.NewCommand("read-tree", "-m").AddDynamicArguments(base, ours, theirs).WithRepo(gitRepo).RunWithStderr(ctx); err != nil {
|
||||
log.Error("Unable to run read-tree -m! Error: %v", err)
|
||||
return false, nil, fmt.Errorf("unable to run read-tree -m! Error: %w", err)
|
||||
}
|
||||
@@ -250,7 +250,7 @@ func AttemptThreeWayMerge(ctx context.Context, gitPath string, gitRepo *git.Repo
|
||||
|
||||
// Then we use git ls-files -u to list the unmerged files and collate the triples in unmergedfiles
|
||||
unmerged := make(chan *unmergedFile)
|
||||
go unmergedFiles(ctx, gitPath, unmerged)
|
||||
go unmergedFiles(ctx, gitRepo, unmerged)
|
||||
|
||||
defer func() {
|
||||
cancel()
|
||||
@@ -273,7 +273,7 @@ func AttemptThreeWayMerge(ctx context.Context, gitPath string, gitRepo *git.Repo
|
||||
}
|
||||
|
||||
// OK now we have the unmerged file triplet attempt to merge it
|
||||
if err := attemptMerge(ctx, file, gitPath, &filesToRemove, &filesToAdd); err != nil {
|
||||
if err := attemptMerge(ctx, file, gitPath, gitRepo, &filesToRemove, &filesToAdd); err != nil {
|
||||
if conflictErr, ok := err.(*errMergeConflict); ok {
|
||||
log.Trace("Conflict: %s in %s", conflictErr.filename, description)
|
||||
conflict = true
|
||||
@@ -298,14 +298,14 @@ func AttemptThreeWayMerge(ctx context.Context, gitPath string, gitRepo *git.Repo
|
||||
return conflict, conflictedFiles, nil
|
||||
}
|
||||
|
||||
func checkConflictsByTmpRepo(ctx context.Context, pr *issues_model.PullRequest, gitRepo *git.Repository, tmpBasePath string) (bool, error) {
|
||||
func checkConflictsByTmpRepo(ctx context.Context, pr *issues_model.PullRequest, tmpGitRepo *git.Repository, tmpBasePath string) (bool, error) {
|
||||
// 1. checkConflictsByTmpRepo resets the conflict status - therefore - reset the conflict status
|
||||
pr.ConflictedFiles = nil
|
||||
|
||||
// 2. AttemptThreeWayMerge first - this is much quicker than plain patch to base
|
||||
description := fmt.Sprintf("PR[%d] %s/%s#%d", pr.ID, pr.BaseRepo.OwnerName, pr.BaseRepo.Name, pr.Index)
|
||||
conflict, conflictFiles, err := AttemptThreeWayMerge(ctx,
|
||||
tmpBasePath, gitRepo, pr.MergeBase, tmpRepoBaseBranch, tmpRepoTrackingBranch, description)
|
||||
tmpBasePath, tmpGitRepo, pr.MergeBase, tmpRepoBaseBranch, tmpRepoTrackingBranch, description)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -314,13 +314,13 @@ func checkConflictsByTmpRepo(ctx context.Context, pr *issues_model.PullRequest,
|
||||
// No conflicts detected so we need to check if the patch is empty...
|
||||
// a. Write the newly merged tree and check the new tree-hash
|
||||
var treeHash string
|
||||
treeHash, _, err = gitcmd.NewCommand("write-tree").WithDir(tmpBasePath).RunStdString(ctx)
|
||||
treeHash, _, err = gitcmd.NewCommand("write-tree").WithRepo(tmpGitRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
lsfiles, _, _ := gitcmd.NewCommand("ls-files", "-u").WithDir(tmpBasePath).RunStdString(ctx)
|
||||
lsfiles, _, _ := gitcmd.NewCommand("ls-files", "-u").WithRepo(tmpGitRepo).RunStdString(ctx)
|
||||
return false, fmt.Errorf("unable to write unconflicted tree: %w\n`git ls-files -u`:\n%s", err, lsfiles)
|
||||
}
|
||||
treeHash = strings.TrimSpace(treeHash)
|
||||
baseTree, err := gitRepo.GetTree(ctx, tmpRepoBaseBranch)
|
||||
baseTree, err := tmpGitRepo.GetTree(ctx, tmpRepoBaseBranch)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -365,11 +365,11 @@ func (err ErrFilePathProtected) Unwrap() error {
|
||||
}
|
||||
|
||||
// CheckFileProtection check file Protection
|
||||
func CheckFileProtection(ctx context.Context, repo *git.Repository, branchName, oldCommitID, newCommitID string, patterns []glob.Glob, limit int, env []string) ([]string, error) {
|
||||
func CheckFileProtection(ctx context.Context, gitRepo *git.Repository, branchName, oldCommitID, newCommitID string, patterns []glob.Glob, limit int, env []string) ([]string, error) {
|
||||
if len(patterns) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
affectedFiles, err := git.GetAffectedFiles(ctx, repo, branchName, oldCommitID, newCommitID, env)
|
||||
affectedFiles, err := git.GetAffectedFiles(ctx, gitRepo, branchName, oldCommitID, newCommitID, env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -395,11 +395,11 @@ func CheckFileProtection(ctx context.Context, repo *git.Repository, branchName,
|
||||
}
|
||||
|
||||
// CheckUnprotectedFiles check if the commit only touches unprotected files
|
||||
func CheckUnprotectedFiles(ctx context.Context, repo *git.Repository, branchName, oldCommitID, newCommitID string, patterns []glob.Glob, env []string) (bool, error) {
|
||||
func CheckUnprotectedFiles(ctx context.Context, gitRepo *git.Repository, branchName, oldCommitID, newCommitID string, patterns []glob.Glob, env []string) (bool, error) {
|
||||
if len(patterns) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
affectedFiles, err := git.GetAffectedFiles(ctx, repo, branchName, oldCommitID, newCommitID, env)
|
||||
affectedFiles, err := git.GetAffectedFiles(ctx, gitRepo, branchName, oldCommitID, newCommitID, env)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
"gitea.dev/modules/log"
|
||||
)
|
||||
@@ -53,7 +54,7 @@ func (line *lsFileLine) String() string {
|
||||
|
||||
// readUnmergedLsFileLines calls git ls-files -u -z and parses the lines into mode-sha-stage-path quadruplets
|
||||
// it will push these to the provided channel closing it at the end
|
||||
func readUnmergedLsFileLines(ctx context.Context, tmpBasePath string, outputChan chan *lsFileLine) {
|
||||
func readUnmergedLsFileLines(ctx context.Context, tmpRepo git.RepositoryFacade, outputChan chan *lsFileLine) {
|
||||
defer func() {
|
||||
// Always close the outputChan at the end of this function
|
||||
close(outputChan)
|
||||
@@ -62,7 +63,7 @@ func readUnmergedLsFileLines(ctx context.Context, tmpBasePath string, outputChan
|
||||
cmd := gitcmd.NewCommand("ls-files", "-u", "-z")
|
||||
lsFilesReader, lsFilesReaderClose := cmd.MakeStdoutPipe()
|
||||
defer lsFilesReaderClose()
|
||||
err := cmd.WithDir(tmpBasePath).
|
||||
err := cmd.WithRepo(tmpRepo).
|
||||
WithPipelineFunc(func(gitcmd.Context) error {
|
||||
bufferedReader := bufio.NewReader(lsFilesReader)
|
||||
|
||||
@@ -123,7 +124,7 @@ func (u *unmergedFile) String() string {
|
||||
|
||||
// unmergedFiles will collate the output from readUnstagedLsFileLines in to file triplets and send them
|
||||
// to the provided channel, closing at the end.
|
||||
func unmergedFiles(ctx context.Context, tmpBasePath string, unmerged chan *unmergedFile) {
|
||||
func unmergedFiles(ctx context.Context, tmpGitRepo git.RepositoryFacade, unmerged chan *unmergedFile) {
|
||||
defer func() {
|
||||
// Always close the channel
|
||||
close(unmerged)
|
||||
@@ -131,7 +132,7 @@ func unmergedFiles(ctx context.Context, tmpBasePath string, unmerged chan *unmer
|
||||
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
lsFileLineChan := make(chan *lsFileLine, 10) // give lsFileLineChan a buffer
|
||||
go readUnmergedLsFileLines(ctx, tmpBasePath, lsFileLineChan)
|
||||
go readUnmergedLsFileLines(ctx, tmpGitRepo, lsFileLineChan)
|
||||
defer func() {
|
||||
cancel()
|
||||
for range lsFileLineChan {
|
||||
|
||||
@@ -536,7 +536,7 @@ func checkIfPRContentChanged(ctx context.Context, pr *issues_model.PullRequest,
|
||||
|
||||
stdoutReader, stdoutReaderClose := cmd.MakeStdoutPipe()
|
||||
defer stdoutReaderClose()
|
||||
if err := cmd.WithDir(prCtx.tmpBasePath).
|
||||
if err := cmd.WithRepo(prCtx.tmpRepo).
|
||||
WithPipelineFunc(func(ctx gitcmd.Context) error {
|
||||
return util.IsEmptyReader(stdoutReader)
|
||||
}).
|
||||
|
||||
@@ -40,7 +40,7 @@ type prTmpRepoContext struct {
|
||||
// Do NOT use it with gitcmd.RunStd*() functions, otherwise it will panic
|
||||
func (ctx *prTmpRepoContext) PrepareGitCmd(cmd *gitcmd.Command) *gitcmd.Command {
|
||||
ctx.outbuf.Reset()
|
||||
return cmd.WithDir(ctx.tmpBasePath).WithStdoutBuffer(ctx.outbuf)
|
||||
return cmd.WithRepo(ctx.tmpRepo).WithStdoutBuffer(ctx.outbuf)
|
||||
}
|
||||
|
||||
// createTemporaryRepoForPR creates a temporary repo with "base" for pr.BaseBranch and "tracking" for pr.HeadBranch
|
||||
|
||||
@@ -29,7 +29,7 @@ func updateHeadByRebaseOnToBase(ctx context.Context, pr *issues_model.PullReques
|
||||
|
||||
// Determine the old merge-base before the rebase - we use this for LFS push later on
|
||||
oldMergeBase, _, _ := gitcmd.NewCommand("merge-base").AddDashesAndList(tmpRepoBaseBranch, tmpRepoTrackingBranch).
|
||||
WithDir(mergeCtx.tmpBasePath).RunStdString(ctx)
|
||||
WithRepo(mergeCtx.tmpRepo).RunStdString(ctx)
|
||||
oldMergeBase = strings.TrimSpace(oldMergeBase)
|
||||
|
||||
// Rebase the tracking branch on to the base as the staging branch
|
||||
@@ -81,7 +81,7 @@ func updateHeadByRebaseOnToBase(ctx context.Context, pr *issues_model.PullReques
|
||||
pr.ID,
|
||||
pr.Index,
|
||||
)).
|
||||
WithDir(mergeCtx.tmpBasePath).
|
||||
WithRepo(mergeCtx.tmpRepo).
|
||||
WithStdoutBuffer(mergeCtx.outbuf).
|
||||
RunWithStderr(ctx); err != nil {
|
||||
if strings.Contains(err.Stderr(), "non-fast-forward") {
|
||||
|
||||
@@ -168,7 +168,7 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user
|
||||
cmdApply.AddArguments("-3")
|
||||
}
|
||||
|
||||
if err := cmdApply.WithDir(t.basePath).
|
||||
if err := cmdApply.WithRepo(t.gitRepo).
|
||||
WithStdinBytes([]byte(opts.Content)).
|
||||
RunWithStderr(ctx); err != nil {
|
||||
return nil, fmt.Errorf("git apply error: %w", err)
|
||||
|
||||
@@ -6,7 +6,6 @@ package files
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@@ -18,7 +17,6 @@ import (
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
"gitea.dev/modules/log"
|
||||
repo_module "gitea.dev/modules/repository"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/util"
|
||||
@@ -76,7 +74,7 @@ func (t *TemporaryUploadRepository) Clone(ctx context.Context, branch string, ba
|
||||
Name: t.repo.Name,
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("Clone: %w %s", err, stderr)
|
||||
return fmt.Errorf("temp repo clone error: %w, %s", err, stderr)
|
||||
}
|
||||
gitRepo, err := git.OpenRepositoryLocal(t.basePath)
|
||||
if err != nil {
|
||||
@@ -101,7 +99,7 @@ func (t *TemporaryUploadRepository) Init(ctx context.Context, objectFormatName s
|
||||
|
||||
// SetDefaultIndex sets the git index to our HEAD
|
||||
func (t *TemporaryUploadRepository) SetDefaultIndex(ctx context.Context) error {
|
||||
if err := gitcmd.NewCommand("read-tree", "HEAD").WithDir(t.basePath).RunWithStderr(ctx); err != nil {
|
||||
if err := gitcmd.NewCommand("read-tree", "HEAD").WithRepo(t.gitRepo).RunWithStderr(ctx); err != nil {
|
||||
return fmt.Errorf("SetDefaultIndex: %w", err)
|
||||
}
|
||||
return nil
|
||||
@@ -109,7 +107,7 @@ func (t *TemporaryUploadRepository) SetDefaultIndex(ctx context.Context) error {
|
||||
|
||||
// RefreshIndex looks at the current index and checks to see if merges or updates are needed by checking stat() information.
|
||||
func (t *TemporaryUploadRepository) RefreshIndex(ctx context.Context) error {
|
||||
if err := gitcmd.NewCommand("update-index", "--refresh").WithDir(t.basePath).RunWithStderr(ctx); err != nil {
|
||||
if err := gitcmd.NewCommand("update-index", "--refresh").WithRepo(t.gitRepo).RunWithStderr(ctx); err != nil {
|
||||
return fmt.Errorf("RefreshIndex: %w", err)
|
||||
}
|
||||
return nil
|
||||
@@ -119,7 +117,7 @@ func (t *TemporaryUploadRepository) RefreshIndex(ctx context.Context) error {
|
||||
func (t *TemporaryUploadRepository) LsFiles(ctx context.Context, filenames ...string) ([]string, error) {
|
||||
stdOut := new(bytes.Buffer)
|
||||
if err := gitcmd.NewCommand("ls-files", "-z").AddDashesAndList(filenames...).
|
||||
WithDir(t.basePath).
|
||||
WithRepo(t.gitRepo).
|
||||
WithStdoutBuffer(stdOut).
|
||||
RunWithStderr(ctx); err != nil {
|
||||
return nil, fmt.Errorf("unable to run git ls-files for temporary repo of: %s, error: %w", t.repo.FullName(), err)
|
||||
@@ -136,7 +134,7 @@ func (t *TemporaryUploadRepository) LsFiles(ctx context.Context, filenames ...st
|
||||
func (t *TemporaryUploadRepository) RemoveRecursivelyFromIndex(ctx context.Context, path string) error {
|
||||
_, _, err := gitcmd.NewCommand("rm", "--cached", "-r").
|
||||
AddDynamicArguments(path).
|
||||
WithDir(t.basePath).
|
||||
WithRepo(t.gitRepo).
|
||||
RunStdBytes(ctx)
|
||||
return err
|
||||
}
|
||||
@@ -157,7 +155,7 @@ func (t *TemporaryUploadRepository) RemoveFilesFromIndex(ctx context.Context, fi
|
||||
}
|
||||
|
||||
if err := gitcmd.NewCommand("update-index", "--remove", "-z", "--index-info").
|
||||
WithDir(t.basePath).
|
||||
WithRepo(t.gitRepo).
|
||||
WithStdinBytes(stdIn.Bytes()).
|
||||
RunWithStderr(ctx); err != nil {
|
||||
return fmt.Errorf("unable to update-index for temporary repo: %q, error: %w", t.repo.FullName(), err)
|
||||
@@ -169,7 +167,7 @@ func (t *TemporaryUploadRepository) RemoveFilesFromIndex(ctx context.Context, fi
|
||||
func (t *TemporaryUploadRepository) HashObjectAndWrite(ctx context.Context, content io.Reader) (string, error) {
|
||||
stdOut := new(bytes.Buffer)
|
||||
if err := gitcmd.NewCommand("hash-object", "-w", "--stdin").
|
||||
WithDir(t.basePath).
|
||||
WithRepo(t.gitRepo).
|
||||
WithStdoutBuffer(stdOut).
|
||||
WithStdinCopy(content).
|
||||
RunWithStderr(ctx); err != nil {
|
||||
@@ -182,7 +180,7 @@ func (t *TemporaryUploadRepository) HashObjectAndWrite(ctx context.Context, cont
|
||||
// AddObjectToIndex adds the provided object hash to the index with the provided mode and path
|
||||
func (t *TemporaryUploadRepository) AddObjectToIndex(ctx context.Context, mode, objectHash, objectPath string) error {
|
||||
cmd := gitcmd.NewCommand("update-index", "--add", "--replace", "--cacheinfo").
|
||||
AddDynamicArguments(mode + "," + objectHash + "," + objectPath).WithDir(t.basePath)
|
||||
AddDynamicArguments(mode + "," + objectHash + "," + objectPath).WithRepo(t.gitRepo)
|
||||
if err := cmd.RunWithStderr(ctx); err != nil {
|
||||
if matched, _ := regexp.MatchString(".*Invalid path '.*", err.Stderr()); matched {
|
||||
return ErrFilePathInvalid{
|
||||
@@ -197,10 +195,9 @@ func (t *TemporaryUploadRepository) AddObjectToIndex(ctx context.Context, mode,
|
||||
|
||||
// WriteTree writes the current index as a tree to the object db and returns its hash
|
||||
func (t *TemporaryUploadRepository) WriteTree(ctx context.Context) (string, error) {
|
||||
stdout, _, err := gitcmd.NewCommand("write-tree").WithDir(t.basePath).RunStdString(ctx)
|
||||
stdout, _, err := gitcmd.NewCommand("write-tree").WithRepo(t.gitRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
log.Error("Unable to write tree in temporary repo: %s(%s): Error: %v", t.repo.FullName(), t.basePath, err)
|
||||
return "", fmt.Errorf("Unable to write-tree in temporary repo for: %s Error: %w", t.repo.FullName(), err)
|
||||
return "", fmt.Errorf("unable to write-tree in temporary repo for %s, error: %w", t.repo.FullName(), err)
|
||||
}
|
||||
return strings.TrimSpace(stdout), nil
|
||||
}
|
||||
@@ -215,10 +212,9 @@ func (t *TemporaryUploadRepository) GetLastCommitByRef(ctx context.Context, ref
|
||||
if ref == "" {
|
||||
ref = "HEAD"
|
||||
}
|
||||
stdout, _, err := gitcmd.NewCommand("rev-parse").AddDynamicArguments(ref).WithDir(t.basePath).RunStdString(ctx)
|
||||
stdout, _, err := gitcmd.NewCommand("rev-parse").AddDynamicArguments(ref).WithRepo(t.gitRepo).RunStdString(ctx)
|
||||
if err != nil {
|
||||
log.Error("Unable to get last ref for %s in temporary repo: %s(%s): Error: %v", ref, t.repo.FullName(), t.basePath, err)
|
||||
return "", fmt.Errorf("Unable to rev-parse %s in temporary repo for: %s Error: %w", ref, t.repo.FullName(), err)
|
||||
return "", fmt.Errorf("unable to rev-parse ref %s in temporary repo for: %s, error: %w", ref, t.repo.FullName(), err)
|
||||
}
|
||||
return strings.TrimSpace(stdout), nil
|
||||
}
|
||||
@@ -328,11 +324,11 @@ func (t *TemporaryUploadRepository) CommitTree(ctx context.Context, opts *Commit
|
||||
stdout := new(bytes.Buffer)
|
||||
if err := cmdCommitTree.
|
||||
WithEnv(env).
|
||||
WithDir(t.basePath).
|
||||
WithRepo(t.gitRepo).
|
||||
WithStdoutBuffer(stdout).
|
||||
WithStdinBytes(messageBytes.Bytes()).
|
||||
RunWithStderr(ctx); err != nil {
|
||||
return "", fmt.Errorf("unable to commit-tree in temporary repo: %s Error: %w", t.repo.FullName(), err)
|
||||
return "", fmt.Errorf("unable to commit-tree in temporary repo: %s, error: %w", t.repo.FullName(), err)
|
||||
}
|
||||
return strings.TrimSpace(stdout.String()), nil
|
||||
}
|
||||
@@ -351,10 +347,7 @@ func (t *TemporaryUploadRepository) Push(ctx context.Context, doer *user_model.U
|
||||
} else if git.IsErrPushRejected(err) {
|
||||
return err
|
||||
}
|
||||
log.Error("Unable to push back to repo from temporary repo: %s (%s)\nError: %v",
|
||||
t.repo.FullName(), t.basePath, err)
|
||||
return fmt.Errorf("Unable to push back to repo from temporary repo: %s (%s) Error: %v",
|
||||
t.repo.FullName(), t.basePath, err)
|
||||
return fmt.Errorf("unable to push back to repo %s from temporary repo, error: %w", t.repo.FullName(), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -367,7 +360,7 @@ func (t *TemporaryUploadRepository) DiffIndex(ctx context.Context, oldContent, n
|
||||
defer stdoutReaderClose()
|
||||
|
||||
err := cmd.WithTimeout(30 * time.Second).
|
||||
WithDir(t.basePath).
|
||||
WithRepo(t.gitRepo).
|
||||
WithPipelineFunc(func(ctx gitcmd.Context) error {
|
||||
var diffErr error
|
||||
diff, diffErr = gitdiff.ParsePatch(ctx, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, stdoutReader, "")
|
||||
@@ -390,16 +383,10 @@ func (t *TemporaryUploadRepository) DiffIndex(ctx context.Context, oldContent, n
|
||||
|
||||
// GetBranchCommit Gets the commit object of the given branch
|
||||
func (t *TemporaryUploadRepository) GetBranchCommit(ctx context.Context, branch string) (*git.Commit, error) {
|
||||
if t.gitRepo == nil {
|
||||
return nil, errors.New("repository has not been cloned")
|
||||
}
|
||||
return t.gitRepo.GetBranchCommit(ctx, branch)
|
||||
}
|
||||
|
||||
// GetCommit Gets the commit object of the given commit ID
|
||||
func (t *TemporaryUploadRepository) GetCommit(ctx context.Context, commitID string) (*git.Commit, error) {
|
||||
if t.gitRepo == nil {
|
||||
return nil, errors.New("repository has not been cloned")
|
||||
}
|
||||
return t.gitRepo.GetCommit(ctx, commitID)
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r
|
||||
}
|
||||
|
||||
// Get active submodules from the template
|
||||
submodules, err := git.GetTemplateSubmoduleCommits(ctx, tmpDir)
|
||||
submodules, err := git.GetTemplateSubmoduleCommits(ctx, templateRepo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetTemplateSubmoduleCommits: %w", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user