misc/git_hook: extract shared githook package; auto-rebuild on version bump (#19440)
Pull the hook logic into a reusable githook library package so tailscale/corp can share it via a thin wrapper main instead of keeping a forked copy in sync. The install flow also changes: a wrapper scripts now build the binary and reinstall the git hooks. Pulling new shared code no longer requires re-running the installer. Updates tailscale/corp#39860 Change-Id: I4d606d11c8c883015c190c54e3387a7f9fe4dd32 Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
This commit is contained in:
committed by
GitHub
parent
1fbb834dc3
commit
514d7d28e7
@@ -3,80 +3,19 @@
|
||||
|
||||
//go:build ignore
|
||||
|
||||
// The install-git-hooks program installs git hooks.
|
||||
//
|
||||
// It installs a Go binary at .git/hooks/ts-git-hook and a pre-hook
|
||||
// forwarding shell wrapper to .git/hooks/NAME.
|
||||
// The install-git-hooks program installs git hooks by delegating to
|
||||
// githook.Install. See that function's doc for what it does.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"tailscale.com/misc/git_hook/githook"
|
||||
)
|
||||
|
||||
var hooks = []string{
|
||||
"pre-push",
|
||||
"pre-commit",
|
||||
"commit-msg",
|
||||
"post-checkout",
|
||||
}
|
||||
|
||||
func fatalf(format string, a ...any) {
|
||||
log.SetFlags(0)
|
||||
log.Fatalf("install-git-hooks: "+format, a...)
|
||||
}
|
||||
|
||||
func main() {
|
||||
out, err := exec.Command("git", "rev-parse", "--git-common-dir").CombinedOutput()
|
||||
if err != nil {
|
||||
fatalf("finding git dir: %v, %s", err, out)
|
||||
}
|
||||
gitDir := strings.TrimSpace(string(out))
|
||||
|
||||
hookDir := filepath.Join(gitDir, "hooks")
|
||||
if fi, err := os.Stat(hookDir); err != nil {
|
||||
fatalf("checking hooks dir: %v", err)
|
||||
} else if !fi.IsDir() {
|
||||
fatalf("%s is not a directory", hookDir)
|
||||
}
|
||||
|
||||
buildOut, err := exec.Command(goBin(), "build",
|
||||
"-o", filepath.Join(hookDir, "ts-git-hook"+exe()),
|
||||
"./misc/git_hook").CombinedOutput()
|
||||
if err != nil {
|
||||
log.Fatalf("go build git-hook: %v, %s", err, buildOut)
|
||||
}
|
||||
|
||||
for _, hook := range hooks {
|
||||
content := fmt.Sprintf(hookScript, hook)
|
||||
file := filepath.Join(hookDir, hook)
|
||||
// Install the hook. If it already exists, overwrite it, in case there's
|
||||
// been changes.
|
||||
if err := os.WriteFile(file, []byte(content), 0755); err != nil {
|
||||
fatalf("%v", err)
|
||||
}
|
||||
log.SetFlags(0)
|
||||
if err := githook.Install(); err != nil {
|
||||
log.Fatalf("install-git-hooks: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
const hookScript = `#!/usr/bin/env bash
|
||||
exec "$(dirname ${BASH_SOURCE[0]})/ts-git-hook" %s "$@"
|
||||
`
|
||||
|
||||
func goBin() string {
|
||||
if p, err := exec.LookPath("go"); err == nil {
|
||||
return p
|
||||
}
|
||||
return "go"
|
||||
}
|
||||
|
||||
func exe() string {
|
||||
if runtime.GOOS == "windows" {
|
||||
return ".exe"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user