diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2017-02-25 22:54:40 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-25 22:54:40 +0800 |
commit | cd1821a7e292b05e04fcc2a969b42d06ab512849 (patch) | |
tree | 084f97bfb24a37ec3028d15fdacb51e86cfcc368 /cmd/hook.go | |
parent | e8e56da9ac321aacb3c06968997a45c2f133cd4e (diff) | |
download | gitea-cd1821a7e292b05e04fcc2a969b42d06ab512849.tar.gz gitea-cd1821a7e292b05e04fcc2a969b42d06ab512849.zip |
Move push update to post-receive and protected branch check to pre-receive (#1030)
* move all push update to git hook post-receive and protected branch check to git hook pre-receive
* add SSH_ORIGINAL_COMMAND check back
* remove all unused codes
* fix the import
Diffstat (limited to 'cmd/hook.go')
-rw-r--r-- | cmd/hook.go | 135 |
1 files changed, 118 insertions, 17 deletions
diff --git a/cmd/hook.go b/cmd/hook.go index 15ad74f8e0..a89c3741bf 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -5,11 +5,22 @@ package cmd import ( + "bufio" + "bytes" + "crypto/tls" "fmt" "os" + "strconv" + "strings" + "code.gitea.io/git" "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/httplib" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" + "github.com/Unknwon/com" "github.com/urfave/cli" ) @@ -57,10 +68,59 @@ func runHookPreReceive(c *cli.Context) error { if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 { return nil } + if err := setup("hooks/pre-receive.log"); err != nil { fail("Hook pre-receive init failed", fmt.Sprintf("setup: %v", err)) } + // the environment setted on serv command + repoID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchRepoID), 10, 64) + isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") + + buf := bytes.NewBuffer(nil) + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + buf.Write(scanner.Bytes()) + buf.WriteByte('\n') + + // TODO: support news feeds for wiki + if isWiki { + continue + } + + fields := bytes.Fields(scanner.Bytes()) + if len(fields) != 3 { + continue + } + + oldCommitID := string(fields[0]) + newCommitID := string(fields[1]) + refFullName := string(fields[2]) + + branchName := strings.TrimPrefix(refFullName, git.BranchPrefix) + protectBranch, err := models.GetProtectedBranchBy(repoID, branchName) + if err != nil { + log.GitLogger.Fatal(2, "retrieve protected branches information failed") + } + + if protectBranch != nil { + fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "") + } + + // check and deletion + if newCommitID == git.EmptySHA { + fail(fmt.Sprintf("Branch '%s' is protected from deletion", branchName), "") + } + + // Check force push + output, err := git.NewCommand("rev-list", oldCommitID, "^"+newCommitID).Run() + if err != nil { + fail("Internal error", "Fail to detect force push: %v", err) + } else if len(output) > 0 { + fail(fmt.Sprintf("Branch '%s' is protected from force push", branchName), "") + } + } + return nil } @@ -73,23 +133,6 @@ func runHookUpdate(c *cli.Context) error { fail("Hook update init failed", fmt.Sprintf("setup: %v", err)) } - args := c.Args() - if len(args) != 3 { - fail("Arguments received are not equal to three", "Arguments received are not equal to three") - } else if len(args[0]) == 0 { - fail("First argument 'refName' is empty", "First argument 'refName' is empty") - } - - uuid := os.Getenv(envUpdateTaskUUID) - if err := models.AddUpdateTask(&models.UpdateTask{ - UUID: uuid, - RefName: args[0], - OldCommitID: args[1], - NewCommitID: args[2], - }); err != nil { - fail("Internal error", "Fail to add update task '%s': %v", uuid, err) - } - return nil } @@ -102,5 +145,63 @@ func runHookPostReceive(c *cli.Context) error { fail("Hook post-receive init failed", fmt.Sprintf("setup: %v", err)) } + // the environment setted on serv command + repoUser := os.Getenv(models.EnvRepoUsername) + repoUserSalt := os.Getenv(models.EnvRepoUserSalt) + isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") + repoName := os.Getenv(models.EnvRepoName) + pusherID, _ := strconv.ParseInt(os.Getenv(models.EnvPusherID), 10, 64) + pusherName := os.Getenv(models.EnvPusherName) + + buf := bytes.NewBuffer(nil) + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + buf.Write(scanner.Bytes()) + buf.WriteByte('\n') + + // TODO: support news feeds for wiki + if isWiki { + continue + } + + fields := bytes.Fields(scanner.Bytes()) + if len(fields) != 3 { + continue + } + + oldCommitID := string(fields[0]) + newCommitID := string(fields[1]) + refFullName := string(fields[2]) + + if err := models.PushUpdate(models.PushUpdateOptions{ + RefFullName: refFullName, + OldCommitID: oldCommitID, + NewCommitID: newCommitID, + PusherID: pusherID, + PusherName: pusherName, + RepoUserName: repoUser, + RepoName: repoName, + }); err != nil { + log.GitLogger.Error(2, "Update: %v", err) + } + + // Ask for running deliver hook and test pull request tasks. + reqURL := setting.LocalURL + repoUser + "/" + repoName + "/tasks/trigger?branch=" + + strings.TrimPrefix(refFullName, git.BranchPrefix) + "&secret=" + base.EncodeMD5(repoUserSalt) + "&pusher=" + com.ToStr(pusherID) + log.GitLogger.Trace("Trigger task: %s", reqURL) + + resp, err := httplib.Head(reqURL).SetTLSClientConfig(&tls.Config{ + InsecureSkipVerify: true, + }).Response() + if err == nil { + resp.Body.Close() + if resp.StatusCode/100 != 2 { + log.GitLogger.Error(2, "Failed to trigger task: not 2xx response code") + } + } else { + log.GitLogger.Error(2, "Failed to trigger task: %v", err) + } + } + return nil } |