diff --git a/cmd/hook.go b/cmd/hook.go index ebd230999..aabd9637c 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -59,6 +59,12 @@ var ( ) func runHookPreReceive(c *cli.Context) error { + if os.Getenv(models.EnvIsInternal) == "true" { + return nil + } + + setup("hooks/pre-receive.log", false) + if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 { if setting.OnlyAllowPushIfGiteaEnvironmentSet { fail(`Rejecting changes as Gitea environment not set. @@ -69,8 +75,6 @@ Gitea or set your environment appropriately.`, "") } } - setup("hooks/pre-receive.log", false) - // the environment setted on serv command isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") username := os.Getenv(models.EnvRepoUsername) @@ -186,6 +190,12 @@ func runHookUpdate(c *cli.Context) error { } func runHookPostReceive(c *cli.Context) error { + if os.Getenv(models.EnvIsInternal) == "true" { + return nil + } + + setup("hooks/post-receive.log", false) + if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 { if setting.OnlyAllowPushIfGiteaEnvironmentSet { fail(`Rejecting changes as Gitea environment not set. @@ -196,8 +206,6 @@ Gitea or set your environment appropriately.`, "") } } - setup("hooks/post-receive.log", false) - // the environment setted on serv command repoUser := os.Getenv(models.EnvRepoUsername) isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") diff --git a/models/helper_environment.go b/models/helper_environment.go index 2095205db..35af17adb 100644 --- a/models/helper_environment.go +++ b/models/helper_environment.go @@ -10,6 +10,16 @@ import ( "strings" ) +// InternalPushingEnvironment returns an os environment to switch off hooks on push +// It is recommended to avoid using this unless you are pushing within a transaction +// or if you absolutely are sure that post-receive and pre-receive will do nothing +// We provide the full pushing-environment for other hook providers +func InternalPushingEnvironment(doer *User, repo *Repository) []string { + return append(PushingEnvironment(doer, repo), + EnvIsInternal+"=true", + ) +} + // PushingEnvironment returns an os environment to allow hooks to work on push func PushingEnvironment(doer *User, repo *Repository) []string { return FullPushingEnvironment(doer, doer, repo, repo.Name, 0) diff --git a/models/repo.go b/models/repo.go index 53a9196aa..0dbdcc11b 100644 --- a/models/repo.go +++ b/models/repo.go @@ -1012,7 +1012,7 @@ func createDelegateHooks(repoPath string) (err error) { } // initRepoCommit temporarily changes with work directory. -func initRepoCommit(tmpPath string, u *User) (err error) { +func initRepoCommit(tmpPath string, repo *Repository, u *User) (err error) { commitTimeStr := time.Now().Format(time.RFC3339) sig := u.NewGitSig() @@ -1061,7 +1061,7 @@ func initRepoCommit(tmpPath string, u *User) (err error) { if stdout, err := git.NewCommand("push", "origin", "master"). SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)). - RunInDir(tmpPath); err != nil { + RunInDirWithEnv(tmpPath, InternalPushingEnvironment(u, repo)); err != nil { log.Error("Failed to push back to master: Stdout: %s\nError: %v", stdout, err) return fmt.Errorf("git push: %v", err) } @@ -1219,7 +1219,7 @@ func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts C } // Apply changes and commit. - if err = initRepoCommit(tmpDir, u); err != nil { + if err = initRepoCommit(tmpDir, repo, u); err != nil { return fmt.Errorf("initRepoCommit: %v", err) } } diff --git a/models/repo_generate.go b/models/repo_generate.go index 98ef0ea00..556a5fc2f 100644 --- a/models/repo_generate.go +++ b/models/repo_generate.go @@ -174,7 +174,7 @@ func generateRepoCommit(e Engine, repo, templateRepo, generateRepo *Repository, return fmt.Errorf("git remote add: %v", err) } - return initRepoCommit(tmpDir, repo.Owner) + return initRepoCommit(tmpDir, repo, repo.Owner) } // generateRepository initializes repository from template diff --git a/models/update.go b/models/update.go index b6c04bd51..212f22cfc 100644 --- a/models/update.go +++ b/models/update.go @@ -24,6 +24,7 @@ const ( EnvPusherID = "GITEA_PUSHER_ID" EnvKeyID = "GITEA_KEY_ID" EnvIsDeployKey = "GITEA_IS_DEPLOY_KEY" + EnvIsInternal = "GITEA_INTERNAL_PUSH" ) // CommitToPushCommit transforms a git.Commit to PushCommit type. diff --git a/services/pull/pull.go b/services/pull/pull.go index fb47df1c3..6be9c2da1 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -242,10 +242,19 @@ func PushToBaseRepo(pr *models.PullRequest) (err error) { _ = os.Remove(file) + if err = pr.LoadIssue(); err != nil { + return fmt.Errorf("unable to load issue %d for pr %d: %v", pr.IssueID, pr.ID, err) + } + if err = pr.Issue.LoadPoster(); err != nil { + return fmt.Errorf("unable to load poster %d for pr %d: %v", pr.Issue.PosterID, pr.ID, err) + } + if err = git.Push(headRepoPath, git.PushOptions{ Remote: tmpRemoteName, Branch: fmt.Sprintf("%s:%s", pr.HeadBranch, headFile), Force: true, + // Use InternalPushingEnvironment here because we know that pre-receive and post-receive do not run on a refs/pulls/... + Env: models.InternalPushingEnvironment(pr.Issue.Poster, pr.BaseRepo), }); err != nil { return fmt.Errorf("Push: %v", err) }