From 1acf93d85470142963afe2344b5719fe5336e5f6 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Thu, 23 Jul 2026 09:22:26 +0800 Subject: [PATCH] refactor: clean up git repo and model migration packages (#38564) enable the golangci depguard lint rule: deny "models" and its sub packages in "modelmigration" package. --- .golangci.yml | 6 ++-- modelmigration/base/db.go | 13 ++++--- modelmigration/base/git.go | 13 ------- modelmigration/base/shared.go | 25 +++++++++++++ modelmigration/migrationtest/tests.go | 4 +-- modelmigration/v1_17/v220.go | 2 +- modelmigration/v1_18/v229.go | 13 +++++-- modelmigration/v1_18/v229_test.go | 26 +++++++++++--- modelmigration/v1_19/v240.go | 3 +- modelmigration/v1_21/v264.go | 3 +- modelmigration/v1_22/v293.go | 34 ++++++++++-------- modelmigration/v1_22/v293_test.go | 32 +++++++++++++---- modelmigration/v1_27/v335.go | 3 +- models/repo/repo_location.go | 35 +++++-------------- models/repo/repo_location_test.go | 5 +-- modules/git/archive.go | 3 +- modules/git/catfile_batch.go | 4 +-- modules/git/catfile_batch_test.go | 6 ++-- modules/git/clone.go | 8 ++--- modules/git/fetch.go | 3 +- modules/git/gitcmd/command.go | 6 ++++ modules/git/gitrepo/dbrepo.go | 24 +++++++++++++ .../{gitcmd/repo.go => gitrepo/gitrepo.go} | 7 +--- modules/git/grep_test.go | 4 +-- modules/git/hook.go | 6 ++-- modules/git/hooks.go | 6 ++-- modules/git/localfs.go | 22 ++++++------ modules/git/main_test.go | 6 ++-- modules/git/push.go | 10 +++--- modules/git/repo.go | 11 +++--- modules/git/repo_base_gogit.go | 4 +-- modules/git/repo_commitgraph_gogit.go | 4 +-- modules/git/size.go | 4 +-- modules/git/submodule.go | 2 +- modules/repository/temp.go | 4 +-- routers/api/v1/admin/adopt.go | 5 +-- routers/private/serv.go | 4 +-- routers/web/admin/repos.go | 3 +- routers/web/user/setting/adopt.go | 3 +- services/migrations/dump.go | 5 +-- services/repository/adopt.go | 3 +- services/repository/repository.go | 3 +- services/repository/transfer.go | 23 ++++++------ 43 files changed, 243 insertions(+), 167 deletions(-) delete mode 100644 modelmigration/base/git.go create mode 100644 modelmigration/base/shared.go create mode 100644 modules/git/gitrepo/dbrepo.go rename modules/git/{gitcmd/repo.go => gitrepo/gitrepo.go} (96%) diff --git a/.golangci.yml b/.golangci.yml index 38b7a9ae28..ba5090367e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -55,10 +55,10 @@ linters: files: - '**/modelmigration/**/*.go' deny: - - pkg: gitea.dev/models$ # FIXME: it should deny all sub packages like "gitea.dev/models/repo" - desc: migrations must not depend on the models package + - pkg: gitea.dev/models + desc: "migrations must not depend on the models package. HINT: MIGRATION-STRUCT-FROZEN" - pkg: gitea.dev/modules/structs - desc: migrations must not depend on modules/structs (API structures change over time) + desc: "migrations must not depend on modules/structs. HINT: MIGRATION-STRUCT-FROZEN" nolintlint: allow-unused: false require-explanation: true diff --git a/modelmigration/base/db.go b/modelmigration/base/db.go index b3dfd9848b..8385fc2735 100644 --- a/modelmigration/base/db.go +++ b/modelmigration/base/db.go @@ -11,19 +11,14 @@ import ( "regexp" "strings" - "gitea.dev/models/db" + "gitea.dev/models/db" //nolint:depguard // allow to access db in migration "gitea.dev/modules/log" "gitea.dev/modules/setting" + "xorm.io/builder" "xorm.io/xorm/schemas" ) -// Migrations should never use model structs directly, because the model structs can be different in different releases. -// e.g. if one migration uses "User" model, it works in the early releases, then one day, -// when the User model changes, the migration breaks because it will use the new (incorrect) User model, -// it should only use the old User model. The same to "modules/structs". -// However, many the existing migrations already abuses "modules/structs" (search "gitea.dev/models/" in the migrations). -// TODO: need to fully decouple the migration package and models & structs package type ( EngineMigration = db.EngineMigration Session = db.Session @@ -519,3 +514,7 @@ func ModifyColumn(x EngineMigration, tableName string, col *schemas.Column) erro } return nil } + +func Iterate[Bean any](ctx context.Context, cond builder.Cond, f func(ctx context.Context, bean *Bean) error) error { + return db.Iterate(ctx, cond, f) +} diff --git a/modelmigration/base/git.go b/modelmigration/base/git.go deleted file mode 100644 index fd8ebba8c5..0000000000 --- a/modelmigration/base/git.go +++ /dev/null @@ -1,13 +0,0 @@ -// 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/base/shared.go b/modelmigration/base/shared.go new file mode 100644 index 0000000000..17c3441762 --- /dev/null +++ b/modelmigration/base/shared.go @@ -0,0 +1,25 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package base + +import ( + "gitea.dev/models/db" //nolint:depguard // allow to access db in migration + "gitea.dev/modules/git/gitrepo" +) + +// HINT: MIGRATION-STRUCT-FROZEN: the structs used in migrations should not be affected by the changes happen in the future, +// because the details can be different in different releases. +// e.g. if one migration uses "User" model, it works in the early releases, +// then one day, when the User model changes, the existing migration will break because it will use the new (incorrect) User model, +// it should only use the old User model. +// +// Related: "models", "modules/structs", git repo directory layout on the disk, etc. +// +// If changes happen, the old migrations need to use a snapshot struct/function (copy the code and freeze) + +type ResourceIndex = db.ResourceIndex + +func LocalCodeGitRepo(ownerName, repoName string) gitrepo.RepositoryFacade { + return gitrepo.CodeRepoByName(ownerName, repoName) +} diff --git a/modelmigration/migrationtest/tests.go b/modelmigration/migrationtest/tests.go index 024afc38aa..9b82e94430 100644 --- a/modelmigration/migrationtest/tests.go +++ b/modelmigration/migrationtest/tests.go @@ -9,8 +9,8 @@ import ( "testing" "gitea.dev/modelmigration/base" - "gitea.dev/models/db" - "gitea.dev/models/unittest" + "gitea.dev/models/db" //nolint:depguard // allow to access db in migration tests + "gitea.dev/models/unittest" //nolint:depguard // allow to access db in migration tests "gitea.dev/modules/git" "gitea.dev/modules/setting" "gitea.dev/modules/testlogger" diff --git a/modelmigration/v1_17/v220.go b/modelmigration/v1_17/v220.go index e2cee4a6bf..c02fd8d315 100644 --- a/modelmigration/v1_17/v220.go +++ b/modelmigration/v1_17/v220.go @@ -5,7 +5,7 @@ package v1_17 import ( "gitea.dev/modelmigration/base" - packages_model "gitea.dev/models/packages" + packages_model "gitea.dev/models/packages" //nolint:depguard // only consts are used container_module "gitea.dev/modules/packages/container" "xorm.io/xorm/schemas" diff --git a/modelmigration/v1_18/v229.go b/modelmigration/v1_18/v229.go index a3081d736e..9b4ef19a55 100644 --- a/modelmigration/v1_18/v229.go +++ b/modelmigration/v1_18/v229.go @@ -7,7 +7,7 @@ import ( "fmt" "gitea.dev/modelmigration/base" - "gitea.dev/models/issues" + "gitea.dev/modules/timeutil" "xorm.io/builder" ) @@ -19,6 +19,15 @@ func UpdateOpenMilestoneCounts(x base.EngineMigration) error { return fmt.Errorf("error selecting open milestone IDs: %w", err) } + type Milestone struct { + ID int64 + IsClosed bool + NumIssues int + NumClosedIssues int + Completeness int + UpdatedUnix timeutil.TimeStamp + } + for _, id := range openMilestoneIDs { _, err := x.ID(id). Cols("num_issues", "num_closed_issues"). @@ -31,7 +40,7 @@ func UpdateOpenMilestoneCounts(x base.EngineMigration) error { "is_closed": true, }, )). - Update(&issues.Milestone{}) + Update(&Milestone{}) if err != nil { return fmt.Errorf("error updating issue counts in milestone %d: %w", id, err) } diff --git a/modelmigration/v1_18/v229_test.go b/modelmigration/v1_18/v229_test.go index ec3306cbd1..7fd76292ac 100644 --- a/modelmigration/v1_18/v229_test.go +++ b/modelmigration/v1_18/v229_test.go @@ -7,16 +7,34 @@ import ( "testing" "gitea.dev/modelmigration/migrationtest" - "gitea.dev/models/issues" + "gitea.dev/modules/timeutil" "github.com/stretchr/testify/assert" ) func Test_UpdateOpenMilestoneCounts(t *testing.T) { - type ExpectedMilestone issues.Milestone + type Issue struct { + ID int64 + RepoID int64 + Index int64 + MilestoneID int64 + IsClosed bool + UpdatedUnix timeutil.TimeStamp + } + + type Milestone struct { + ID int64 + IsClosed bool + NumIssues int + NumClosedIssues int + Completeness int + UpdatedUnix timeutil.TimeStamp + } + + type ExpectedMilestone Milestone // Prepare and load the testing database - x, deferable := migrationtest.PrepareTestEnv(t, 0, new(issues.Milestone), new(ExpectedMilestone), new(issues.Issue)) + x, deferable := migrationtest.PrepareTestEnv(t, 0, new(Milestone), new(ExpectedMilestone), new(Issue)) defer deferable() if x == nil || t.Failed() { return @@ -32,7 +50,7 @@ func Test_UpdateOpenMilestoneCounts(t *testing.T) { return } - got := []issues.Milestone{} + got := []Milestone{} if err := x.Table("milestone").Asc("id").Find(&got); !assert.NoError(t, err) { return } diff --git a/modelmigration/v1_19/v240.go b/modelmigration/v1_19/v240.go index 34bab4bb51..834e4479d9 100644 --- a/modelmigration/v1_19/v240.go +++ b/modelmigration/v1_19/v240.go @@ -5,7 +5,6 @@ package v1_19 import ( "gitea.dev/modelmigration/base" - "gitea.dev/models/db" "gitea.dev/modules/timeutil" ) @@ -96,7 +95,7 @@ func AddActionsTables(x base.EngineMigration) error { NumClosedActionRuns int `xorm:"NOT NULL DEFAULT 0"` } - type ActionRunIndex db.ResourceIndex + type ActionRunIndex base.ResourceIndex type ActionTask struct { ID int64 diff --git a/modelmigration/v1_21/v264.go b/modelmigration/v1_21/v264.go index 0cc50be077..7ecab57c76 100644 --- a/modelmigration/v1_21/v264.go +++ b/modelmigration/v1_21/v264.go @@ -8,7 +8,6 @@ import ( "errors" "gitea.dev/modelmigration/base" - "gitea.dev/models/db" "gitea.dev/modules/timeutil" ) @@ -60,7 +59,7 @@ func AddBranchTable(x base.EngineMigration) error { } branches := make([]Branch, 0, 100) - if err := db.Iterate(context.Background(), nil, func(ctx context.Context, deletedBranch *DeletedBranch) error { + if err := base.Iterate(context.Background(), nil, func(ctx context.Context, deletedBranch *DeletedBranch) error { branches = append(branches, Branch{ RepoID: deletedBranch.RepoID, Name: deletedBranch.Name, diff --git a/modelmigration/v1_22/v293.go b/modelmigration/v1_22/v293.go index 3a119988c4..492f312335 100644 --- a/modelmigration/v1_22/v293.go +++ b/modelmigration/v1_22/v293.go @@ -9,6 +9,24 @@ import ( "gitea.dev/modules/timeutil" ) +type ProjectBoardV293 struct { + ID int64 `xorm:"pk autoincr"` + Title string + Default bool `xorm:"NOT NULL DEFAULT false"` // issues not assigned to a specific board will be assigned to this board + Sorting int8 `xorm:"NOT NULL DEFAULT 0"` + Color string `xorm:"VARCHAR(7)"` + + ProjectID int64 `xorm:"INDEX NOT NULL"` + CreatorID int64 `xorm:"NOT NULL"` + + CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` + UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` +} + +func (ProjectBoardV293) TableName() string { + return "project_board" +} + // CheckProjectColumnsConsistency ensures there is exactly one default board per project present func CheckProjectColumnsConsistency(x base.EngineMigration) error { sess := x.NewSession() @@ -25,20 +43,6 @@ func CheckProjectColumnsConsistency(x base.EngineMigration) error { BoardID int64 } - type ProjectBoard struct { - ID int64 `xorm:"pk autoincr"` - Title string - Default bool `xorm:"NOT NULL DEFAULT false"` // issues not assigned to a specific board will be assigned to this board - Sorting int8 `xorm:"NOT NULL DEFAULT 0"` - Color string `xorm:"VARCHAR(7)"` - - ProjectID int64 `xorm:"INDEX NOT NULL"` - CreatorID int64 `xorm:"NOT NULL"` - - CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` - UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` - } - for { if err := sess.Begin(); err != nil { return err @@ -56,7 +60,7 @@ func CheckProjectColumnsConsistency(x base.EngineMigration) error { } for _, p := range projects { - if _, err := sess.Insert(ProjectBoard{ + if _, err := sess.Insert(ProjectBoardV293{ ProjectID: p.ID, Default: true, Title: "Uncategorized", diff --git a/modelmigration/v1_22/v293_test.go b/modelmigration/v1_22/v293_test.go index bac5e4ea33..e3d86aed6a 100644 --- a/modelmigration/v1_22/v293_test.go +++ b/modelmigration/v1_22/v293_test.go @@ -7,14 +7,30 @@ import ( "testing" "gitea.dev/modelmigration/migrationtest" - "gitea.dev/models/project" + "gitea.dev/modules/timeutil" "github.com/stretchr/testify/assert" ) func Test_CheckProjectColumnsConsistency(t *testing.T) { - // Prepare and load the testing database - x, deferable := migrationtest.PrepareTestEnv(t, 0, new(project.Project), new(project.Column)) + type Project struct { + ID int64 + Title string + Description string + OwnerID int64 + RepoID int64 + CreatorID int64 + IsClosed bool + TemplateType uint8 + BoardType uint8 + Type uint8 + + CreatedUnix timeutil.TimeStamp + UpdatedUnix timeutil.TimeStamp + ClosedDateUnix timeutil.TimeStamp + } + + x, deferable := migrationtest.PrepareTestEnv(t, 0, new(Project), new(ProjectBoardV293)) defer deferable() if x == nil || t.Failed() { return @@ -23,7 +39,7 @@ func Test_CheckProjectColumnsConsistency(t *testing.T) { assert.NoError(t, CheckProjectColumnsConsistency(x)) // check if default column was added - var defaultColumn project.Column + var defaultColumn ProjectBoardV293 has, err := x.Where("project_id=? AND `default` = ?", 1, true).Get(&defaultColumn) assert.NoError(t, err) assert.True(t, has) @@ -31,13 +47,17 @@ func Test_CheckProjectColumnsConsistency(t *testing.T) { assert.True(t, defaultColumn.Default) // check if multiple defaults, previous were removed and last will be kept - expectDefaultColumn, err := project.GetColumn(t.Context(), 2) + var expectDefaultColumn ProjectBoardV293 + has, err = x.ID(2).Get(&expectDefaultColumn) assert.NoError(t, err) + assert.True(t, has) assert.Equal(t, int64(2), expectDefaultColumn.ProjectID) assert.False(t, expectDefaultColumn.Default) - expectNonDefaultColumn, err := project.GetColumn(t.Context(), 3) + var expectNonDefaultColumn ProjectBoardV293 + has, err = x.ID(3).Get(&expectNonDefaultColumn) assert.NoError(t, err) + assert.True(t, has) assert.Equal(t, int64(2), expectNonDefaultColumn.ProjectID) assert.True(t, expectNonDefaultColumn.Default) } diff --git a/modelmigration/v1_27/v335.go b/modelmigration/v1_27/v335.go index e0e9a1ffb4..e0d12ff50f 100644 --- a/modelmigration/v1_27/v335.go +++ b/modelmigration/v1_27/v335.go @@ -5,7 +5,6 @@ package v1_27 import ( "gitea.dev/modelmigration/base" - "gitea.dev/models/db" "xorm.io/xorm" ) @@ -25,7 +24,7 @@ func AddReusableWorkflowFieldsToActionRunJob(x base.EngineMigration) error { ReusableWorkflowContent []byte `xorm:"LONGBLOB"` } - type ActionRunAttemptJobIDIndex db.ResourceIndex + type ActionRunAttemptJobIDIndex base.ResourceIndex if _, err := x.SyncWithOptions(xorm.SyncOptions{IgnoreDropIndices: true}, new(ActionRunJob)); err != nil { return err diff --git a/models/repo/repo_location.go b/models/repo/repo_location.go index 64ded367d8..1057eee8d7 100644 --- a/models/repo/repo_location.go +++ b/models/repo/repo_location.go @@ -5,42 +5,23 @@ package repo import ( "strconv" - "strings" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" ) -func repoCodeGitRepoRelativePath(ownerName, repoName string) string { - return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git" -} - -func repoWikiGitRepoRelativePath(ownerName, repoName string) string { - return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".wiki.git" -} - -// CodeRepoByName returns an unmanaged repository facade for the code repository of the given owner and repository name. -// Usually it is used for migration fixes or repository adoption/creation/rename/transfer. -func CodeRepoByName(ownerName, repoName string) gitcmd.RepositoryFacade { - return gitcmd.RepositoryUnmanaged(repoCodeGitRepoRelativePath(ownerName, repoName)) -} - -func WikiRepoByName(ownerName, repoName string) gitcmd.RepositoryFacade { - return gitcmd.RepositoryUnmanaged(repoWikiGitRepoRelativePath(ownerName, repoName)) -} - func repoCodeGitRepoManagedID(repoID int64) string { return "repo-" + strconv.FormatInt(repoID, 10) } -func (repo *Repository) CodeStorageRepo() gitcmd.RepositoryFacade { +func (repo *Repository) CodeStorageRepo() gitrepo.RepositoryFacade { id := repoCodeGitRepoManagedID(repo.ID) - repoPath := repoCodeGitRepoRelativePath(repo.OwnerName, repo.Name) - return gitcmd.RepositoryManaged(id, repoPath) + repoPath := gitrepo.RepoCodeGitRepoRelativePath(repo.OwnerName, repo.Name) + return gitrepo.RepositoryManaged(id, repoPath) } func (repo *Repository) GitRepoLocation() string { // TODO: use CodeGitRepo instead of this one - return repoCodeGitRepoRelativePath(repo.OwnerName, repo.Name) + return gitrepo.RepoCodeGitRepoRelativePath(repo.OwnerName, repo.Name) } func (repo *Repository) GitRepoManagedID() string { @@ -48,9 +29,9 @@ func (repo *Repository) GitRepoManagedID() string { return repoCodeGitRepoManagedID(repo.ID) } -func (repo *Repository) WikiStorageRepo() gitcmd.RepositoryFacade { +func (repo *Repository) WikiStorageRepo() gitrepo.RepositoryFacade { // The wiki repository should have the same object format as the code repository. TODO: old comment, REALLY? Why? id := "repo-wiki-" + strconv.FormatInt(repo.ID, 10) - repoPath := repoWikiGitRepoRelativePath(repo.OwnerName, repo.Name) - return gitcmd.RepositoryManaged(id, repoPath) + repoPath := gitrepo.RepoWikiGitRepoRelativePath(repo.OwnerName, repo.Name) + return gitrepo.RepositoryManaged(id, repoPath) } diff --git a/models/repo/repo_location_test.go b/models/repo/repo_location_test.go index bc74d7d815..7b6c66a23a 100644 --- a/models/repo/repo_location_test.go +++ b/models/repo/repo_location_test.go @@ -8,6 +8,7 @@ import ( repo_model "gitea.dev/models/repo" "gitea.dev/models/unittest" + "gitea.dev/modules/git/gitrepo" "github.com/stretchr/testify/assert" ) @@ -16,11 +17,11 @@ func TestRepository_GitRepo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - assert.Equal(t, "user2/repo1.git", repo_model.CodeRepoByName(repo.OwnerName, repo.Name).GitRepoLocation()) + assert.Equal(t, "user2/repo1.git", gitrepo.CodeRepoByName(repo.OwnerName, repo.Name).GitRepoLocation()) assert.Equal(t, "user2/repo1.git", repo.CodeStorageRepo().GitRepoLocation()) assert.Equal(t, "repo-1", repo.CodeStorageRepo().GitRepoManagedID()) - assert.Equal(t, "user2/repo1.wiki.git", repo_model.WikiRepoByName(repo.OwnerName, repo.Name).GitRepoLocation()) + assert.Equal(t, "user2/repo1.wiki.git", gitrepo.WikiRepoByName(repo.OwnerName, repo.Name).GitRepoLocation()) assert.Equal(t, "user2/repo1.wiki.git", repo.WikiStorageRepo().GitRepoLocation()) assert.Equal(t, "repo-wiki-1", repo.WikiStorageRepo().GitRepoManagedID()) } diff --git a/modules/git/archive.go b/modules/git/archive.go index c5e3451c48..159db42011 100644 --- a/modules/git/archive.go +++ b/modules/git/archive.go @@ -13,6 +13,7 @@ import ( "strings" "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/setting" ) @@ -48,7 +49,7 @@ func CreateBundle(ctx context.Context, repo RepositoryFacade, commit string, out } defer cleanup() - env := append(os.Environ(), "GIT_OBJECT_DIRECTORY="+filepath.Join(gitcmd.RepoLocalPath(repo), "objects")) + env := append(os.Environ(), "GIT_OBJECT_DIRECTORY="+filepath.Join(gitrepo.RepoLocalPath(repo), "objects")) gitTmpCmd := func() *gitcmd.Command { return gitcmd.NewCommand().WithDir(tmpDir).WithEnv(env) } diff --git a/modules/git/catfile_batch.go b/modules/git/catfile_batch.go index f3e71f3085..1d8b6dd9c2 100644 --- a/modules/git/catfile_batch.go +++ b/modules/git/catfile_batch.go @@ -8,7 +8,7 @@ import ( "io" "os" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/util" ) @@ -50,7 +50,7 @@ type CatFileBatchCloser interface { // NewBatch creates a "batch object provider (CatFileBatch)" for the given repository path to retrieve object info and content efficiently. // 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) + repoPath := gitrepo.RepoLocalPath(repo) if _, err := os.Stat(repoPath); err != nil { return nil, util.NewNotExistErrorf("repo %q doesn't exist", repo.LogString()) } diff --git a/modules/git/catfile_batch_test.go b/modules/git/catfile_batch_test.go index 955782bc3c..754da557a2 100644 --- a/modules/git/catfile_batch_test.go +++ b/modules/git/catfile_batch_test.go @@ -9,7 +9,7 @@ import ( "path/filepath" "testing" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/test" "github.com/stretchr/testify/assert" @@ -26,10 +26,10 @@ func TestCatFileBatch(t *testing.T) { func testCatFileBatch(t *testing.T) { repo1Path, _ := filepath.Abs(filepath.Join(testReposDir, "repo1_bare")) - repo1 := gitcmd.RepositoryUnmanaged(repo1Path) + repo1 := gitrepo.RepositoryUnmanaged(repo1Path) t.Run("CorruptedGitRepo", func(t *testing.T) { tmpDir := t.TempDir() - batch, err := NewBatch(t.Context(), gitcmd.RepositoryUnmanaged(tmpDir)) + batch, err := NewBatch(t.Context(), gitrepo.RepositoryUnmanaged(tmpDir)) // as long as the directory exists, no error, because we can't really know whether the git repo is valid until we run commands require.NoError(t, err) defer batch.Close() diff --git a/modules/git/clone.go b/modules/git/clone.go index 9c30a0cbfe..c4b8ab9f12 100644 --- a/modules/git/clone.go +++ b/modules/git/clone.go @@ -6,19 +6,19 @@ package git import ( "context" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" ) // CloneExternalRepo clones an external repository to the managed repository. func CloneExternalRepo(ctx context.Context, fromRemoteURL string, toRepo RepositoryFacade, opts CloneRepoOptions) error { - return Clone(ctx, fromRemoteURL, gitcmd.RepoLocalPath(toRepo), opts) + return Clone(ctx, fromRemoteURL, gitrepo.RepoLocalPath(toRepo), opts) } // CloneRepoToLocal clones a managed repository to a local path. func CloneRepoToLocal(ctx context.Context, fromRepo RepositoryFacade, toLocalPath string, opts CloneRepoOptions) error { - return Clone(ctx, gitcmd.RepoLocalPath(fromRepo), toLocalPath, opts) + return Clone(ctx, gitrepo.RepoLocalPath(fromRepo), toLocalPath, opts) } func CloneManaged(ctx context.Context, fromRepo, toRepo RepositoryFacade, opts CloneRepoOptions) error { - return Clone(ctx, gitcmd.RepoLocalPath(fromRepo), gitcmd.RepoLocalPath(toRepo), opts) + return Clone(ctx, gitrepo.RepoLocalPath(fromRepo), gitrepo.RepoLocalPath(toRepo), opts) } diff --git a/modules/git/fetch.go b/modules/git/fetch.go index e370655fd9..0995aacb5b 100644 --- a/modules/git/fetch.go +++ b/modules/git/fetch.go @@ -7,6 +7,7 @@ import ( "context" "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" ) // FetchRemoteCommit fetches a specific commit and its related objects from a remote @@ -21,7 +22,7 @@ import ( func FetchRemoteCommit(ctx context.Context, repo, remoteRepo RepositoryFacade, commitID string) error { return LockWriteAndDo(ctx, repo, func(ctx context.Context) error { return gitcmd.NewCommand("fetch", "--no-tags"). - AddDynamicArguments(gitcmd.RepoLocalPath(remoteRepo)). + AddDynamicArguments(gitrepo.RepoLocalPath(remoteRepo)). AddDynamicArguments(commitID). WithRepo(repo).Run(ctx) }) diff --git a/modules/git/gitcmd/command.go b/modules/git/gitcmd/command.go index 230f62e597..35454603ac 100644 --- a/modules/git/gitcmd/command.go +++ b/modules/git/gitcmd/command.go @@ -16,6 +16,7 @@ import ( "strings" "time" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/git/internal" //nolint:depguard // only this file can use the internal type CmdArg, other files and packages should use AddXxx functions "gitea.dev/modules/gtprof" "gitea.dev/modules/log" @@ -261,6 +262,11 @@ func (c *Command) WithDir(dir string) *Command { return c } +func (c *Command) WithRepo(repo gitrepo.RepositoryFacade) *Command { + c.gitDir = gitrepo.RepoLocalPath(repo) + return c +} + func (c *Command) WithEnv(env []string) *Command { c.cmdEnv = env return c diff --git a/modules/git/gitrepo/dbrepo.go b/modules/git/gitrepo/dbrepo.go new file mode 100644 index 0000000000..0c555d3e88 --- /dev/null +++ b/modules/git/gitrepo/dbrepo.go @@ -0,0 +1,24 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitrepo + +import "strings" + +func RepoCodeGitRepoRelativePath(ownerName, repoName string) string { + return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git" +} + +func RepoWikiGitRepoRelativePath(ownerName, repoName string) string { + return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".wiki.git" +} + +// CodeRepoByName returns an unmanaged repository facade for the code repository of the given owner and repository name. +// Usually it is used for migration fixes or repository adoption/creation/rename/transfer. +func CodeRepoByName(ownerName, repoName string) RepositoryFacade { + return RepositoryUnmanaged(RepoCodeGitRepoRelativePath(ownerName, repoName)) +} + +func WikiRepoByName(ownerName, repoName string) RepositoryFacade { + return RepositoryUnmanaged(RepoWikiGitRepoRelativePath(ownerName, repoName)) +} diff --git a/modules/git/gitcmd/repo.go b/modules/git/gitrepo/gitrepo.go similarity index 96% rename from modules/git/gitcmd/repo.go rename to modules/git/gitrepo/gitrepo.go index 4e05fda32e..903fd8c770 100644 --- a/modules/git/gitcmd/repo.go +++ b/modules/git/gitrepo/gitrepo.go @@ -1,7 +1,7 @@ // Copyright 2026 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package gitcmd +package gitrepo import ( "path/filepath" @@ -24,11 +24,6 @@ type RepositoryFacade interface { LogString() string } -func (c *Command) WithRepo(repo RepositoryFacade) *Command { - c.gitDir = RepoLocalPath(repo) - return c -} - // RepoLocalPath returns an absolute path for a RepositoryFacade. // TODO: most of the calls to this function should be replaced with a "Repo FS" in the future // to handle file accesses in the git repo (e.g.: read, write, list, remove). diff --git a/modules/git/grep_test.go b/modules/git/grep_test.go index 08cebaf825..2c4c04c9e1 100644 --- a/modules/git/grep_test.go +++ b/modules/git/grep_test.go @@ -7,7 +7,7 @@ import ( "path/filepath" "testing" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/setting" "gitea.dev/modules/test" @@ -79,7 +79,7 @@ func TestGrepSearch(t *testing.T) { assert.NoError(t, err) assert.Empty(t, res) - nonExistingRepo := &Repository{RepositoryBase: RepositoryBase{repoFacade: gitcmd.RepositoryUnmanaged("no-such-git-repo")}} + nonExistingRepo := &Repository{RepositoryBase: RepositoryBase{repoFacade: gitrepo.RepositoryUnmanaged("no-such-git-repo")}} res, err = GrepSearch(t.Context(), nonExistingRepo, "no-such-content", GrepOptions{}) assert.Error(t, err) assert.Empty(t, res) diff --git a/modules/git/hook.go b/modules/git/hook.go index bba8f423a9..f94e6a5295 100644 --- a/modules/git/hook.go +++ b/modules/git/hook.go @@ -11,7 +11,7 @@ import ( "slices" "strings" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/util" ) @@ -41,7 +41,7 @@ type Hook struct { // GetHook returns a Git hook by given name and repository. func GetHook(repo RepositoryFacade, name string) (*Hook, error) { - repoPath := gitcmd.RepoLocalPath(repo) + repoPath := gitrepo.RepoLocalPath(repo) if !IsValidHookName(name) { return nil, ErrNotValidHook } @@ -100,7 +100,7 @@ func (h *Hook) Update() error { // ListHooks returns a list of Git hooks of given repository. func ListHooks(repo RepositoryFacade) (_ []*Hook, err error) { - exist, err := util.IsDir(filepath.Join(gitcmd.RepoLocalPath(repo), "hooks")) + exist, err := util.IsDir(filepath.Join(gitrepo.RepoLocalPath(repo), "hooks")) if err != nil { return nil, err } else if !exist { diff --git a/modules/git/hooks.go b/modules/git/hooks.go index d4084bd09e..d852087147 100644 --- a/modules/git/hooks.go +++ b/modules/git/hooks.go @@ -10,7 +10,7 @@ import ( "path/filepath" "runtime" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/setting" "gitea.dev/modules/util" ) @@ -109,7 +109,7 @@ done // CreateDelegateHooks creates all the hooks scripts for the repo func CreateDelegateHooks(_ context.Context, repo RepositoryFacade) (err error) { - return createDelegateHooks(filepath.Join(gitcmd.RepoLocalPath(repo), "hooks")) + return createDelegateHooks(filepath.Join(gitrepo.RepoLocalPath(repo), "hooks")) } func createDelegateHooks(hookDir string) (err error) { @@ -176,7 +176,7 @@ func ensureExecutable(filename string) error { // CheckDelegateHooks checks the hooks scripts for the repo func CheckDelegateHooks(_ context.Context, repo RepositoryFacade) ([]string, error) { - return checkDelegateHooks(filepath.Join(gitcmd.RepoLocalPath(repo), "hooks")) + return checkDelegateHooks(filepath.Join(gitrepo.RepoLocalPath(repo), "hooks")) } func checkDelegateHooks(hookDir string) ([]string, error) { diff --git a/modules/git/localfs.go b/modules/git/localfs.go index 9471440fc4..06a0f68a0f 100644 --- a/modules/git/localfs.go +++ b/modules/git/localfs.go @@ -11,59 +11,59 @@ import ( "os" "path/filepath" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/util" ) // IsRepositoryExist returns true if the repository directory exists in the disk func IsRepositoryExist(ctx context.Context, repo RepositoryFacade) (bool, error) { - return util.IsExist(gitcmd.RepoLocalPath(repo)) + return util.IsExist(gitrepo.RepoLocalPath(repo)) } // DeleteRepository deletes the repository directory from the disk, it will return // nil if the repository does not exist. func DeleteRepository(ctx context.Context, repo RepositoryFacade) error { - return util.RemoveAll(gitcmd.RepoLocalPath(repo)) + return util.RemoveAll(gitrepo.RepoLocalPath(repo)) } // RenameRepository renames a repository's name on disk func RenameRepository(ctx context.Context, repo, newRepo RepositoryFacade) error { - dstDir := gitcmd.RepoLocalPath(newRepo) + dstDir := gitrepo.RepoLocalPath(newRepo) if err := os.MkdirAll(filepath.Dir(dstDir), os.ModePerm); err != nil { return fmt.Errorf("Failed to create dir %s: %w", filepath.Dir(dstDir), err) } - if err := util.Rename(gitcmd.RepoLocalPath(repo), dstDir); err != nil { + if err := util.Rename(gitrepo.RepoLocalPath(repo), dstDir); err != nil { return fmt.Errorf("rename repository directory: %w", err) } return nil } func InitRepository(ctx context.Context, repo RepositoryFacade, objectFormatName string) error { - return InitRepositoryLocal(ctx, gitcmd.RepoLocalPath(repo), true, objectFormatName) + return InitRepositoryLocal(ctx, gitrepo.RepoLocalPath(repo), true, objectFormatName) } func GetRepoFS(repo RepositoryFacade) fs.FS { - return os.DirFS(gitcmd.RepoLocalPath(repo)) + return os.DirFS(gitrepo.RepoLocalPath(repo)) } func IsRepoFileExist(ctx context.Context, repo RepositoryFacade, relativeFilePath string) (bool, error) { - absoluteFilePath := filepath.Join(gitcmd.RepoLocalPath(repo), relativeFilePath) + absoluteFilePath := filepath.Join(gitrepo.RepoLocalPath(repo), relativeFilePath) return util.IsExist(absoluteFilePath) } func IsRepoDirExist(ctx context.Context, repo RepositoryFacade, relativeDirPath string) (bool, error) { - absoluteDirPath := filepath.Join(gitcmd.RepoLocalPath(repo), relativeDirPath) + absoluteDirPath := filepath.Join(gitrepo.RepoLocalPath(repo), relativeDirPath) return util.IsDir(absoluteDirPath) } func RemoveRepoFileOrDir(ctx context.Context, repo RepositoryFacade, relativeFileOrDirPath string) error { - absoluteFilePath := filepath.Join(gitcmd.RepoLocalPath(repo), relativeFileOrDirPath) + absoluteFilePath := filepath.Join(gitrepo.RepoLocalPath(repo), relativeFileOrDirPath) return util.Remove(absoluteFilePath) } func CreateRepoFile(ctx context.Context, repo RepositoryFacade, relativeFilePath string) (io.WriteCloser, error) { - absoluteFilePath := filepath.Join(gitcmd.RepoLocalPath(repo), relativeFilePath) + absoluteFilePath := filepath.Join(gitrepo.RepoLocalPath(repo), relativeFilePath) if err := os.MkdirAll(filepath.Dir(absoluteFilePath), os.ModePerm); err != nil { return nil, err } diff --git a/modules/git/main_test.go b/modules/git/main_test.go index 85e7a983e9..78a95c637f 100644 --- a/modules/git/main_test.go +++ b/modules/git/main_test.go @@ -7,17 +7,17 @@ import ( "path/filepath" "testing" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" ) const testReposDir = "tests/repos/" -func mockRepository(repoPath string) gitcmd.RepositoryFacade { +func mockRepository(repoPath string) RepositoryFacade { if !filepath.IsAbs(repoPath) { // resolve repository path relative to the unit test fixture directory repoPath, _ = filepath.Abs(filepath.Join(testReposDir, repoPath)) } - return gitcmd.RepositoryUnmanaged(repoPath) + return gitrepo.RepositoryUnmanaged(repoPath) } func TestMain(m *testing.M) { diff --git a/modules/git/push.go b/modules/git/push.go index 1c050166f0..103f5cbe83 100644 --- a/modules/git/push.go +++ b/modules/git/push.go @@ -6,22 +6,22 @@ package git import ( "context" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" ) // PushToExternal pushes a managed repository to an external remote. func PushToExternal(ctx context.Context, repo RepositoryFacade, opts PushOptions) error { - return Push(ctx, gitcmd.RepoLocalPath(repo), opts) + return Push(ctx, gitrepo.RepoLocalPath(repo), opts) } // PushManaged pushes from one managed repository to another managed repository. func PushManaged(ctx context.Context, fromRepo, toRepo RepositoryFacade, opts PushOptions) error { - opts.Remote = gitcmd.RepoLocalPath(toRepo) - return Push(ctx, gitcmd.RepoLocalPath(fromRepo), opts) + opts.Remote = gitrepo.RepoLocalPath(toRepo) + return Push(ctx, gitrepo.RepoLocalPath(fromRepo), opts) } // PushFromLocal pushes from a local path to a managed repository. func PushFromLocal(ctx context.Context, fromLocalPath string, toRepo RepositoryFacade, opts PushOptions) error { - opts.Remote = gitcmd.RepoLocalPath(toRepo) + opts.Remote = gitrepo.RepoLocalPath(toRepo) return Push(ctx, fromLocalPath, opts) } diff --git a/modules/git/repo.go b/modules/git/repo.go index 8cd5ff3540..e9cf974381 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -17,12 +17,13 @@ import ( "time" "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/proxy" "gitea.dev/modules/setting" "gitea.dev/modules/util" ) -type RepositoryFacade = gitcmd.RepositoryFacade +type RepositoryFacade = gitrepo.RepositoryFacade type RepositoryBase struct { LastCommitCache *LastCommitCache @@ -36,7 +37,7 @@ type RepositoryBase struct { catFileBatchInUse bool } -var _ gitcmd.RepositoryFacade = (*Repository)(nil) +var _ RepositoryFacade = (*Repository)(nil) func (repo *Repository) GitRepoManagedID() string { return repo.repoFacade.GitRepoManagedID() @@ -51,7 +52,7 @@ func (repo *Repository) LogString() string { } func OpenRepository(repo RepositoryFacade) (*Repository, error) { - repoPath := gitcmd.RepoLocalPath(repo) + repoPath := gitrepo.RepoLocalPath(repo) exist, err := util.IsDir(repoPath) if err != nil { return nil, err @@ -77,7 +78,7 @@ func OpenRepositoryLocal(localPath string) (_ *Repository, err error) { return nil, err } } - return OpenRepository(gitcmd.RepositoryUnmanaged(localPath)) + return OpenRepository(gitrepo.RepositoryUnmanaged(localPath)) } func (repo *Repository) Close() error { @@ -130,7 +131,7 @@ func InitRepositoryLocal(ctx context.Context, localRepoPath string, bare bool, o // IsEmpty Check if repository is empty. func (repo *Repository) IsEmpty(ctx context.Context) (bool, error) { stdout, _, err := gitcmd.NewCommand(). - AddOptionFormat("--git-dir=%s", gitcmd.RepoLocalPath(repo)). // TODO: all git commands should use "--git-dir" or "GIT_DIR=..." + AddOptionFormat("--git-dir=%s", gitrepo.RepoLocalPath(repo)). // TODO: all git commands should use "--git-dir" or "GIT_DIR=..." AddArguments("rev-list", "-n", "1", "--all"). WithRepo(repo). RunStdString(ctx) diff --git a/modules/git/repo_base_gogit.go b/modules/git/repo_base_gogit.go index 82929014fa..ef282af912 100644 --- a/modules/git/repo_base_gogit.go +++ b/modules/git/repo_base_gogit.go @@ -9,7 +9,7 @@ package git import ( "path/filepath" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/setting" "github.com/go-git/go-billy/v5" @@ -30,7 +30,7 @@ type Repository struct { } func openRepositoryInternal(gitRepo *Repository) error { - repoPath := gitcmd.RepoLocalPath(gitRepo) + repoPath := gitrepo.RepoLocalPath(gitRepo) fs := osfs.New(repoPath) _, err := fs.Stat(".git") if err == nil { diff --git a/modules/git/repo_commitgraph_gogit.go b/modules/git/repo_commitgraph_gogit.go index 2c025881a3..ecfda61be2 100644 --- a/modules/git/repo_commitgraph_gogit.go +++ b/modules/git/repo_commitgraph_gogit.go @@ -10,7 +10,7 @@ import ( "os" "path/filepath" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/log" commitgraph "github.com/go-git/go-git/v5/plumbing/format/commitgraph/v2" @@ -19,7 +19,7 @@ import ( // CommitNodeIndex returns the index for walking commit graph func (repo *Repository) CommitNodeIndex() (_ cgobject.CommitNodeIndex, closer func()) { - indexPath := filepath.Join(gitcmd.RepoLocalPath(repo), "objects", "info", "commit-graph") + indexPath := filepath.Join(gitrepo.RepoLocalPath(repo), "objects", "info", "commit-graph") file, err := os.Open(indexPath) if err == nil { var index commitgraph.Index diff --git a/modules/git/size.go b/modules/git/size.go index 480db26b55..c7e0f80888 100644 --- a/modules/git/size.go +++ b/modules/git/size.go @@ -7,7 +7,7 @@ import ( "os" "path/filepath" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" ) const notRegularFileMode = os.ModeSymlink | os.ModeNamedPipe | os.ModeSocket | os.ModeDevice | os.ModeCharDevice | os.ModeIrregular @@ -15,7 +15,7 @@ const notRegularFileMode = os.ModeSymlink | os.ModeNamedPipe | os.ModeSocket | o // CalcRepositorySize returns the disk consumption for a given path func CalcRepositorySize(repo RepositoryFacade) (int64, error) { var size int64 - err := filepath.WalkDir(gitcmd.RepoLocalPath(repo), func(_ string, entry os.DirEntry, err error) error { + err := filepath.WalkDir(gitrepo.RepoLocalPath(repo), func(_ string, entry os.DirEntry, err error) error { if os.IsNotExist(err) { // ignore the error because some files (like temp/lock file) may be deleted during traversing. return nil } else if err != nil { diff --git a/modules/git/submodule.go b/modules/git/submodule.go index 8beebebb6e..9cf81e5ee5 100644 --- a/modules/git/submodule.go +++ b/modules/git/submodule.go @@ -19,7 +19,7 @@ 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, repo gitcmd.RepositoryFacade) (submoduleCommits []TemplateSubmoduleCommit, _ error) { +func GetTemplateSubmoduleCommits(ctx context.Context, repo RepositoryFacade) (submoduleCommits []TemplateSubmoduleCommit, _ error) { cmd := gitcmd.NewCommand("ls-tree", "-r", "--", "HEAD") stdoutReader, stdoutReaderClose := cmd.MakeStdoutPipe() defer stdoutReaderClose() diff --git a/modules/repository/temp.go b/modules/repository/temp.go index 4441decd34..b04906ece6 100644 --- a/modules/repository/temp.go +++ b/modules/repository/temp.go @@ -8,7 +8,7 @@ import ( "fmt" "gitea.dev/modules/git" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/setting" ) @@ -19,6 +19,6 @@ func CreateTemporaryGitRepo(prefix string) (tmpPath string, tmpRepo git.Reposito if err != nil { return "", nil, nil, fmt.Errorf("failed to create temp dir with prefix %s: %w", tmpNamePrefix, err) } - tmpRepo = gitcmd.RepositoryUnmanaged(tmpPath) + tmpRepo = gitrepo.RepositoryUnmanaged(tmpPath) return tmpPath, tmpRepo, cancel, nil } diff --git a/routers/api/v1/admin/adopt.go b/routers/api/v1/admin/adopt.go index c5d6a53a27..5b65e51a92 100644 --- a/routers/api/v1/admin/adopt.go +++ b/routers/api/v1/admin/adopt.go @@ -9,6 +9,7 @@ import ( repo_model "gitea.dev/models/repo" user_model "gitea.dev/models/user" "gitea.dev/modules/git" + "gitea.dev/modules/git/gitrepo" "gitea.dev/routers/api/v1/utils" "gitea.dev/services/context" repo_service "gitea.dev/services/repository" @@ -99,7 +100,7 @@ func AdoptRepository(ctx *context.APIContext) { ctx.APIErrorInternal(err) return } - exist, err := git.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, repoName)) + exist, err := git.IsRepositoryExist(ctx, gitrepo.CodeRepoByName(ctxUser.Name, repoName)) if err != nil { ctx.APIErrorInternal(err) return @@ -161,7 +162,7 @@ func DeleteUnadoptedRepository(ctx *context.APIContext) { ctx.APIErrorInternal(err) return } - exist, err := git.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, repoName)) + exist, err := git.IsRepositoryExist(ctx, gitrepo.CodeRepoByName(ctxUser.Name, repoName)) if err != nil { ctx.APIErrorInternal(err) return diff --git a/routers/private/serv.go b/routers/private/serv.go index b9fa76ce85..61a91a4d99 100644 --- a/routers/private/serv.go +++ b/routers/private/serv.go @@ -14,7 +14,7 @@ import ( "gitea.dev/models/unit" user_model "gitea.dev/models/user" "gitea.dev/modules/git" - "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/log" "gitea.dev/modules/private" "gitea.dev/modules/setting" @@ -320,7 +320,7 @@ func ServCommand(ctx *context.PrivateContext) { } gitRepo := util.Iif(results.IsWiki, repo.WikiStorageRepo(), repo.CodeStorageRepo()) - results.RepoStoragePath = gitcmd.RepoLocalPath(gitRepo) + results.RepoStoragePath = gitrepo.RepoLocalPath(gitRepo) log.Debug("Serv Results: %+v", results) ctx.JSON(http.StatusOK, results) // We will update the keys in a different call. diff --git a/routers/web/admin/repos.go b/routers/web/admin/repos.go index 2e751c6a7f..c9f5b8d3b7 100644 --- a/routers/web/admin/repos.go +++ b/routers/web/admin/repos.go @@ -12,6 +12,7 @@ import ( repo_model "gitea.dev/models/repo" user_model "gitea.dev/models/user" "gitea.dev/modules/git" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/log" "gitea.dev/modules/setting" "gitea.dev/modules/templates" @@ -134,7 +135,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) { ctx.ServerError("IsRepositoryExist", err) return } - exist, err := git.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, repoName)) + exist, err := git.IsRepositoryExist(ctx, gitrepo.CodeRepoByName(ctxUser.Name, repoName)) if err != nil { ctx.ServerError("IsDir", err) return diff --git a/routers/web/user/setting/adopt.go b/routers/web/user/setting/adopt.go index eed0b8c36c..be6057fde7 100644 --- a/routers/web/user/setting/adopt.go +++ b/routers/web/user/setting/adopt.go @@ -6,6 +6,7 @@ package setting import ( repo_model "gitea.dev/models/repo" "gitea.dev/modules/git" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/setting" "gitea.dev/services/context" repo_service "gitea.dev/services/repository" @@ -32,7 +33,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) { return } - exist, err := git.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, dir)) + exist, err := git.IsRepositoryExist(ctx, gitrepo.CodeRepoByName(ctxUser.Name, dir)) if err != nil { ctx.ServerError("IsDir", err) return diff --git a/services/migrations/dump.go b/services/migrations/dump.go index 752d229615..fdbb6ce00b 100644 --- a/services/migrations/dump.go +++ b/services/migrations/dump.go @@ -18,6 +18,7 @@ import ( user_model "gitea.dev/models/user" "gitea.dev/modules/git" "gitea.dev/modules/git/gitcmd" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/log" base "gitea.dev/modules/migration" "gitea.dev/modules/repository" @@ -161,7 +162,7 @@ func (g *RepositoryDumper) CreateRepo(ctx context.Context, repo *base.Repository return fmt.Errorf("clone code: %w", err) } - repoLocal := gitcmd.RepositoryUnmanaged(repoAbsPath) + repoLocal := gitrepo.RepositoryUnmanaged(repoAbsPath) if err := git.WriteCommitGraph(ctx, repoLocal); err != nil { return err } @@ -176,7 +177,7 @@ func (g *RepositoryDumper) CreateRepo(ctx context.Context, repo *base.Repository if err := os.MkdirAll(wikiAbsPath, os.ModePerm); err != nil { return fmt.Errorf("failed to create %s: %w", wikiAbsPath, err) } - wikiLocal := gitcmd.RepositoryUnmanaged(wikiAbsPath) + wikiLocal := gitrepo.RepositoryUnmanaged(wikiAbsPath) if err := git.Clone(ctx, wikiRemotePath, wikiAbsPath, git.CloneRepoOptions{ Mirror: true, Quiet: true, diff --git a/services/repository/adopt.go b/services/repository/adopt.go index eef625fe73..c7a83d489e 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -17,6 +17,7 @@ import ( user_model "gitea.dev/models/user" "gitea.dev/modules/container" "gitea.dev/modules/git" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/glob" "gitea.dev/modules/graceful" "gitea.dev/modules/log" @@ -213,7 +214,7 @@ func DeleteUnadoptedRepository(ctx context.Context, doer, u *user_model.User, re return err } - codeRepo := repo_model.CodeRepoByName(u.Name, repoName) + codeRepo := gitrepo.CodeRepoByName(u.Name, repoName) exist, err := git.IsRepositoryExist(ctx, codeRepo) if err != nil { log.Error("Unable to check if repo %s/%s exists. Error: %v", u.Name, repoName, err) diff --git a/services/repository/repository.go b/services/repository/repository.go index 8a9bb520d9..c7686021d0 100644 --- a/services/repository/repository.go +++ b/services/repository/repository.go @@ -19,6 +19,7 @@ import ( "gitea.dev/models/unit" user_model "gitea.dev/models/user" git2 "gitea.dev/modules/git" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/graceful" issue_indexer "gitea.dev/modules/indexer/issues" "gitea.dev/modules/log" @@ -331,7 +332,7 @@ func CheckCreateRepository(ctx context.Context, doer, owner *user_model.User, na } else if has { return repo_model.ErrRepoAlreadyExist{Uname: owner.Name, Name: name} } - repo := repo_model.CodeRepoByName(owner.Name, name) + repo := gitrepo.CodeRepoByName(owner.Name, name) isExist, err := git2.IsRepositoryExist(ctx, repo) if err != nil { log.Error("Unable to check if repo %s/%s exists, error: %v", owner.Name, name, err) diff --git a/services/repository/transfer.go b/services/repository/transfer.go index 70f89a4d71..92825cb45b 100644 --- a/services/repository/transfer.go +++ b/services/repository/transfer.go @@ -18,6 +18,7 @@ import ( repo_model "gitea.dev/models/repo" user_model "gitea.dev/models/user" "gitea.dev/modules/git" + "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/globallock" "gitea.dev/modules/log" "gitea.dev/modules/util" @@ -94,7 +95,7 @@ func isRepositoryModelOrDirExist(ctx context.Context, u *user_model.User, repoNa if err != nil { return false, err } - repo := repo_model.CodeRepoByName(u.Name, repoName) + repo := gitrepo.CodeRepoByName(u.Name, repoName) isExist, err := git.IsRepositoryExist(ctx, repo) return has || isExist, err } @@ -117,16 +118,16 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName if repoRenamed { // revert the rename - from := repo_model.CodeRepoByName(newOwnerName, repo.Name) - to := repo_model.CodeRepoByName(oldOwnerName, repo.Name) + from := gitrepo.CodeRepoByName(newOwnerName, repo.Name) + to := gitrepo.CodeRepoByName(oldOwnerName, repo.Name) if err := git.RenameRepository(ctx, from, to); err != nil { log.Error("Unable to revert repository %s/%s to %s/%s: %v", newOwnerName, repo.Name, oldOwnerName, repo.Name, err) } } if wikiRenamed { - from := repo_model.WikiRepoByName(newOwnerName, repo.Name) - to := repo_model.WikiRepoByName(oldOwnerName, repo.Name) + from := gitrepo.WikiRepoByName(newOwnerName, repo.Name) + to := gitrepo.WikiRepoByName(oldOwnerName, repo.Name) if err := git.RenameRepository(ctx, from, to); err != nil { log.Error("Unable to revert wiki repository %s/%s to %s/%s: %v", newOwnerName, repo.Name, oldOwnerName, repo.Name, err) } @@ -303,20 +304,20 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName } // Rename remote repository to new path and delete local copy. - oldCodeRepo := repo_model.CodeRepoByName(oldOwner.Name, repo.Name) - newCodeRepo := repo_model.CodeRepoByName(newOwner.Name, repo.Name) + oldCodeRepo := gitrepo.CodeRepoByName(oldOwner.Name, repo.Name) + newCodeRepo := gitrepo.CodeRepoByName(newOwner.Name, repo.Name) if err := git.RenameRepository(ctx, oldCodeRepo, newCodeRepo); err != nil { return fmt.Errorf("rename repository directory: %w", err) } repoRenamed = true // Rename remote wiki repository to new path and delete local copy. - oldWikiRepo := repo_model.WikiRepoByName(oldOwner.Name, repo.Name) + oldWikiRepo := gitrepo.WikiRepoByName(oldOwner.Name, repo.Name) if isExist, err := git.IsRepositoryExist(ctx, oldWikiRepo); err != nil { log.Error("Unable to check if wiki of repo %s/%s exists. Error: %v", oldOwner.Name, repo.Name, err) return err } else if isExist { - newWikiRepo := repo_model.WikiRepoByName(newOwner.Name, repo.Name) + newWikiRepo := gitrepo.WikiRepoByName(newOwner.Name, repo.Name) if err := git.RenameRepository(ctx, oldWikiRepo, newWikiRepo); err != nil { return fmt.Errorf("rename repository wiki: %w", err) } @@ -376,13 +377,13 @@ func changeRepositoryName(ctx context.Context, repo *repo_model.Repository, newR } } - newCodeRepo := repo_model.CodeRepoByName(repo.OwnerName, newRepoName) + newCodeRepo := gitrepo.CodeRepoByName(repo.OwnerName, newRepoName) if err = git.RenameRepository(ctx, repo, newCodeRepo); err != nil { return fmt.Errorf("rename repository directory: %w", err) } if HasWiki(ctx, repo) { - newWikiRepo := repo_model.WikiRepoByName(repo.OwnerName, newRepoName) + newWikiRepo := gitrepo.WikiRepoByName(repo.OwnerName, newRepoName) if err = git.RenameRepository(ctx, repo.WikiStorageRepo(), newWikiRepo); err != nil { return fmt.Errorf("rename repository wiki: %w", err) }