78 lines
2.4 KiB
Go
78 lines
2.4 KiB
Go
package common
|
|
|
|
import (
|
|
"fmt"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
var gitHookNames = []string{
|
|
"pre-receive", "update", "post-receive", "post-update", "proc-receive",
|
|
"push-to-checkout", "reference-transaction", "pre-applypatch",
|
|
"post-applypatch", "pre-commit", "pre-merge-commit", "prepare-commit-msg",
|
|
"commit-msg", "post-commit", "pre-rebase", "post-checkout", "post-merge",
|
|
"pre-push", "pre-auto-gc", "post-rewrite", "sendemail-validate",
|
|
"fsmonitor-watchman", "p4-pre-submit", "p4-post-changelist",
|
|
"p4-prepare-changelist", "p4-changelist",
|
|
}
|
|
|
|
const hookWrapper = `#!/bin/sh
|
|
# Generated by simplegit. The operator controls hook behavior with -hook-script.
|
|
test -n "$SIMPLEGIT_HOOK_SCRIPT" || exit 0
|
|
repo_dir=$(pwd -P)
|
|
repo=${repo_dir#"$SIMPLEGIT_REPO_ROOT"/}
|
|
repo=${repo%%.git}
|
|
exec "$SIMPLEGIT_HOOK_SCRIPT" %s "$repo" "$@"
|
|
`
|
|
|
|
// EnsureHookTemplate creates the git-init template used for new repositories.
|
|
// All hook entrypoints delegate to one environment-specific external script.
|
|
func EnsureHookTemplate(root string) (string, error) {
|
|
dir := filepath.Join(root, "template")
|
|
hooksDir := filepath.Join(dir, "hooks")
|
|
if err := os.MkdirAll(hooksDir, 0o755); err != nil {
|
|
return "", fmt.Errorf("create hook template: %w", err)
|
|
}
|
|
for _, name := range gitHookNames {
|
|
path := filepath.Join(hooksDir, name)
|
|
if err := os.WriteFile(path, []byte(fmt.Sprintf(hookWrapper, name)), 0o755); err != nil {
|
|
return "", fmt.Errorf("write hook %s: %w", name, err)
|
|
}
|
|
}
|
|
if err := refreshRepositoryHooks(filepath.Join(root, "repos"), hooksDir); err != nil {
|
|
return "", err
|
|
}
|
|
return dir, nil
|
|
}
|
|
|
|
// refreshRepositoryHooks updates repositories created with an older template.
|
|
func refreshRepositoryHooks(reposRoot, templateHooks string) error {
|
|
if _, err := os.Stat(reposRoot); os.IsNotExist(err) {
|
|
return nil
|
|
}
|
|
return filepath.WalkDir(reposRoot, func(path string, entry fs.DirEntry, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !entry.IsDir() || !strings.HasSuffix(entry.Name(), ".git") {
|
|
return nil
|
|
}
|
|
dst := filepath.Join(path, "hooks")
|
|
if err := os.MkdirAll(dst, 0o755); err != nil {
|
|
return err
|
|
}
|
|
for _, name := range gitHookNames {
|
|
body, err := os.ReadFile(filepath.Join(templateHooks, name))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := os.WriteFile(filepath.Join(dst, name), body, 0o755); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return filepath.SkipDir
|
|
})
|
|
}
|