0
0
mirror of https://github.com/go-gitea/gitea.git synced 2025-06-05 23:06:48 +02:00

Merge 024d52840b3e5939db794c897e20f8a70dd44bb9 into 0cec4b84e2e2385d33cd19351f8a9e098a29ecc2

This commit is contained in:
Lunny Xiao 2025-05-29 08:22:42 +08:00 committed by GitHub
commit d33a93a7ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 119 additions and 44 deletions

View File

@ -229,6 +229,10 @@ func RelativePath(ownerName, repoName string) string {
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git" return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git"
} }
func RelativeWikiPath(ownerName, repoName string) string {
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".wiki.git"
}
// RelativePath should be an unix style path like username/reponame.git // RelativePath should be an unix style path like username/reponame.git
func (repo *Repository) RelativePath() string { func (repo *Repository) RelativePath() string {
return RelativePath(repo.OwnerName, repo.Name) return RelativePath(repo.OwnerName, repo.Name)
@ -242,7 +246,7 @@ func (sr StorageRepo) RelativePath() string {
} }
func (repo *Repository) WikiStorageRepo() StorageRepo { func (repo *Repository) WikiStorageRepo() StorageRepo {
return StorageRepo(strings.ToLower(repo.OwnerName) + "/" + strings.ToLower(repo.Name) + ".wiki.git") return StorageRepo(RelativeWikiPath(repo.OwnerName, repo.Name))
} }
// SanitizedOriginalURL returns a sanitized OriginalURL // SanitizedOriginalURL returns a sanitized OriginalURL

View File

@ -11,7 +11,6 @@ import (
"strings" "strings"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
) )
@ -86,12 +85,3 @@ func WikiPath(userName, repoName string) string {
func (repo *Repository) WikiPath() string { func (repo *Repository) WikiPath() string {
return WikiPath(repo.OwnerName, repo.Name) return WikiPath(repo.OwnerName, repo.Name)
} }
// HasWiki returns true if repository has wiki.
func (repo *Repository) HasWiki() bool {
isDir, err := util.IsDir(repo.WikiPath())
if err != nil {
log.Error("Unable to check if %s is a directory: %v", repo.WikiPath(), err)
}
return isDir
}

View File

@ -9,6 +9,7 @@ import (
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -39,7 +40,12 @@ func TestRepository_WikiPath(t *testing.T) {
func TestRepository_HasWiki(t *testing.T) { func TestRepository_HasWiki(t *testing.T) {
unittest.PrepareTestEnv(t) unittest.PrepareTestEnv(t)
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
assert.True(t, repo1.HasWiki()) exist, err := gitrepo.IsRepositoryExist(t.Context(), repo1.WikiStorageRepo())
assert.NoError(t, err)
assert.True(t, exist)
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
assert.False(t, repo2.HasWiki()) exist, err = gitrepo.IsRepositoryExist(t.Context(), repo2.WikiStorageRepo())
assert.NoError(t, err)
assert.False(t, exist)
} }

View File

@ -556,7 +556,12 @@ func Wiki(ctx *context.Context) {
return return
} }
if !ctx.Repo.Repository.HasWiki() { hasWiki, err := gitrepo.IsRepositoryExist(ctx, ctx.Repo.Repository.WikiStorageRepo())
if err != nil {
ctx.ServerError("IsWikiRepositoryExist", err)
return
}
if !hasWiki {
ctx.Data["Title"] = ctx.Tr("repo.wiki") ctx.Data["Title"] = ctx.Tr("repo.wiki")
ctx.HTML(http.StatusOK, tplWikiStart) ctx.HTML(http.StatusOK, tplWikiStart)
return return
@ -597,7 +602,12 @@ func Wiki(ctx *context.Context) {
func WikiRevision(ctx *context.Context) { func WikiRevision(ctx *context.Context) {
ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(unit.TypeWiki) && !ctx.Repo.Repository.IsArchived ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(unit.TypeWiki) && !ctx.Repo.Repository.IsArchived
if !ctx.Repo.Repository.HasWiki() { hasWiki, err := gitrepo.IsRepositoryExist(ctx, ctx.Repo.Repository.WikiStorageRepo())
if err != nil {
ctx.ServerError("IsWikiRepositoryExist", err)
return
}
if !hasWiki {
ctx.Data["Title"] = ctx.Tr("repo.wiki") ctx.Data["Title"] = ctx.Tr("repo.wiki")
ctx.HTML(http.StatusOK, tplWikiStart) ctx.HTML(http.StatusOK, tplWikiStart)
return return
@ -633,7 +643,12 @@ func WikiRevision(ctx *context.Context) {
// WikiPages render wiki pages list page // WikiPages render wiki pages list page
func WikiPages(ctx *context.Context) { func WikiPages(ctx *context.Context) {
if !ctx.Repo.Repository.HasWiki() { hasWiki, err := gitrepo.IsRepositoryExist(ctx, ctx.Repo.Repository.WikiStorageRepo())
if err != nil {
ctx.ServerError("IsWikiRepositoryExist", err)
return
}
if !hasWiki {
ctx.Redirect(ctx.Repo.RepoLink + "/wiki") ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
return return
} }
@ -752,7 +767,12 @@ func WikiRaw(ctx *context.Context) {
func NewWiki(ctx *context.Context) { func NewWiki(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page") ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
if !ctx.Repo.Repository.HasWiki() { hasWiki, err := gitrepo.IsRepositoryExist(ctx, ctx.Repo.Repository.WikiStorageRepo())
if err != nil {
ctx.ServerError("IsWikiRepositoryExist", err)
return
}
if !hasWiki {
ctx.Data["title"] = "Home" ctx.Data["title"] = "Home"
} }
if ctx.FormString("title") != "" { if ctx.FormString("title") != "" {
@ -805,7 +825,12 @@ func NewWikiPost(ctx *context.Context) {
func EditWiki(ctx *context.Context) { func EditWiki(ctx *context.Context) {
ctx.Data["PageIsWikiEdit"] = true ctx.Data["PageIsWikiEdit"] = true
if !ctx.Repo.Repository.HasWiki() { hasWiki, err := gitrepo.IsRepositoryExist(ctx, ctx.Repo.Repository.WikiStorageRepo())
if err != nil {
ctx.ServerError("IsWikiRepositoryExist", err)
return
}
if !hasWiki {
ctx.Redirect(ctx.Repo.RepoLink + "/wiki") ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
return return
} }

View File

@ -241,7 +241,9 @@ func TestDefaultWikiBranch(t *testing.T) {
// repo with no wiki // repo with no wiki
repoWithNoWiki := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) repoWithNoWiki := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
assert.False(t, repoWithNoWiki.HasWiki()) exist, err := gitrepo.IsRepositoryExist(db.DefaultContext, repoWithNoWiki.WikiStorageRepo())
assert.NoError(t, err)
assert.False(t, exist)
assert.NoError(t, wiki_service.ChangeDefaultWikiBranch(db.DefaultContext, repoWithNoWiki, "main")) assert.NoError(t, wiki_service.ChangeDefaultWikiBranch(db.DefaultContext, repoWithNoWiki, "main"))
// repo with wiki // repo with wiki

View File

@ -63,7 +63,9 @@ func TestGiteaUploadRepo(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: user.ID, Name: repoName}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: user.ID, Name: repoName})
assert.True(t, repo.HasWiki()) exist, err := gitrepo.IsRepositoryExist(ctx, repo)
assert.NoError(t, err)
assert.True(t, exist)
assert.Equal(t, repo_model.RepositoryReady, repo.Status) assert.Equal(t, repo_model.RepositoryReady, repo.Status)
milestones, err := db.Find[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{ milestones, err := db.Find[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{

View File

@ -52,7 +52,11 @@ func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error
return err return err
} }
if m.Repo.HasWiki() { hasWiki, err := gitrepo.IsRepositoryExist(ctx, m.Repo.WikiStorageRepo())
if err != nil {
return err
}
if hasWiki {
wikiPath := m.Repo.WikiPath() wikiPath := m.Repo.WikiPath()
wikiRemotePath := repo_module.WikiRemoteURL(ctx, addr) wikiRemotePath := repo_module.WikiRemoteURL(ctx, addr)
// Remove old remote of wiki // Remove old remote of wiki
@ -347,7 +351,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
endpoint := lfs.DetermineEndpoint(remoteURL.String(), m.LFSEndpoint) endpoint := lfs.DetermineEndpoint(remoteURL.String(), m.LFSEndpoint)
lfsClient := lfs.NewClient(endpoint, nil) lfsClient := lfs.NewClient(endpoint, nil)
if err = repo_module.StoreMissingLfsObjectsInRepository(ctx, m.Repo, gitRepo, lfsClient); err != nil { if err = repo_module.StoreMissingLfsObjectsInRepository(ctx, m.Repo, gitRepo, lfsClient); err != nil {
log.Error("SyncMirrors [repo: %-v]: failed to synchronize LFS objects for repository: %v", m.Repo, err) log.Error("SyncMirrors [repo: %-v]: failed to synchronize LFS objects for repository: %v", m.Repo.FullName(), err)
} }
} }
@ -364,10 +368,14 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
log.Trace("SyncMirrors [repo: %-v]: updating size of repository", m.Repo) log.Trace("SyncMirrors [repo: %-v]: updating size of repository", m.Repo)
if err := repo_module.UpdateRepoSize(ctx, m.Repo); err != nil { if err := repo_module.UpdateRepoSize(ctx, m.Repo); err != nil {
log.Error("SyncMirrors [repo: %-v]: failed to update size for mirror repository: %v", m.Repo, err) log.Error("SyncMirrors [repo: %-v]: failed to update size for mirror repository: %v", m.Repo.FullName(), err)
} }
if m.Repo.HasWiki() { hasWiki, err := gitrepo.IsRepositoryExist(ctx, m.Repo.WikiStorageRepo())
if err != nil {
log.Error("SyncMirrors [repo: %-v]: failed to check if wiki repository exists: %v", m.Repo.FullName(), err)
}
if hasWiki {
log.Trace("SyncMirrors [repo: %-v Wiki]: running git remote update...", m.Repo) log.Trace("SyncMirrors [repo: %-v Wiki]: running git remote update...", m.Repo)
stderrBuilder.Reset() stderrBuilder.Reset()
stdoutBuilder.Reset() stdoutBuilder.Reset()

View File

@ -47,7 +47,11 @@ func AddPushMirrorRemote(ctx context.Context, m *repo_model.PushMirror, addr str
return err return err
} }
if m.Repo.HasWiki() { hasWiki, err := gitrepo.IsRepositoryExist(ctx, m.Repo.WikiStorageRepo())
if err != nil {
return err
}
if hasWiki {
wikiRemoteURL := repository.WikiRemoteURL(ctx, addr) wikiRemoteURL := repository.WikiRemoteURL(ctx, addr)
if len(wikiRemoteURL) > 0 { if len(wikiRemoteURL) > 0 {
if err := addRemoteAndConfig(wikiRemoteURL, m.Repo.WikiPath()); err != nil { if err := addRemoteAndConfig(wikiRemoteURL, m.Repo.WikiPath()); err != nil {
@ -68,7 +72,11 @@ func RemovePushMirrorRemote(ctx context.Context, m *repo_model.PushMirror) error
return err return err
} }
if m.Repo.HasWiki() { hasWiki, err := gitrepo.IsRepositoryExist(ctx, m.Repo.WikiStorageRepo())
if err != nil {
return err
}
if hasWiki {
if _, _, err := cmd.RunStdString(ctx, &git.RunOpts{Dir: m.Repo.WikiPath()}); err != nil { if _, _, err := cmd.RunStdString(ctx, &git.RunOpts{Dir: m.Repo.WikiPath()}); err != nil {
// The wiki remote may not exist // The wiki remote may not exist
log.Warn("Wiki Remote[%d] could not be removed: %v", m.ID, err) log.Warn("Wiki Remote[%d] could not be removed: %v", m.ID, err)
@ -183,7 +191,11 @@ func runPushSync(ctx context.Context, m *repo_model.PushMirror) error {
return err return err
} }
if m.Repo.HasWiki() { hasWiki, err := gitrepo.IsRepositoryExist(ctx, m.Repo.WikiStorageRepo())
if err != nil {
return err
}
if hasWiki {
_, err := git.GetRemoteAddress(ctx, m.Repo.WikiPath(), m.RemoteName) _, err := git.GetRemoteAddress(ctx, m.Repo.WikiPath(), m.RemoteName)
if err == nil { if err == nil {
err := performPush(m.Repo, true) err := performPush(m.Repo, true)

View File

@ -314,9 +314,13 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID
} }
} }
// Remove wiki files // Remove wiki files if it exists.
if repo.HasWiki() { if err := gitrepo.DeleteRepository(ctx, repo.WikiStorageRepo()); err != nil {
system_model.RemoveAllWithNotice(ctx, "Delete repository wiki", repo.WikiPath()) desc := fmt.Sprintf("Delete wiki repository files [%s]: %v", repo.FullName(), err)
// Note we use the db.DefaultContext here rather than passing in a context as the context may be cancelled
if err = system_model.CreateNotice(db.DefaultContext, system_model.NoticeRepository, desc); err != nil {
log.Error("CreateRepositoryNotice: %v", err)
}
} }
// Remove archives // Remove archives

View File

@ -32,11 +32,15 @@ func SyncRepositoryHooks(ctx context.Context) error {
} }
if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil { if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
return fmt.Errorf("SyncRepositoryHook: %w", err) return fmt.Errorf("CreateDelegateHooks: %w", err)
} }
if repo.HasWiki() { exist, err := gitrepo.IsRepositoryExist(ctx, repo.WikiStorageRepo())
if err != nil {
return fmt.Errorf("IsRepositoryExist: %w", err)
}
if exist {
if err := gitrepo.CreateDelegateHooks(ctx, repo.WikiStorageRepo()); err != nil { if err := gitrepo.CreateDelegateHooks(ctx, repo.WikiStorageRepo()); err != nil {
return fmt.Errorf("SyncRepositoryHook: %w", err) return fmt.Errorf("CreateDelegateHooks: %w", err)
} }
} }
return nil return nil

View File

@ -276,18 +276,23 @@ func CleanUpMigrateInfo(ctx context.Context, repo *repo_model.Repository) (*repo
if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil { if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
return repo, fmt.Errorf("createDelegateHooks: %w", err) return repo, fmt.Errorf("createDelegateHooks: %w", err)
} }
if repo.HasWiki() {
hasWiki, err := gitrepo.IsRepositoryExist(ctx, repo.WikiStorageRepo())
if err != nil {
return repo, fmt.Errorf("IsWikiRepositoryExist: %w", err)
}
if hasWiki {
if err := gitrepo.CreateDelegateHooks(ctx, repo.WikiStorageRepo()); err != nil { if err := gitrepo.CreateDelegateHooks(ctx, repo.WikiStorageRepo()); err != nil {
return repo, fmt.Errorf("createDelegateHooks.(wiki): %w", err) return repo, fmt.Errorf("createDelegateHooks.(wiki): %w", err)
} }
} }
_, _, err := git.NewCommand("remote", "rm", "origin").RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) _, _, err = git.NewCommand("remote", "rm", "origin").RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()})
if err != nil && !git.IsRemoteNotExistError(err) { if err != nil && !git.IsRemoteNotExistError(err) {
return repo, fmt.Errorf("CleanUpMigrateInfo: %w", err) return repo, fmt.Errorf("CleanUpMigrateInfo: %w", err)
} }
if repo.HasWiki() { if hasWiki {
if err := cleanUpMigrateGitConfig(ctx, repo.WikiPath()); err != nil { if err := cleanUpMigrateGitConfig(ctx, repo.WikiPath()); err != nil {
return repo, fmt.Errorf("cleanUpMigrateGitConfig (wiki): %w", err) return repo, fmt.Errorf("cleanUpMigrateGitConfig (wiki): %w", err)
} }

View File

@ -358,14 +358,14 @@ func changeRepositoryName(ctx context.Context, repo *repo_model.Repository, newR
return fmt.Errorf("rename repository directory: %w", err) return fmt.Errorf("rename repository directory: %w", err)
} }
wikiPath := repo.WikiPath() isExist, err := gitrepo.IsRepositoryExist(ctx, repo.WikiStorageRepo())
isExist, err := util.IsExist(wikiPath)
if err != nil { if err != nil {
log.Error("Unable to check if %s exists. Error: %v", wikiPath, err) log.Error("Unable to check if the wiki of %s exists. Error: %v", repo.FullName(), err)
return err return err
} }
if isExist { if isExist {
if err = util.Rename(wikiPath, repo_model.WikiPath(repo.Owner.Name, newRepoName)); err != nil { if err = gitrepo.RenameRepository(ctx, repo.WikiStorageRepo(), repo_model.StorageRepo(
repo_model.RelativeWikiPath(repo.OwnerName, newRepoName))); err != nil {
return fmt.Errorf("rename repository wiki: %w", err) return fmt.Errorf("rename repository wiki: %w", err)
} }
} }

View File

@ -35,7 +35,9 @@ func getWikiWorkingLockKey(repoID int64) string {
// InitWiki initializes a wiki for repository, // InitWiki initializes a wiki for repository,
// it does nothing when repository already has wiki. // it does nothing when repository already has wiki.
func InitWiki(ctx context.Context, repo *repo_model.Repository) error { func InitWiki(ctx context.Context, repo *repo_model.Repository) error {
if repo.HasWiki() { if exist, err := gitrepo.IsRepositoryExist(ctx, repo.WikiStorageRepo()); err != nil {
return err
} else if exist {
return nil return nil
} }
@ -355,7 +357,14 @@ func DeleteWiki(ctx context.Context, repo *repo_model.Repository) error {
return err return err
} }
system_model.RemoveAllWithNotice(ctx, "Delete repository wiki", repo.WikiPath()) if err := gitrepo.DeleteRepository(ctx, repo.WikiStorageRepo()); err != nil {
desc := fmt.Sprintf("Delete wiki repository files [%s]: %v", repo.FullName(), err)
// Note we use the db.DefaultContext here rather than passing in a context as the context may be cancelled
if err = system_model.CreateNotice(db.DefaultContext, system_model.NoticeRepository, desc); err != nil {
log.Error("CreateRepositoryNotice: %v", err)
}
}
return nil return nil
} }
@ -369,7 +378,9 @@ func ChangeDefaultWikiBranch(ctx context.Context, repo *repo_model.Repository, n
return fmt.Errorf("unable to update database: %w", err) return fmt.Errorf("unable to update database: %w", err)
} }
if !repo.HasWiki() { if exist, err := gitrepo.IsRepositoryExist(ctx, repo.WikiStorageRepo()); err != nil {
return err
} else if !exist {
return nil return nil
} }

View File

@ -149,7 +149,9 @@ func TestRepository_InitWiki(t *testing.T) {
// repo2 does not already have a wiki // repo2 does not already have a wiki
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
assert.NoError(t, InitWiki(git.DefaultContext, repo2)) assert.NoError(t, InitWiki(git.DefaultContext, repo2))
assert.True(t, repo2.HasWiki()) exist, err := gitrepo.IsRepositoryExist(git.DefaultContext, repo2.WikiStorageRepo())
assert.NoError(t, err)
assert.True(t, exist)
} }
func TestRepository_AddWikiPage(t *testing.T) { func TestRepository_AddWikiPage(t *testing.T) {