mirror of
https://github.com/go-gitea/gitea
synced 2025-07-22 10:18:38 +00:00
Rework create/fork/adopt/generate repository to make sure resources will be cleanup once failed (#31035)
Fix #28144 To make the resources will be cleanup once failed. All repository operations now follow a consistent pattern: - 1. Create a database record for the repository with the status being_migrated. - 2. Register a deferred cleanup function to delete the repository and its related data if the operation fails. - 3. Perform the actual Git and database operations step by step. - 4. Upon successful completion, update the repository’s status to ready. The adopt operation is a special case — if it fails, the repository on disk should not be deleted.
This commit is contained in:
@@ -17,7 +17,6 @@ import (
|
||||
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@@ -328,57 +327,6 @@ func (gro GenerateRepoOptions) IsValid() bool {
|
||||
gro.IssueLabels || gro.ProtectedBranch // or other items as they are added
|
||||
}
|
||||
|
||||
// generateRepository generates a repository from a template
|
||||
func generateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts GenerateRepoOptions) (_ *repo_model.Repository, err error) {
|
||||
generateRepo := &repo_model.Repository{
|
||||
OwnerID: owner.ID,
|
||||
Owner: owner,
|
||||
OwnerName: owner.Name,
|
||||
Name: opts.Name,
|
||||
LowerName: strings.ToLower(opts.Name),
|
||||
Description: opts.Description,
|
||||
DefaultBranch: opts.DefaultBranch,
|
||||
IsPrivate: opts.Private,
|
||||
IsEmpty: !opts.GitContent || templateRepo.IsEmpty,
|
||||
IsFsckEnabled: templateRepo.IsFsckEnabled,
|
||||
TemplateID: templateRepo.ID,
|
||||
TrustModel: templateRepo.TrustModel,
|
||||
ObjectFormatName: templateRepo.ObjectFormatName,
|
||||
}
|
||||
|
||||
if err = CreateRepositoryByExample(ctx, doer, owner, generateRepo, false, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
isExist, err := gitrepo.IsRepositoryExist(ctx, generateRepo)
|
||||
if err != nil {
|
||||
log.Error("Unable to check if %s exists. Error: %v", generateRepo.FullName(), err)
|
||||
return nil, err
|
||||
}
|
||||
if isExist {
|
||||
return nil, repo_model.ErrRepoFilesAlreadyExist{
|
||||
Uname: generateRepo.OwnerName,
|
||||
Name: generateRepo.Name,
|
||||
}
|
||||
}
|
||||
|
||||
if err = repo_module.CheckInitRepository(ctx, generateRepo); err != nil {
|
||||
return generateRepo, err
|
||||
}
|
||||
|
||||
if err = repo_module.CheckDaemonExportOK(ctx, generateRepo); err != nil {
|
||||
return generateRepo, fmt.Errorf("checkDaemonExportOK: %w", err)
|
||||
}
|
||||
|
||||
if stdout, _, err := git.NewCommand("update-server-info").
|
||||
RunStdString(ctx, &git.RunOpts{Dir: generateRepo.RepoPath()}); err != nil {
|
||||
log.Error("GenerateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", generateRepo, stdout, err)
|
||||
return generateRepo, fmt.Errorf("error in GenerateRepository(git update-server-info): %w", err)
|
||||
}
|
||||
|
||||
return generateRepo, nil
|
||||
}
|
||||
|
||||
var fileNameSanitizeRegexp = regexp.MustCompile(`(?i)\.\.|[<>:\"/\\|?*\x{0000}-\x{001F}]|^(con|prn|aux|nul|com\d|lpt\d)$`)
|
||||
|
||||
// Sanitize user input to valid OS filenames
|
||||
|
Reference in New Issue
Block a user