Cleanup resources when create/adopt/generate repository failed

This commit is contained in:
Lunny Xiao 2024-05-21 14:48:19 +08:00
parent 1007ce764e
commit 2c02c2eb47
No known key found for this signature in database
GPG Key ID: C3B7C91B632F738A
4 changed files with 79 additions and 35 deletions

View File

@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
system_model "code.gitea.io/gitea/models/system"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/git"
@ -48,28 +49,28 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR
IsPrivate: opts.IsPrivate,
IsFsckEnabled: !opts.IsMirror,
CloseIssuesViaCommitInAnyBranch: setting.Repository.DefaultCloseIssuesViaCommitsInAnyBranch,
Status: opts.Status,
Status: repo_model.RepositoryBeingMigrated,
IsEmpty: !opts.AutoInit,
}
repoPath := repo_model.RepoPath(u.Name, repo.Name)
isExist, err := util.IsExist(repoPath)
if err != nil {
log.Error("Unable to check if %s exists. Error: %v", repoPath, err)
return nil, err
}
if !isExist {
return nil, repo_model.ErrRepoNotExist{
OwnerName: u.Name,
Name: repo.Name,
}
}
if err := repo_module.CreateRepositoryByExample(ctx, doer, u, repo, true, false); err != nil {
return nil, err
}
if err := db.WithTx(ctx, func(ctx context.Context) error {
repoPath := repo_model.RepoPath(u.Name, repo.Name)
isExist, err := util.IsExist(repoPath)
if err != nil {
log.Error("Unable to check if %s exists. Error: %v", repoPath, err)
return err
}
if !isExist {
return repo_model.ErrRepoNotExist{
OwnerName: u.Name,
Name: repo.Name,
}
}
if err := repo_module.CreateRepositoryByExample(ctx, doer, u, repo, true, false); err != nil {
return err
}
// Re-fetch the repository from database before updating it (else it would
// override changes that were done earlier with sql)
if repo, err = repo_model.GetRepositoryByID(ctx, repo.ID); err != nil {
@ -97,8 +98,24 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR
log.Error("CreateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err)
return fmt.Errorf("CreateRepository(git update-server-info): %w", err)
}
// update repository status
repo.Status = repo_model.RepositoryReady
if err = repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil {
return fmt.Errorf("UpdateRepositoryCols: %w", err)
}
return nil
}); err != nil {
if repo != nil {
if errDelete := DeleteRepositoryDirectly(ctx, doer, repo.ID); errDelete != nil {
log.Error("Rollback deleteRepository: %v", errDelete)
// add system notice
if err := system_model.CreateRepositoryNotice("DeleteRepositoryDirectly failed when adopt repository: %v", errDelete); err != nil {
log.Error("CreateRepositoryNotice: %v", err)
}
}
}
return nil, err
}

View File

@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
system_model "code.gitea.io/gitea/models/system"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
@ -240,13 +241,13 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt
ObjectFormatName: opts.ObjectFormatName,
}
var rollbackRepo *repo_model.Repository
needsUpdateStatus := opts.Status == 0
if err := repo_module.CreateRepositoryByExample(ctx, doer, u, repo, false, false); err != nil {
return nil, err
}
if err := db.WithTx(ctx, func(ctx context.Context) error {
if err := repo_module.CreateRepositoryByExample(ctx, doer, u, repo, false, false); err != nil {
return err
}
// No need for init mirror.
if opts.IsMirror {
return nil
@ -285,8 +286,6 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt
// Initialize Issue Labels if selected
if len(opts.IssueLabels) > 0 {
if err = repo_module.InitializeLabels(ctx, repo.ID, opts.IssueLabels, false); err != nil {
rollbackRepo = repo
rollbackRepo.OwnerID = u.ID
return fmt.Errorf("InitializeLabels: %w", err)
}
}
@ -299,15 +298,25 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt
SetDescription(fmt.Sprintf("CreateRepository(git update-server-info): %s", repoPath)).
RunStdString(&git.RunOpts{Dir: repoPath}); err != nil {
log.Error("CreateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err)
rollbackRepo = repo
rollbackRepo.OwnerID = u.ID
return fmt.Errorf("CreateRepository(git update-server-info): %w", err)
}
if needsUpdateStatus {
repo.Status = repo_model.RepositoryReady
if err = repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil {
return fmt.Errorf("UpdateRepositoryCols: %w", err)
}
}
return nil
}); err != nil {
if rollbackRepo != nil {
if errDelete := DeleteRepositoryDirectly(ctx, doer, rollbackRepo.ID); errDelete != nil {
if repo != nil {
if errDelete := DeleteRepositoryDirectly(ctx, doer, repo.ID); errDelete != nil {
log.Error("Rollback deleteRepository: %v", errDelete)
// add system notice
if err := system_model.CreateRepositoryNotice("DeleteRepositoryDirectly failed when create repository: %v", errDelete); err != nil {
log.Error("CreateRepositoryNotice: %v", err)
}
}
}

View File

@ -335,6 +335,7 @@ func generateRepository(ctx context.Context, doer, owner *user_model.User, templ
TemplateID: templateRepo.ID,
TrustModel: templateRepo.TrustModel,
ObjectFormatName: templateRepo.ObjectFormatName,
Status: repo_model.RepositoryBeingMigrated,
}
if err = repo_module.CreateRepositoryByExample(ctx, doer, owner, generateRepo, false, false); err != nil {

View File

@ -5,12 +5,15 @@ package repository
import (
"context"
"fmt"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
system_model "code.gitea.io/gitea/models/system"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
notify_service "code.gitea.io/gitea/services/notify"
)
@ -69,13 +72,12 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ
}
}
var generateRepo *repo_model.Repository
if err = db.WithTx(ctx, func(ctx context.Context) error {
generateRepo, err = generateRepository(ctx, doer, owner, templateRepo, opts)
if err != nil {
return err
}
generateRepo, err := generateRepository(ctx, doer, owner, templateRepo, opts)
if err != nil {
return nil, err
}
if err = db.WithTx(ctx, func(ctx context.Context) error {
// Git Content
if opts.GitContent && !templateRepo.IsEmpty {
if err = GenerateGitContent(ctx, templateRepo, generateRepo); err != nil {
@ -124,8 +126,23 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ
}
}
// update repository status to be ready
generateRepo.Status = repo_model.RepositoryReady
if err = repo_model.UpdateRepositoryCols(ctx, generateRepo, "status"); err != nil {
return fmt.Errorf("UpdateRepositoryCols: %w", err)
}
return nil
}); err != nil {
if generateRepo != nil {
if errDelete := DeleteRepositoryDirectly(ctx, doer, generateRepo.ID); errDelete != nil {
log.Error("Rollback deleteRepository: %v", errDelete)
// add system notice
if err := system_model.CreateRepositoryNotice("DeleteRepositoryDirectly failed when generate repository: %v", errDelete); err != nil {
log.Error("CreateRepositoryNotice: %v", err)
}
}
}
return nil, err
}