pass hook configuration through CLI arguments

This commit is contained in:
Jabberwocky238
2026-07-30 01:15:49 -04:00
parent 1e5b0225f5
commit 8d299013f9
4 changed files with 54 additions and 36 deletions
+30 -20
View File
@@ -33,6 +33,10 @@ func Run(args []string) {
return nil
})
fs.StringVar(&cfg.HookScript, "hook-script", "./hook.sh", "script run by every Git hook; receives hook type and owner/name as its first two arguments")
fs.Func("hook-arg", "fixed argument passed to -hook-script before hook type and owner/name (repeatable)", func(arg string) error {
cfg.HookArgs = append(cfg.HookArgs, arg)
return nil
})
fs.StringVar(&cfg.DBUri, "db", "sqlite://./db.sqlite", "private state DB URI (sqlite://<path> or postgres://<dsn>) - backs PAT/SSH-key ACLs and repo metadata")
fs.Parse(args)
@@ -51,9 +55,6 @@ func Run(args []string) {
app := NewApp(cfg.RepoRoot(), store)
server := gitrpc.NewServer(&cfg, store)
if _, err := ensureHookTemplate(cfg.Root); err != nil {
log.Printf("simplegit: hook template: %v (hooks disabled)", err)
}
if cfg.HookScript != "" {
hookScript, err := resolveHookScript(cfg.HookScript)
if err != nil {
@@ -67,15 +68,10 @@ func Run(args []string) {
log.Fatalf("simplegit: hook script %s is not executable", hookScript)
}
cfg.HookScript = hookScript
_ = os.Setenv("SIMPLEGIT_HOOK_SCRIPT", hookScript)
repoRoot, err := filepath.Abs(cfg.RepoRoot())
if err != nil {
log.Fatalf("simplegit: resolve repository root: %v", err)
}
_ = os.Setenv("SIMPLEGIT_REPO_ROOT", repoRoot)
log.Printf("simplegit: Git hooks execute %s", hookScript)
} else {
_ = os.Unsetenv("SIMPLEGIT_HOOK_SCRIPT")
log.Printf("simplegit: Git hooks execute %s %s", hookScript, strings.Join(cfg.HookArgs, " "))
}
if _, err := ensureHookTemplate(cfg.Root, cfg.HookScript, cfg.HookArgs); err != nil {
log.Printf("simplegit: hook template: %v (hooks disabled)", err)
}
// gitrpc mux: Connect-RPC (GitService + ManageService) + the binary content
@@ -153,16 +149,18 @@ var gitHookNames = []string{
"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
const hookWrapperTemplate = `#!/bin/sh
# Generated by simplegit. The operator controls behavior with -hook-script.
repo_dir=$(pwd -P)
repo=${repo_dir#"$SIMPLEGIT_REPO_ROOT"/}
repo=${repo%%.git}
exec "$SIMPLEGIT_HOOK_SCRIPT" %s "$repo" "$@"
repo_name=${repo_dir##*/}
repo_name=${repo_name%%.git}
owner_dir=${repo_dir%%/*}
owner=${owner_dir##*/}
repo=$owner/$repo_name
exec %s %s "$repo" "$@"
`
func ensureHookTemplate(root string) (string, error) {
func ensureHookTemplate(root, script string, args []string) (string, error) {
dir := filepath.Join(root, "template")
hooksDir := filepath.Join(dir, "hooks")
if err := os.MkdirAll(hooksDir, 0o755); err != nil {
@@ -170,7 +168,15 @@ func ensureHookTemplate(root string) (string, error) {
}
for _, name := range gitHookNames {
path := filepath.Join(hooksDir, name)
if err := os.WriteFile(path, []byte(fmt.Sprintf(hookWrapper, name)), 0o755); err != nil {
body := "#!/bin/sh\nexit 0\n"
if script != "" {
command := shellQuote(script)
for _, arg := range args {
command += " " + shellQuote(arg)
}
body = fmt.Sprintf(hookWrapperTemplate, command, shellQuote(name))
}
if err := os.WriteFile(path, []byte(body), 0o755); err != nil {
return "", fmt.Errorf("write hook %s: %w", name, err)
}
}
@@ -180,6 +186,10 @@ func ensureHookTemplate(root string) (string, error) {
return dir, nil
}
func shellQuote(value string) string {
return "'" + strings.ReplaceAll(value, "'", `'"'"'`) + "'"
}
func refreshRepositoryHooks(reposRoot, templateHooks string) error {
if _, err := os.Stat(reposRoot); os.IsNotExist(err) {
return nil