mirror of
https://github.com/tailscale/tailscale.git
synced 2026-04-22 14:02:19 +02:00
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>
65 lines
1.6 KiB
Go
65 lines
1.6 KiB
Go
// Copyright (c) Tailscale Inc & contributors
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package githook
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/rand"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
)
|
|
|
|
// AddChangeID strips comments from the commit message at args[0] and
|
|
// prepends a random Change-Id trailer.
|
|
//
|
|
// Intended as a commit-msg hook.
|
|
// https://git-scm.com/docs/githooks#_commit_msg
|
|
func AddChangeID(args []string) error {
|
|
if len(args) != 1 {
|
|
return errors.New("usage: commit-msg message.txt")
|
|
}
|
|
file := args[0]
|
|
msg, err := os.ReadFile(file)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
msg = filterCutLine(msg)
|
|
|
|
var id [20]byte
|
|
if _, err := io.ReadFull(rand.Reader, id[:]); err != nil {
|
|
return fmt.Errorf("could not generate Change-Id: %v", err)
|
|
}
|
|
cmdLines := [][]string{
|
|
{"git", "stripspace", "--strip-comments"},
|
|
{"git", "interpret-trailers", "--no-divider", "--where=start", "--if-exists", "doNothing", "--trailer", fmt.Sprintf("Change-Id: I%x", id)},
|
|
}
|
|
for _, cmdLine := range cmdLines {
|
|
if len(msg) == 0 {
|
|
// Don't let commands turn an empty message into a non-empty one (issue 2205).
|
|
break
|
|
}
|
|
cmd := exec.Command(cmdLine[0], cmdLine[1:]...)
|
|
cmd.Stdin = bytes.NewReader(msg)
|
|
msg, err = cmd.CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to run %v: %w\n%s", cmd, err, msg)
|
|
}
|
|
}
|
|
return os.WriteFile(file, msg, 0666)
|
|
}
|
|
|
|
var gitCutLine = []byte("# ------------------------ >8 ------------------------")
|
|
|
|
// filterCutLine strips a `git commit -v`-style cutline and everything
|
|
// after it from msg.
|
|
func filterCutLine(msg []byte) []byte {
|
|
if before, _, ok := bytes.Cut(msg, gitCutLine); ok {
|
|
return before
|
|
}
|
|
return msg
|
|
}
|