From 91eb14c94460c3c2bc41e1f5e13166ed3a12d61c Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Tue, 21 Jul 2026 20:18:00 +0800 Subject: [PATCH] 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) --- modelmigration/base/git.go | 13 ++++++ modelmigration/migrationtest/tests.go | 4 ++ modelmigration/v1_12/v128.go | 12 +++--- modelmigration/v1_12/v134.go | 8 ++-- modelmigration/v1_12/v136.go | 3 +- modelmigration/v1_14/v156.go | 3 +- modelmigration/v1_17/v215.go | 13 +++--- modelmigration/v1_17/v219.go | 6 +-- modelmigration/v1_21/v276.go | 3 +- modelmigration/v1_22/v297.go | 3 +- modelmigration/v1_24/v318.go | 3 +- modelmigration/v1_26/v326_test.go | 4 -- modelmigration/v1_9/v82.go | 3 +- models/db/engine.go | 4 ++ models/init.go | 15 +++++++ models/{ => repostats}/main_test.go | 2 +- models/{ => repostats}/repo.go | 8 +--- models/{ => repostats}/repo_test.go | 2 +- modules/git/archive.go | 16 +++++--- modules/git/catfile_batch.go | 11 ++++-- modules/git/catfile_batch_command.go | 18 +++------ modules/git/catfile_batch_legacy.go | 16 +++----- modules/git/catfile_batch_reader.go | 6 +-- modules/git/gitcmd/command.go | 55 ++++++++++++-------------- modules/git/gitcmd/repo.go | 2 +- modules/git/pipeline/catfile.go | 12 +++--- modules/git/pipeline/revlist.go | 5 ++- modules/git/repo.go | 10 ++--- modules/git/submodule.go | 10 ++--- modules/git/submodule_test.go | 4 +- routers/web/repo/githttp.go | 6 +-- services/cron/tasks_basic.go | 4 +- services/doctor/misc.go | 4 +- services/migrations/gitea_uploader.go | 4 +- services/pull/lfs.go | 4 +- services/pull/merge_prepare.go | 12 +++--- services/pull/merge_rebase.go | 4 +- services/pull/patch.go | 50 +++++++++++------------ services/pull/patch_unmerged.go | 9 +++-- services/pull/pull.go | 2 +- services/pull/temp_repo.go | 2 +- services/pull/update_rebase.go | 4 +- services/repository/files/patch.go | 2 +- services/repository/files/temp_repo.go | 45 ++++++++------------- services/repository/generate.go | 2 +- 45 files changed, 211 insertions(+), 217 deletions(-) create mode 100644 modelmigration/base/git.go create mode 100644 models/init.go rename models/{ => repostats}/main_test.go (97%) rename models/{ => repostats}/repo.go (98%) rename models/{ => repostats}/repo_test.go (98%) diff --git a/modelmigration/base/git.go b/modelmigration/base/git.go new file mode 100644 index 00000000000..fd8ebba8c5d --- /dev/null +++ b/modelmigration/base/git.go @@ -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) +} diff --git a/modelmigration/migrationtest/tests.go b/modelmigration/migrationtest/tests.go index 4e3c0899ff1..024afc38aa0 100644 --- a/modelmigration/migrationtest/tests.go +++ b/modelmigration/migrationtest/tests.go @@ -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 diff --git a/modelmigration/v1_12/v128.go b/modelmigration/v1_12/v128.go index 6760d6f858f..991ab25ae50 100644 --- a/modelmigration/v1_12/v128.go +++ b/modelmigration/v1_12/v128.go @@ -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 diff --git a/modelmigration/v1_12/v134.go b/modelmigration/v1_12/v134.go index dc70923a228..043ecacb80b 100644 --- a/modelmigration/v1_12/v134.go +++ b/modelmigration/v1_12/v134.go @@ -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 diff --git a/modelmigration/v1_12/v136.go b/modelmigration/v1_12/v136.go index a7004b58bfc..7a85484f93f 100644 --- a/modelmigration/v1_12/v136.go +++ b/modelmigration/v1_12/v136.go @@ -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 { diff --git a/modelmigration/v1_14/v156.go b/modelmigration/v1_14/v156.go index f9be57ffe3f..001cb238689 100644 --- a/modelmigration/v1_14/v156.go +++ b/modelmigration/v1_14/v156.go @@ -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 diff --git a/modelmigration/v1_17/v215.go b/modelmigration/v1_17/v215.go index 9b09a207d20..f376b0e1a72 100644 --- a/modelmigration/v1_17/v215.go +++ b/modelmigration/v1_17/v215.go @@ -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)) diff --git a/modelmigration/v1_17/v219.go b/modelmigration/v1_17/v219.go index fa6c3a4bcbc..0c7a783c739 100644 --- a/modelmigration/v1_17/v219.go +++ b/modelmigration/v1_17/v219.go @@ -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"` diff --git a/modelmigration/v1_21/v276.go b/modelmigration/v1_21/v276.go index c0375eaf4bb..7ad785020de 100644 --- a/modelmigration/v1_21/v276.go +++ b/modelmigration/v1_21/v276.go @@ -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 } diff --git a/modelmigration/v1_22/v297.go b/modelmigration/v1_22/v297.go index af42b5c67c3..2f03e342eb6 100644 --- a/modelmigration/v1_22/v297.go +++ b/modelmigration/v1_22/v297.go @@ -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{}) } diff --git a/modelmigration/v1_24/v318.go b/modelmigration/v1_24/v318.go index d9d9b429e15..218126093a9 100644 --- a/modelmigration/v1_24/v318.go +++ b/modelmigration/v1_24/v318.go @@ -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, diff --git a/modelmigration/v1_26/v326_test.go b/modelmigration/v1_26/v326_test.go index 6721954f1f6..ba07cff909b 100644 --- a/modelmigration/v1_26/v326_test.go +++ b/modelmigration/v1_26/v326_test.go @@ -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" ) diff --git a/modelmigration/v1_9/v82.go b/modelmigration/v1_9/v82.go index 44b58432ad7..97b0095e6ae 100644 --- a/modelmigration/v1_9/v82.go +++ b/modelmigration/v1_9/v82.go @@ -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 } diff --git a/models/db/engine.go b/models/db/engine.go index ef0636ca607..5cfb2018e0c 100755 --- a/models/db/engine.go +++ b/models/db/engine.go @@ -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{ diff --git a/models/init.go b/models/init.go new file mode 100644 index 00000000000..50119e6595f --- /dev/null +++ b/models/init.go @@ -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() +} diff --git a/models/main_test.go b/models/repostats/main_test.go similarity index 97% rename from models/main_test.go rename to models/repostats/main_test.go index 21112a1736c..064d5f4ddf0 100644 --- a/models/main_test.go +++ b/models/repostats/main_test.go @@ -1,7 +1,7 @@ // Copyright 2020 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package models +package repostats import ( "testing" diff --git a/models/repo.go b/models/repostats/repo.go similarity index 98% rename from models/repo.go rename to models/repostats/repo.go index c0f59e3bdaa..997db52e2ef 100644 --- a/models/repo.go +++ b/models/repostats/repo.go @@ -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 diff --git a/models/repo_test.go b/models/repostats/repo_test.go similarity index 98% rename from models/repo_test.go rename to models/repostats/repo_test.go index 059ceab709e..97b90f0bef5 100644 --- a/models/repo_test.go +++ b/models/repostats/repo_test.go @@ -1,7 +1,7 @@ // Copyright 2017 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package models +package repostats import ( "testing" diff --git a/modules/git/archive.go b/modules/git/archive.go index b8174933938..c5e3451c48f 100644 --- a/modules/git/archive.go +++ b/modules/git/archive.go @@ -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 } diff --git a/modules/git/catfile_batch.go b/modules/git/catfile_batch.go index d4e697117aa..f3e71f30857 100644 --- a/modules/git/catfile_batch.go +++ b/modules/git/catfile_batch.go @@ -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 } diff --git a/modules/git/catfile_batch_command.go b/modules/git/catfile_batch_command.go index 96d58334f8f..df9b7c01578 100644 --- a/modules/git/catfile_batch_command.go +++ b/modules/git/catfile_batch_command.go @@ -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 } diff --git a/modules/git/catfile_batch_legacy.go b/modules/git/catfile_batch_legacy.go index 79f12a9f433..356e67eb8da 100644 --- a/modules/git/catfile_batch_legacy.go +++ b/modules/git/catfile_batch_legacy.go @@ -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 } diff --git a/modules/git/catfile_batch_reader.go b/modules/git/catfile_batch_reader.go index 71c0c87af6b..fca670c1f28 100644 --- a/modules/git/catfile_batch_reader.go +++ b/modules/git/catfile_batch_reader.go @@ -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) }() diff --git a/modules/git/gitcmd/command.go b/modules/git/gitcmd/command.go index 184874bde6c..230f62e597a 100644 --- a/modules/git/gitcmd/command.go +++ b/modules/git/gitcmd/command.go @@ -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, diff --git a/modules/git/gitcmd/repo.go b/modules/git/gitcmd/repo.go index 6e76e760eb8..4e05fda32e1 100644 --- a/modules/git/gitcmd/repo.go +++ b/modules/git/gitcmd/repo.go @@ -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 } diff --git a/modules/git/pipeline/catfile.go b/modules/git/pipeline/catfile.go index 57ae25b3f80..6f3f511a89e 100644 --- a/modules/git/pipeline/catfile.go +++ b/modules/git/pipeline/catfile.go @@ -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 diff --git a/modules/git/pipeline/revlist.go b/modules/git/pipeline/revlist.go index 48b489bef7c..b5266fd628b 100644 --- a/modules/git/pipeline/revlist.go +++ b/modules/git/pipeline/revlist.go @@ -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 diff --git a/modules/git/repo.go b/modules/git/repo.go index e96c612e02f..8cd5ff3540e 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -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} diff --git a/modules/git/submodule.go b/modules/git/submodule.go index 1b100c06c58..8beebebb6ef 100644 --- a/modules/git/submodule.go +++ b/modules/git/submodule.go @@ -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 } } diff --git a/modules/git/submodule_test.go b/modules/git/submodule_test.go index 25355ac32a6..94de9c5a5ef 100644 --- a/modules/git/submodule_test.go +++ b/modules/git/submodule_test.go @@ -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) diff --git a/routers/web/repo/githttp.go b/routers/web/repo/githttp.go index 24009bb93a8..c8730b59616 100644 --- a/routers/web/repo/githttp.go +++ b/routers/web/repo/githttp.go @@ -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))) diff --git a/services/cron/tasks_basic.go b/services/cron/tasks_basic.go index d76d873b368..34183b2271b 100644 --- a/services/cron/tasks_basic.go +++ b/services/cron/tasks_basic.go @@ -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) }) } diff --git a/services/doctor/misc.go b/services/doctor/misc.go index 9880ce6adc2..21193b4752e 100644 --- a/services/doctor/misc.go +++ b/services/doctor/misc.go @@ -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 } diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index 283e7069111..4cc2d073b48 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -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 } diff --git a/services/pull/lfs.go b/services/pull/lfs.go index dd619e3b419..fda3f058ff5 100644 --- a/services/pull/lfs.go +++ b/services/pull/lfs.go @@ -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() diff --git a/services/pull/merge_prepare.go b/services/pull/merge_prepare.go index 974250357d5..17cd03c5c85 100644 --- a/services/pull/merge_prepare.go +++ b/services/pull/merge_prepare.go @@ -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) diff --git a/services/pull/merge_rebase.go b/services/pull/merge_rebase.go index fbdf0163793..f82492d8ebb 100644 --- a/services/pull/merge_rebase.go +++ b/services/pull/merge_rebase.go @@ -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 } diff --git a/services/pull/patch.go b/services/pull/patch.go index f9231c004f2..2a099cf0c5b 100644 --- a/services/pull/patch.go +++ b/services/pull/patch.go @@ -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 } diff --git a/services/pull/patch_unmerged.go b/services/pull/patch_unmerged.go index 447cf4e1b47..854acc5d3b5 100644 --- a/services/pull/patch_unmerged.go +++ b/services/pull/patch_unmerged.go @@ -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 { diff --git a/services/pull/pull.go b/services/pull/pull.go index 8de32f5f839..868f29621e3 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -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) }). diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go index 45a3ffe04fe..2b92baf1a35 100644 --- a/services/pull/temp_repo.go +++ b/services/pull/temp_repo.go @@ -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 diff --git a/services/pull/update_rebase.go b/services/pull/update_rebase.go index 9709125a41f..bd2906d548c 100644 --- a/services/pull/update_rebase.go +++ b/services/pull/update_rebase.go @@ -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") { diff --git a/services/repository/files/patch.go b/services/repository/files/patch.go index 0be007f1f7d..e791e4859c1 100644 --- a/services/repository/files/patch.go +++ b/services/repository/files/patch.go @@ -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) diff --git a/services/repository/files/temp_repo.go b/services/repository/files/temp_repo.go index dfe627527ac..abf03e24103 100644 --- a/services/repository/files/temp_repo.go +++ b/services/repository/files/temp_repo.go @@ -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) } diff --git a/services/repository/generate.go b/services/repository/generate.go index 998958ecfae..5f55ccfb8c8 100644 --- a/services/repository/generate.go +++ b/services/repository/generate.go @@ -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) }