Skip to content

Commit fe94032

Browse files
philfrylunny
authored andcommitted
rewrite pre-commit, post-commit and options hooks (fixes #1250) (#1257)
* issue #1250, replace {pre,post}-receive and update hooks with a single shell script that does not require custom hooks to be a sh-script * issue #1250, make script posix compilant * v23, add migration script to update {pre,post}-receive and update hooks * migration: use a more common name and rename v23 to v26 to avoid conflicts * gofmt'ed and added copyright header * fix SyncRepositoryHooks to also sync wiki repos
1 parent d330a23 commit fe94032

File tree

3 files changed

+96
-6
lines changed

3 files changed

+96
-6
lines changed

models/migrations/migrations.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ var migrations = []Migration{
100100
NewMigration("change the key_id and primary_key_id type", changeGPGKeysColumns),
101101
// v25 -> v26
102102
NewMigration("add show field in user openid table", addUserOpenIDShow),
103+
// v26 -> v27
104+
NewMigration("generate and migrate repo and wiki Git hooks", generateAndMigrateGitHookChains),
103105
}
104106

105107
// Migrate database to current version

models/migrations/v26.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright 2017 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"crypto/md5"
9+
"encoding/hex"
10+
"fmt"
11+
"io"
12+
"io/ioutil"
13+
"os"
14+
"path/filepath"
15+
"strings"
16+
17+
"code.gitea.io/gitea/modules/setting"
18+
19+
"github.com/Unknwon/com"
20+
"github.com/go-xorm/xorm"
21+
)
22+
23+
func generateAndMigrateGitHookChains(x *xorm.Engine) (err error) {
24+
type Repository struct {
25+
ID int64
26+
OwnerID int64
27+
Name string
28+
}
29+
type User struct {
30+
ID int64
31+
Name string
32+
}
33+
34+
var (
35+
hookNames = []string{"pre-receive", "update", "post-receive"}
36+
hookTpl = fmt.Sprintf("#!/usr/bin/env %s\ndata=$(cat)\nexitcodes=\"\"\nhookname=$(basename $0)\nGIT_DIR=${GIT_DIR:-$(dirname $0)}\n\nfor hook in ${GIT_DIR}/hooks/${hookname}.d/*; do\ntest -x \"${hook}\" || continue\necho \"${data}\" | \"${hook}\"\nexitcodes=\"${exitcodes} $?\"\ndone\n\nfor i in ${exitcodes}; do\n[ ${i} -eq 0 ] || exit ${i}\ndone\n", setting.ScriptType)
37+
)
38+
39+
return x.Where("id > 0").Iterate(new(Repository),
40+
func(idx int, bean interface{}) error {
41+
repo := bean.(*Repository)
42+
user := new(User)
43+
has, err := x.Where("id = ?", repo.OwnerID).Get(user)
44+
if err != nil {
45+
return fmt.Errorf("query owner of repository [repo_id: %d, owner_id: %d]: %v", repo.ID, repo.OwnerID, err)
46+
} else if !has {
47+
return nil
48+
}
49+
50+
repoPaths := []string{
51+
filepath.Join(setting.RepoRootPath, strings.ToLower(user.Name), strings.ToLower(repo.Name)) + ".git",
52+
filepath.Join(setting.RepoRootPath, strings.ToLower(user.Name), strings.ToLower(repo.Name)) + ".wiki.git",
53+
}
54+
55+
for _, repoPath := range repoPaths {
56+
if com.IsExist(repoPath) {
57+
hookDir := filepath.Join(repoPath, "hooks")
58+
59+
for _, hookName := range hookNames {
60+
oldHookPath := filepath.Join(hookDir, hookName)
61+
62+
// compare md5sums of hooks
63+
if com.IsExist(oldHookPath) {
64+
65+
f, err := os.Open(oldHookPath)
66+
if err != nil {
67+
return fmt.Errorf("cannot open old hook file '%s': %v", oldHookPath, err)
68+
}
69+
defer f.Close()
70+
h := md5.New()
71+
if _, err := io.Copy(h, f); err != nil {
72+
return fmt.Errorf("cannot read old hook file '%s': %v", oldHookPath, err)
73+
}
74+
if hex.EncodeToString(h.Sum(nil)) == "6718ef67d0834e0a7908259acd566e3f" {
75+
return nil
76+
}
77+
}
78+
79+
if err = ioutil.WriteFile(oldHookPath, []byte(hookTpl), 0777); err != nil {
80+
return fmt.Errorf("write old hook file '%s': %v", oldHookPath, err)
81+
}
82+
}
83+
}
84+
}
85+
return nil
86+
})
87+
}

models/repo.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -845,11 +845,7 @@ func cleanUpMigrateGitConfig(configPath string) error {
845845
func createDelegateHooks(repoPath string) (err error) {
846846
var (
847847
hookNames = []string{"pre-receive", "update", "post-receive"}
848-
hookTpls = []string{
849-
fmt.Sprintf("#!/usr/bin/env %s\nORI_DIR=`pwd`\nSHELL_FOLDER=$(cd \"$(dirname \"$0\")\";pwd)\ncd \"$ORI_DIR\"\nfor i in `ls \"$SHELL_FOLDER/pre-receive.d\"`; do\n sh \"$SHELL_FOLDER/pre-receive.d/$i\"\ndone", setting.ScriptType),
850-
fmt.Sprintf("#!/usr/bin/env %s\nORI_DIR=`pwd`\nSHELL_FOLDER=$(cd \"$(dirname \"$0\")\";pwd)\ncd \"$ORI_DIR\"\nfor i in `ls \"$SHELL_FOLDER/update.d\"`; do\n sh \"$SHELL_FOLDER/update.d/$i\" $1 $2 $3\ndone", setting.ScriptType),
851-
fmt.Sprintf("#!/usr/bin/env %s\nORI_DIR=`pwd`\nSHELL_FOLDER=$(cd \"$(dirname \"$0\")\";pwd)\ncd \"$ORI_DIR\"\nfor i in `ls \"$SHELL_FOLDER/post-receive.d\"`; do\n sh \"$SHELL_FOLDER/post-receive.d/$i\"\ndone", setting.ScriptType),
852-
}
848+
hookTpl = fmt.Sprintf("#!/usr/bin/env %s\ndata=$(cat)\nexitcodes=\"\"\nhookname=$(basename $0)\nGIT_DIR=${GIT_DIR:-$(dirname $0)}\n\nfor hook in ${GIT_DIR}/hooks/${hookname}.d/*; do\ntest -x \"${hook}\" || continue\necho \"${data}\" | \"${hook}\"\nexitcodes=\"${exitcodes} $?\"\ndone\n\nfor i in ${exitcodes}; do\n[ ${i} -eq 0 ] || exit ${i}\ndone\n", setting.ScriptType)
853849
giteaHookTpls = []string{
854850
fmt.Sprintf("#!/usr/bin/env %s\n\"%s\" hook --config='%s' pre-receive\n", setting.ScriptType, setting.AppPath, setting.CustomConf),
855851
fmt.Sprintf("#!/usr/bin/env %s\n\"%s\" hook --config='%s' update $1 $2 $3\n", setting.ScriptType, setting.AppPath, setting.CustomConf),
@@ -868,7 +864,7 @@ func createDelegateHooks(repoPath string) (err error) {
868864
}
869865

870866
// WARNING: This will override all old server-side hooks
871-
if err = ioutil.WriteFile(oldHookPath, []byte(hookTpls[i]), 0777); err != nil {
867+
if err = ioutil.WriteFile(oldHookPath, []byte(hookTpl), 0777); err != nil {
872868
return fmt.Errorf("write old hook file '%s': %v", oldHookPath, err)
873869
}
874870

@@ -1909,6 +1905,11 @@ func SyncRepositoryHooks() error {
19091905
if err := createDelegateHooks(bean.(*Repository).RepoPath()); err != nil {
19101906
return fmt.Errorf("SyncRepositoryHook: %v", err)
19111907
}
1908+
if bean.(*Repository).HasUncyclo() {
1909+
if err := createDelegateHooks(bean.(*Repository).UncycloPath()); err != nil {
1910+
return fmt.Errorf("SyncRepositoryHook: %v", err)
1911+
}
1912+
}
19121913
return nil
19131914
})
19141915
}

0 commit comments

Comments
 (0)