diff options
author | Unknwon <u@gogs.io> | 2017-02-17 15:10:50 -0500 |
---|---|---|
committer | Unknwon <u@gogs.io> | 2017-02-17 15:10:50 -0500 |
commit | 7e09d210ba421a1baf03ef7ba8770bebe8d28b72 (patch) | |
tree | 1d209f6175c3e4d7e21c4bda62e65db0ac4608f5 /cmd/hook.go | |
parent | dab768212af15f4e671e5403ad3def455117f699 (diff) |
Initial version of protected branches (#776)
- Able to restrict force push and deletion
- Able to restrict direct push
Diffstat (limited to 'cmd/hook.go')
-rw-r--r-- | cmd/hook.go | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/cmd/hook.go b/cmd/hook.go index cb8b5112..c65b76e2 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -8,6 +8,7 @@ import ( "bufio" "bytes" "crypto/tls" + "fmt" "os" "os/exec" "path/filepath" @@ -64,13 +65,58 @@ func runHookPreReceive(c *cli.Context) error { if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 { return nil } - setup(c, "hooks/pre-receive.log", false) + setup(c, "hooks/pre-receive.log", true) + + isWiki := strings.Contains(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/") buf := bytes.NewBuffer(nil) scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { buf.Write(scanner.Bytes()) buf.WriteByte('\n') + + if isWiki { + continue + } + + fields := bytes.Fields(scanner.Bytes()) + if len(fields) != 3 { + continue + } + oldCommitID := string(fields[0]) + newCommitID := string(fields[1]) + branchName := strings.TrimPrefix(string(fields[2]), git.BRANCH_PREFIX) + + // Branch protection + repoID := com.StrTo(os.Getenv(http.ENV_REPO_ID)).MustInt64() + protectBranch, err := models.GetProtectBranchOfRepoByName(repoID, branchName) + if err != nil { + if models.IsErrBranchNotExist(err) { + continue + } + fail("Internal error", "GetProtectBranchOfRepoByName [repo_id: %d, branch: %s]: %v", repoID, branchName, err) + } + if !protectBranch.Protected { + continue + } + + // Check if branch allows direct push + if protectBranch.RequirePullRequest { + fail(fmt.Sprintf("Branch '%s' is protected and commits must be merged through pull request", branchName), "") + } + + // check and deletion + if newCommitID == git.EMPTY_SHA { + 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), "") + } } customHooksPath := filepath.Join(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), "pre-receive") |