@@ -6,22 +6,18 @@ package repository | |||
import ( | |||
"context" | |||
"fmt" | |||
"os" | |||
"path/filepath" | |||
"sort" | |||
"strings" | |||
"time" | |||
issues_model "code.gitea.io/gitea/models/issues" | |||
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/label" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/options" | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/modules/util" | |||
asymkey_service "code.gitea.io/gitea/services/asymkey" | |||
) | |||
type OptionFile struct { | |||
@@ -124,70 +120,6 @@ func LoadRepoConfig() error { | |||
return nil | |||
} | |||
// 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) { | |||
commitTimeStr := time.Now().Format(time.RFC3339) | |||
sig := u.NewGitSig() | |||
// Because this may call hooks we should pass in the environment | |||
env := append(os.Environ(), | |||
"GIT_AUTHOR_NAME="+sig.Name, | |||
"GIT_AUTHOR_EMAIL="+sig.Email, | |||
"GIT_AUTHOR_DATE="+commitTimeStr, | |||
"GIT_COMMITTER_DATE="+commitTimeStr, | |||
) | |||
committerName := sig.Name | |||
committerEmail := sig.Email | |||
if stdout, _, err := git.NewCommand(ctx, "add", "--all"). | |||
SetDescription(fmt.Sprintf("initRepoCommit (git add): %s", tmpPath)). | |||
RunStdString(&git.RunOpts{Dir: tmpPath}); err != nil { | |||
log.Error("git add --all failed: Stdout: %s\nError: %v", stdout, err) | |||
return fmt.Errorf("git add --all: %w", err) | |||
} | |||
cmd := git.NewCommand(ctx, "commit", "--message=Initial commit"). | |||
AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email) | |||
sign, keyID, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u) | |||
if sign { | |||
cmd.AddOptionFormat("-S%s", keyID) | |||
if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { | |||
// need to set the committer to the KeyID owner | |||
committerName = signer.Name | |||
committerEmail = signer.Email | |||
} | |||
} else { | |||
cmd.AddArguments("--no-gpg-sign") | |||
} | |||
env = append(env, | |||
"GIT_COMMITTER_NAME="+committerName, | |||
"GIT_COMMITTER_EMAIL="+committerEmail, | |||
) | |||
if stdout, _, err := cmd. | |||
SetDescription(fmt.Sprintf("initRepoCommit (git commit): %s", tmpPath)). | |||
RunStdString(&git.RunOpts{Dir: tmpPath, Env: env}); err != nil { | |||
log.Error("Failed to commit: %v: Stdout: %s\nError: %v", cmd.String(), stdout, err) | |||
return fmt.Errorf("git commit: %w", err) | |||
} | |||
if len(defaultBranch) == 0 { | |||
defaultBranch = setting.Repository.DefaultBranch | |||
} | |||
if stdout, _, err := git.NewCommand(ctx, "push", "origin").AddDynamicArguments("HEAD:" + defaultBranch). | |||
SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)). | |||
RunStdString(&git.RunOpts{Dir: tmpPath, Env: InternalPushingEnvironment(u, repo)}); err != nil { | |||
log.Error("Failed to push back to HEAD: Stdout: %s\nError: %v", stdout, err) | |||
return fmt.Errorf("git push: %w", err) | |||
} | |||
return nil | |||
} | |||
func CheckInitRepository(ctx context.Context, owner, name, objectFormatName string) (err error) { | |||
// Somehow the directory could exist. | |||
repoPath := repo_model.RepoPath(owner, name) |
@@ -358,7 +358,7 @@ func Generate(ctx *context.APIContext) { | |||
return | |||
} | |||
opts := repo_module.GenerateRepoOptions{ | |||
opts := repo_service.GenerateRepoOptions{ | |||
Name: form.Name, | |||
DefaultBranch: form.DefaultBranch, | |||
Description: form.Description, |
@@ -244,7 +244,7 @@ func CreatePost(ctx *context.Context) { | |||
var repo *repo_model.Repository | |||
var err error | |||
if form.RepoTemplate > 0 { | |||
opts := repo_module.GenerateRepoOptions{ | |||
opts := repo_service.GenerateRepoOptions{ | |||
Name: form.RepoName, | |||
Description: form.Description, | |||
Private: form.Private, |
@@ -157,7 +157,7 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re | |||
} | |||
// Apply changes and commit. | |||
if err = repo_module.InitRepoCommit(ctx, tmpDir, repo, u, opts.DefaultBranch); err != nil { | |||
if err = initRepoCommit(ctx, tmpDir, repo, u, opts.DefaultBranch); err != nil { | |||
return fmt.Errorf("initRepoCommit: %w", err) | |||
} | |||
} |
@@ -21,6 +21,7 @@ import ( | |||
"code.gitea.io/gitea/modules/git" | |||
"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/util" | |||
"github.com/gobwas/glob" | |||
@@ -242,7 +243,7 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r | |||
defaultBranch = templateRepo.DefaultBranch | |||
} | |||
return InitRepoCommit(ctx, tmpDir, repo, repo.Owner, defaultBranch) | |||
return initRepoCommit(ctx, tmpDir, repo, repo.Owner, defaultBranch) | |||
} | |||
func generateGitContent(ctx context.Context, repo, templateRepo, generateRepo *repo_model.Repository) (err error) { | |||
@@ -292,7 +293,7 @@ func GenerateGitContent(ctx context.Context, templateRepo, generateRepo *repo_mo | |||
return err | |||
} | |||
if err := UpdateRepoSize(ctx, generateRepo); err != nil { | |||
if err := repo_module.UpdateRepoSize(ctx, generateRepo); err != nil { | |||
return fmt.Errorf("failed to update size for repository: %w", err) | |||
} | |||
@@ -323,8 +324,8 @@ 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) { | |||
// 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, | |||
@@ -341,7 +342,7 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ | |||
ObjectFormatName: templateRepo.ObjectFormatName, | |||
} | |||
if err = CreateRepositoryByExample(ctx, doer, owner, generateRepo, false, false); err != nil { | |||
if err = repo_module.CreateRepositoryByExample(ctx, doer, owner, generateRepo, false, false); err != nil { | |||
return nil, err | |||
} | |||
@@ -358,11 +359,11 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ | |||
} | |||
} | |||
if err = CheckInitRepository(ctx, owner.Name, generateRepo.Name, generateRepo.ObjectFormatName); err != nil { | |||
if err = repo_module.CheckInitRepository(ctx, owner.Name, generateRepo.Name, generateRepo.ObjectFormatName); err != nil { | |||
return generateRepo, err | |||
} | |||
if err = CheckDaemonExportOK(ctx, generateRepo); err != nil { | |||
if err = repo_module.CheckDaemonExportOK(ctx, generateRepo); err != nil { | |||
return generateRepo, fmt.Errorf("checkDaemonExportOK: %w", err) | |||
} | |||
@@ -0,0 +1,83 @@ | |||
// Copyright 2024 The Gitea Authors. All rights reserved. | |||
// SPDX-License-Identifier: MIT | |||
package repository | |||
import ( | |||
"context" | |||
"fmt" | |||
"os" | |||
"time" | |||
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/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) { | |||
commitTimeStr := time.Now().Format(time.RFC3339) | |||
sig := u.NewGitSig() | |||
// Because this may call hooks we should pass in the environment | |||
env := append(os.Environ(), | |||
"GIT_AUTHOR_NAME="+sig.Name, | |||
"GIT_AUTHOR_EMAIL="+sig.Email, | |||
"GIT_AUTHOR_DATE="+commitTimeStr, | |||
"GIT_COMMITTER_DATE="+commitTimeStr, | |||
) | |||
committerName := sig.Name | |||
committerEmail := sig.Email | |||
if stdout, _, err := git.NewCommand(ctx, "add", "--all"). | |||
SetDescription(fmt.Sprintf("initRepoCommit (git add): %s", tmpPath)). | |||
RunStdString(&git.RunOpts{Dir: tmpPath}); err != nil { | |||
log.Error("git add --all failed: Stdout: %s\nError: %v", stdout, err) | |||
return fmt.Errorf("git add --all: %w", err) | |||
} | |||
cmd := git.NewCommand(ctx, "commit", "--message=Initial commit"). | |||
AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email) | |||
sign, keyID, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u) | |||
if sign { | |||
cmd.AddOptionFormat("-S%s", keyID) | |||
if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { | |||
// need to set the committer to the KeyID owner | |||
committerName = signer.Name | |||
committerEmail = signer.Email | |||
} | |||
} else { | |||
cmd.AddArguments("--no-gpg-sign") | |||
} | |||
env = append(env, | |||
"GIT_COMMITTER_NAME="+committerName, | |||
"GIT_COMMITTER_EMAIL="+committerEmail, | |||
) | |||
if stdout, _, err := cmd. | |||
SetDescription(fmt.Sprintf("initRepoCommit (git commit): %s", tmpPath)). | |||
RunStdString(&git.RunOpts{Dir: tmpPath, Env: env}); err != nil { | |||
log.Error("Failed to commit: %v: Stdout: %s\nError: %v", cmd.String(), stdout, err) | |||
return fmt.Errorf("git commit: %w", err) | |||
} | |||
if len(defaultBranch) == 0 { | |||
defaultBranch = setting.Repository.DefaultBranch | |||
} | |||
if stdout, _, err := git.NewCommand(ctx, "push", "origin").AddDynamicArguments("HEAD:" + defaultBranch). | |||
SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)). | |||
RunStdString(&git.RunOpts{Dir: tmpPath, Env: repo_module.InternalPushingEnvironment(u, repo)}); err != nil { | |||
log.Error("Failed to push back to HEAD: Stdout: %s\nError: %v", stdout, err) | |||
return fmt.Errorf("git push: %w", err) | |||
} | |||
return nil | |||
} |
@@ -11,7 +11,6 @@ import ( | |||
issues_model "code.gitea.io/gitea/models/issues" | |||
repo_model "code.gitea.io/gitea/models/repo" | |||
user_model "code.gitea.io/gitea/models/user" | |||
repo_module "code.gitea.io/gitea/modules/repository" | |||
notify_service "code.gitea.io/gitea/services/notify" | |||
) | |||
@@ -63,7 +62,7 @@ func GenerateProtectedBranch(ctx context.Context, templateRepo, generateRepo *re | |||
} | |||
// GenerateRepository generates a repository from a template | |||
func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts repo_module.GenerateRepoOptions) (_ *repo_model.Repository, err error) { | |||
func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts GenerateRepoOptions) (_ *repo_model.Repository, err error) { | |||
if !doer.IsAdmin && !owner.CanCreateRepo() { | |||
return nil, repo_model.ErrReachLimitOfRepo{ | |||
Limit: owner.MaxRepoCreation, | |||
@@ -72,14 +71,14 @@ 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 = repo_module.GenerateRepository(ctx, doer, owner, templateRepo, opts) | |||
generateRepo, err = generateRepository(ctx, doer, owner, templateRepo, opts) | |||
if err != nil { | |||
return err | |||
} | |||
// Git Content | |||
if opts.GitContent && !templateRepo.IsEmpty { | |||
if err = repo_module.GenerateGitContent(ctx, templateRepo, generateRepo); err != nil { | |||
if err = GenerateGitContent(ctx, templateRepo, generateRepo); err != nil { | |||
return err | |||
} | |||
} |