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.
This commit is contained in:
+3
-3
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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).
|
||||
@@ -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)
|
||||
|
||||
+3
-3
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+11
-11
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+5
-5
@@ -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)
|
||||
}
|
||||
|
||||
+6
-5
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-2
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user