fix(repo): /generate must sync the branch table for the new repo (#37693)

Two bugs in GenerateGitContent, the function behind
`POST /api/v1/repos/{owner}/{template}/generate`:

1. The new repository's refs were not written `branch` DB table
2. The function re-fetched the new repo row from the database
    but reassigned its local pointer

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
agyss
2026-05-15 09:24:40 +02:00
committed by GitHub
parent 5c887d68ca
commit 5b3575a8be
4 changed files with 41 additions and 52 deletions
+18 -25
View File
@@ -152,6 +152,16 @@ func initRepository(ctx context.Context, u *user_model.User, repo *repo_model.Re
return fmt.Errorf("createDelegateHooks: %w", err)
}
repo.DefaultBranch = util.IfZero(opts.DefaultBranch, setting.Repository.DefaultBranch)
repo.DefaultWikiBranch = setting.Repository.DefaultBranch
if !opts.AutoInit {
repo.IsEmpty = true
}
if err = repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "is_empty", "default_branch", "default_wiki_branch"); err != nil {
return fmt.Errorf("updateRepository: %w", err)
}
// Initialize repository according to user's choice.
if opts.AutoInit {
tmpDir, cleanup, err := setting.AppDataTempDir("git-repo-content").MkdirTempRandom("repos-" + repo.Name)
@@ -165,39 +175,22 @@ func initRepository(ctx context.Context, u *user_model.User, repo *repo_model.Re
}
// Apply changes and commit.
if err = initRepoCommit(ctx, tmpDir, repo, u, opts.DefaultBranch); err != nil {
if err = initRepoCommit(ctx, tmpDir, repo, u); err != nil {
return fmt.Errorf("initRepoCommit: %w", err)
}
}
// Re-fetch the repository from database before updating it (else it would
// override changes that were done earlier with sql)
if err = gitrepo.SetDefaultBranch(ctx, repo, repo.DefaultBranch); err != nil {
return fmt.Errorf("setDefaultBranch: %w", err)
}
// Re-fetch the repository from database before updating it (keep changes that were done earlier with SQL)
if repo, err = repo_model.GetRepositoryByID(ctx, repo.ID); err != nil {
return fmt.Errorf("getRepositoryByID: %w", err)
}
if !opts.AutoInit {
repo.IsEmpty = true
}
repo.DefaultBranch = setting.Repository.DefaultBranch
repo.DefaultWikiBranch = setting.Repository.DefaultBranch
if len(opts.DefaultBranch) > 0 {
repo.DefaultBranch = opts.DefaultBranch
if err = gitrepo.SetDefaultBranch(ctx, repo, repo.DefaultBranch); err != nil {
return fmt.Errorf("setDefaultBranch: %w", err)
}
if !repo.IsEmpty {
if _, err := repo_module.SyncRepoBranches(ctx, repo.ID, u.ID); err != nil {
return fmt.Errorf("SyncRepoBranches: %w", err)
}
}
}
if err = repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "is_empty", "default_branch", "default_wiki_branch"); err != nil {
return fmt.Errorf("updateRepository: %w", err)
if _, err := repo_module.SyncRepoBranches(ctx, repo.ID, u.ID); err != nil {
return fmt.Errorf("SyncRepoBranches: %w", err)
}
if err = repo_module.UpdateRepoSize(ctx, repo); err != nil {
+8 -18
View File
@@ -207,6 +207,9 @@ func processGiteaTemplateFile(ctx context.Context, tmpDir string, templateRepo,
}
func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *repo_model.Repository, tmpDir string) error {
// set default branch based on whether it's specified in the newly generated repo or not
repo.DefaultBranch = util.IfZero(repo.DefaultBranch, util.IfZero(templateRepo.DefaultBranch, setting.Repository.DefaultBranch))
// Clone to temporary path and do the init commit.
if err := gitrepo.CloneRepoToLocal(ctx, templateRepo, tmpDir, git.CloneRepoOptions{
Depth: 1,
@@ -246,13 +249,7 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r
return fmt.Errorf("failed to add submodules: %v", err)
}
// set default branch based on whether it's specified in the newly generated repo or not
defaultBranch := repo.DefaultBranch
if strings.TrimSpace(defaultBranch) == "" {
defaultBranch = templateRepo.DefaultBranch
}
return initRepoCommit(ctx, tmpDir, repo, repo.Owner, defaultBranch)
return initRepoCommit(ctx, tmpDir, repo, repo.Owner)
}
// GenerateGitContent generates git content from a template repository
@@ -266,17 +263,6 @@ func GenerateGitContent(ctx context.Context, templateRepo, generateRepo *repo_mo
if err = generateRepoCommit(ctx, generateRepo, templateRepo, generateRepo, tmpDir); err != nil {
return fmt.Errorf("generateRepoCommit: %w", err)
}
// re-fetch repo
if generateRepo, err = repo_model.GetRepositoryByID(ctx, generateRepo.ID); err != nil {
return fmt.Errorf("getRepositoryByID: %w", err)
}
// if there was no default branch supplied when generating the repo, use the default one from the template
if strings.TrimSpace(generateRepo.DefaultBranch) == "" {
generateRepo.DefaultBranch = templateRepo.DefaultBranch
}
if err = gitrepo.SetDefaultBranch(ctx, generateRepo, generateRepo.DefaultBranch); err != nil {
return fmt.Errorf("setDefaultBranch: %w", err)
}
@@ -291,6 +277,10 @@ func GenerateGitContent(ctx context.Context, templateRepo, generateRepo *repo_mo
if err := git_model.CopyLFS(ctx, generateRepo, templateRepo); err != nil {
return fmt.Errorf("failed to copy LFS: %w", err)
}
if _, err := repo_module.SyncRepoBranches(ctx, generateRepo.ID, 0); err != nil {
return fmt.Errorf("SyncRepoBranches: %w", err)
}
return nil
}
+2 -7
View File
@@ -16,12 +16,11 @@ import (
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
asymkey_service "code.gitea.io/gitea/services/asymkey"
)
// initRepoCommit temporarily changes with work directory.
func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Repository, u *user_model.User, defaultBranch string) (err error) {
func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Repository, u *user_model.User) (err error) {
commitTimeStr := time.Now().Format(time.RFC3339)
sig := u.NewGitSig()
@@ -69,13 +68,9 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi
return fmt.Errorf("git commit: %w", err)
}
if len(defaultBranch) == 0 {
defaultBranch = setting.Repository.DefaultBranch
}
if err := gitrepo.PushFromLocal(ctx, tmpPath, repo, git.PushOptions{
LocalRefName: "HEAD",
Branch: defaultBranch,
Branch: repo.DefaultBranch,
Env: repo_module.InternalPushingEnvironment(u, repo),
}); err != nil {
log.Error("Failed to push back to HEAD Error: %v", err)