From 55cc649d3d293a13eee7a56ca1744577c08b4e6c Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 14 Mar 2025 11:38:55 -0700 Subject: [PATCH] Add abstraction layer to delete repository from disk (#33879) Extract from #28966 Follow #33874 --- modules/gitrepo/gitrepo.go | 21 ++++++++++++++++++++- routers/web/repo/blame.go | 9 +++++---- services/repository/create.go | 2 +- services/repository/delete.go | 10 ++++++++-- services/repository/fork.go | 2 +- services/repository/transfer.go | 4 ++-- 6 files changed, 37 insertions(+), 11 deletions(-) diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go index c3b412fd83..5e2ec9ed1e 100644 --- a/modules/gitrepo/gitrepo.go +++ b/modules/gitrepo/gitrepo.go @@ -5,6 +5,7 @@ package gitrepo import ( "context" + "fmt" "io" "path/filepath" "strings" @@ -20,8 +21,12 @@ type Repository interface { GetOwnerName() string } +func absPath(owner, name string) string { + return filepath.Join(setting.RepoRootPath, strings.ToLower(owner), strings.ToLower(name)+".git") +} + func repoPath(repo Repository) string { - return filepath.Join(setting.RepoRootPath, strings.ToLower(repo.GetOwnerName()), strings.ToLower(repo.GetName())+".git") + return absPath(repo.GetOwnerName(), repo.GetName()) } func wikiPath(repo Repository) string { @@ -74,3 +79,17 @@ func RepositoryFromRequestContextOrOpen(ctx reqctx.RequestContext, repo Reposito func IsRepositoryExist(ctx context.Context, repo Repository) (bool, error) { return util.IsExist(repoPath(repo)) } + +// DeleteRepository deletes the repository directory from the disk +func DeleteRepository(ctx context.Context, repo Repository) error { + return util.RemoveAll(repoPath(repo)) +} + +// RenameRepository renames a repository's name on disk +func RenameRepository(ctx context.Context, repo Repository, newName string) error { + newRepoPath := absPath(repo.GetOwnerName(), newName) + if err := util.Rename(repoPath(repo), newRepoPath); err != nil { + return fmt.Errorf("rename repository directory: %w", err) + } + return nil +} diff --git a/routers/web/repo/blame.go b/routers/web/repo/blame.go index e79029a55e..2da5acd299 100644 --- a/routers/web/repo/blame.go +++ b/routers/web/repo/blame.go @@ -11,6 +11,7 @@ import ( "strconv" "strings" + repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/charset" "code.gitea.io/gitea/modules/git" @@ -105,7 +106,7 @@ func RefBlame(ctx *context.Context) { bypassBlameIgnore, _ := strconv.ParseBool(ctx.FormString("bypass-blame-ignore")) - result, err := performBlame(ctx, ctx.Repo.Repository.RepoPath(), ctx.Repo.Commit, fileName, bypassBlameIgnore) + result, err := performBlame(ctx, ctx.Repo.Repository, ctx.Repo.Commit, fileName, bypassBlameIgnore) if err != nil { ctx.NotFound(err) return @@ -130,10 +131,10 @@ type blameResult struct { FaultyIgnoreRevsFile bool } -func performBlame(ctx *context.Context, repoPath string, commit *git.Commit, file string, bypassBlameIgnore bool) (*blameResult, error) { +func performBlame(ctx *context.Context, repo *repo_model.Repository, commit *git.Commit, file string, bypassBlameIgnore bool) (*blameResult, error) { objectFormat := ctx.Repo.GetObjectFormat() - blameReader, err := git.CreateBlameReader(ctx, objectFormat, repoPath, commit, file, bypassBlameIgnore) + blameReader, err := git.CreateBlameReader(ctx, objectFormat, repo.RepoPath(), commit, file, bypassBlameIgnore) if err != nil { return nil, err } @@ -149,7 +150,7 @@ func performBlame(ctx *context.Context, repoPath string, commit *git.Commit, fil if len(r.Parts) == 0 && r.UsesIgnoreRevs { // try again without ignored revs - blameReader, err = git.CreateBlameReader(ctx, objectFormat, repoPath, commit, file, true) + blameReader, err = git.CreateBlameReader(ctx, objectFormat, repo.RepoPath(), commit, file, true) if err != nil { return nil, err } diff --git a/services/repository/create.go b/services/repository/create.go index 62b5931fd9..1a6a68b35a 100644 --- a/services/repository/create.go +++ b/services/repository/create.go @@ -277,7 +277,7 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt } if err = initRepository(ctx, doer, repo, opts); err != nil { - if err2 := util.RemoveAll(repo.RepoPath()); err2 != nil { + if err2 := gitrepo.DeleteRepository(ctx, repo); err2 != nil { log.Error("initRepository: %v", err) return fmt.Errorf( "delete repo directory %s/%s failed(2): %v", u.Name, repo.Name, err2) diff --git a/services/repository/delete.go b/services/repository/delete.go index 3b953d3ec7..ff74a20817 100644 --- a/services/repository/delete.go +++ b/services/repository/delete.go @@ -23,6 +23,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/models/webhook" actions_module "code.gitea.io/gitea/modules/actions" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/storage" @@ -289,8 +290,13 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID // we delete the file but the database rollback, the repository will be broken. // Remove repository files. - repoPath := repo.RepoPath() - system_model.RemoveAllWithNotice(ctx, "Delete repository files", repoPath) + if err := gitrepo.DeleteRepository(ctx, repo); err != nil { + desc := fmt.Sprintf("Delete 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 wiki files if repo.HasWiki() { diff --git a/services/repository/fork.go b/services/repository/fork.go index 1bd4d4a13b..ec6ba56ddf 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -116,7 +116,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork // As the transaction will be failed and hence database changes will be destroyed we only need // to delete the related repository on the filesystem - if errDelete := util.RemoveAll(repo.RepoPath()); errDelete != nil { + if errDelete := gitrepo.DeleteRepository(ctx, repo); errDelete != nil { log.Error("Failed to remove fork repo") } } diff --git a/services/repository/transfer.go b/services/repository/transfer.go index bd3bf326b4..3940b2a142 100644 --- a/services/repository/transfer.go +++ b/services/repository/transfer.go @@ -17,6 +17,7 @@ import ( project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/globallock" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/util" @@ -335,8 +336,7 @@ func changeRepositoryName(ctx context.Context, repo *repo_model.Repository, newR } } - newRepoPath := repo_model.RepoPath(repo.Owner.Name, newRepoName) - if err = util.Rename(repo.RepoPath(), newRepoPath); err != nil { + if err = gitrepo.RenameRepository(ctx, repo, newRepoName); err != nil { return fmt.Errorf("rename repository directory: %w", err) }