From 752c3fe61577be762b1aef7c6529193102655154 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Thu, 26 Dec 2019 10:48:11 +0000 Subject: [PATCH 1/8] Also fix #8982 - need to read settings before you check their value --- cmd/hook.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/hook.go b/cmd/hook.go index 03fa15aabc072..d47504dd44b9f 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -59,6 +59,8 @@ var ( ) func runHookPreReceive(c *cli.Context) error { + 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 +71,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) @@ -197,6 +197,8 @@ Gitea or set your environment appropriately.`, "") } func runHookPostReceive(c *cli.Context) error { + 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. @@ -207,8 +209,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") From 2ac4341e273783ace884f30410395b3e0902d813 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Thu, 26 Dec 2019 11:31:59 +0000 Subject: [PATCH 2/8] Account for push in pull.PushToBaseRepo --- services/pull/pull.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/services/pull/pull.go b/services/pull/pull.go index fb47df1c3a6a7..252cfe95c8574 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -242,10 +242,18 @@ 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, + Env: models.PushingEnvironment(pr.Issue.Poster, pr.BaseRepo), }); err != nil { return fmt.Errorf("Push: %v", err) } From 21f81144d9db633323a6109848fb062fbfad1b2d Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Thu, 26 Dec 2019 13:21:45 +0000 Subject: [PATCH 3/8] Ensure push in initRepoCommit sets the SSH flag --- models/repo.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/models/repo.go b/models/repo.go index 02cb3b912866f..fcde1c4d4612e 100644 --- a/models/repo.go +++ b/models/repo.go @@ -1011,6 +1011,7 @@ func initRepoCommit(tmpPath string, u *User) (err error) { sig := u.NewGitSig() // Because this may call hooks we should pass in the environment env := append(os.Environ(), + "SSH_ORIGINAL_COMMAND=gitea-internal", "GIT_AUTHOR_NAME="+sig.Name, "GIT_AUTHOR_EMAIL="+sig.Email, "GIT_AUTHOR_DATE="+commitTimeStr, @@ -1054,7 +1055,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, env); err != nil { log.Error("Failed to push back to master: Stdout: %s\nError: %v", stdout, err) return fmt.Errorf("git push: %v", err) } From 59885c55c40d2bedb83fd45729ddca3c1f0f3d3a Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Thu, 26 Dec 2019 13:27:38 +0000 Subject: [PATCH 4/8] fixup! Ensure push in initRepoCommit sets the SSH flag --- models/repo.go | 7 +++---- models/repo_generate.go | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/models/repo.go b/models/repo.go index fcde1c4d4612e..c197c5a6eb791 100644 --- a/models/repo.go +++ b/models/repo.go @@ -1005,13 +1005,12 @@ 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() // Because this may call hooks we should pass in the environment env := append(os.Environ(), - "SSH_ORIGINAL_COMMAND=gitea-internal", "GIT_AUTHOR_NAME="+sig.Name, "GIT_AUTHOR_EMAIL="+sig.Email, "GIT_AUTHOR_DATE="+commitTimeStr, @@ -1055,7 +1054,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)). - RunInDirWithEnv(tmpPath, env); err != nil { + RunInDirWithEnv(tmpPath, PushingEnvironment(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) } @@ -1213,7 +1212,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 98ef0ea00081b..556a5fc2f72b9 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 From 165dd80afae4a98fcccff007ba77addb9b7ce88d Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Thu, 26 Dec 2019 20:53:22 +0000 Subject: [PATCH 5/8] Create internal push marker --- cmd/hook.go | 6 ++++++ models/helper_environment.go | 9 +++++++++ models/repo.go | 6 +++--- models/repo_generate.go | 2 +- models/update.go | 1 + 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/cmd/hook.go b/cmd/hook.go index d47504dd44b9f..0df9097051369 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -70,6 +70,9 @@ Gitea or set your environment appropriately.`, "") return nil } } + if os.Getenv(models.EnvIsInternal) == "true" { + return nil + } // the environment setted on serv command isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") @@ -208,6 +211,9 @@ Gitea or set your environment appropriately.`, "") return nil } } + if os.Getenv(models.EnvIsInternal) == "true" { + return nil + } // the environment setted on serv command repoUser := os.Getenv(models.EnvRepoUsername) diff --git a/models/helper_environment.go b/models/helper_environment.go index 2095205db3184..4e1b413ad11bc 100644 --- a/models/helper_environment.go +++ b/models/helper_environment.go @@ -10,6 +10,15 @@ 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 +func internalPushingEnvironment() []string { + return append(os.Environ(), + EnvIsInternal+"=true", + "SSH_ORIGINAL_COMMAND=gitea-internal", + ) +} + // 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 c197c5a6eb791..7d64b36c5d5ec 100644 --- a/models/repo.go +++ b/models/repo.go @@ -1005,7 +1005,7 @@ func createDelegateHooks(repoPath string) (err error) { } // initRepoCommit temporarily changes with work directory. -func initRepoCommit(tmpPath string, repo *Repository, u *User) (err error) { +func initRepoCommit(tmpPath string, u *User) (err error) { commitTimeStr := time.Now().Format(time.RFC3339) sig := u.NewGitSig() @@ -1054,7 +1054,7 @@ func initRepoCommit(tmpPath string, repo *Repository, u *User) (err error) { if stdout, err := git.NewCommand("push", "origin", "master"). SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)). - RunInDirWithEnv(tmpPath, PushingEnvironment(u, repo)); err != nil { + RunInDirWithEnv(tmpPath, internalPushingEnvironment()); err != nil { log.Error("Failed to push back to master: Stdout: %s\nError: %v", stdout, err) return fmt.Errorf("git push: %v", err) } @@ -1212,7 +1212,7 @@ func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts C } // Apply changes and commit. - if err = initRepoCommit(tmpDir, repo, u); err != nil { + if err = initRepoCommit(tmpDir, u); err != nil { return fmt.Errorf("initRepoCommit: %v", err) } } diff --git a/models/repo_generate.go b/models/repo_generate.go index 556a5fc2f72b9..98ef0ea00081b 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, repo.Owner) + return initRepoCommit(tmpDir, repo.Owner) } // generateRepository initializes repository from template diff --git a/models/update.go b/models/update.go index 1105c9a82895b..98c65d232d141 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. From ebd787896e49e40af94bcd4a35f03d4c26d1bf98 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Fri, 27 Dec 2019 12:16:10 +0000 Subject: [PATCH 6/8] Do not load settings if this is an internal push --- cmd/hook.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cmd/hook.go b/cmd/hook.go index 0df9097051369..537ef2a770cd5 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -59,6 +59,10 @@ 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 { @@ -70,9 +74,6 @@ Gitea or set your environment appropriately.`, "") return nil } } - if os.Getenv(models.EnvIsInternal) == "true" { - return nil - } // the environment setted on serv command isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") @@ -200,6 +201,10 @@ Gitea or set your environment appropriately.`, "") } 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 { @@ -211,9 +216,6 @@ Gitea or set your environment appropriately.`, "") return nil } } - if os.Getenv(models.EnvIsInternal) == "true" { - return nil - } // the environment setted on serv command repoUser := os.Getenv(models.EnvRepoUsername) From efccd5b04b42aad4933631985fefcffa4136475c Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Fri, 27 Dec 2019 12:17:25 +0000 Subject: [PATCH 7/8] Adjust internalPushingEnvironment to also run on the pushtobaserepo --- models/helper_environment.go | 9 +++++---- models/repo.go | 6 +++--- models/repo_generate.go | 2 +- services/pull/pull.go | 3 ++- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/models/helper_environment.go b/models/helper_environment.go index 4e1b413ad11bc..35af17adb1025 100644 --- a/models/helper_environment.go +++ b/models/helper_environment.go @@ -10,12 +10,13 @@ import ( "strings" ) -// internalPushingEnvironment returns an os environment to switch off hooks on push +// 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 -func internalPushingEnvironment() []string { - return append(os.Environ(), +// 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", - "SSH_ORIGINAL_COMMAND=gitea-internal", ) } diff --git a/models/repo.go b/models/repo.go index 7d64b36c5d5ec..5c41a7c0fd9e0 100644 --- a/models/repo.go +++ b/models/repo.go @@ -1005,7 +1005,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() @@ -1054,7 +1054,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)). - RunInDirWithEnv(tmpPath, internalPushingEnvironment()); 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) } @@ -1212,7 +1212,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 98ef0ea00081b..556a5fc2f72b9 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/services/pull/pull.go b/services/pull/pull.go index 252cfe95c8574..6be9c2da176c0 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -253,7 +253,8 @@ func PushToBaseRepo(pr *models.PullRequest) (err error) { Remote: tmpRemoteName, Branch: fmt.Sprintf("%s:%s", pr.HeadBranch, headFile), Force: true, - Env: models.PushingEnvironment(pr.Issue.Poster, pr.BaseRepo), + // 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) } From e00c5ab4ea59811503291da4d6802e51dea638d4 Mon Sep 17 00:00:00 2001 From: zeripath Date: Fri, 27 Dec 2019 19:03:47 +0000 Subject: [PATCH 8/8] Update models/repo.go --- models/repo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/repo.go b/models/repo.go index a48ae9fae77ae..0dbdcc11b5b6a 100644 --- a/models/repo.go +++ b/models/repo.go @@ -1061,7 +1061,7 @@ func initRepoCommit(tmpPath string, repo *Repository, u *User) (err error) { if stdout, err := git.NewCommand("push", "origin", "master"). SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)). - RunInDirWithEnv(tmpPath, internalPushingEnvironment(u, repo)); 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) }