summarylogtreecommitdiffstats
path: root/pluginhook.go
diff options
context:
space:
mode:
Diffstat (limited to 'pluginhook.go')
-rw-r--r--pluginhook.go93
1 files changed, 93 insertions, 0 deletions
diff --git a/pluginhook.go b/pluginhook.go
new file mode 100644
index 000000000000..5ee57a0b44f8
--- /dev/null
+++ b/pluginhook.go
@@ -0,0 +1,93 @@
+package main
+
+import (
+ "os"
+ "fmt"
+ "os/exec"
+ "syscall"
+ "path/filepath"
+ "log"
+ "flag"
+ "bytes"
+ "strings"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+func main() {
+ var parallel = flag.Bool("p", false, "Run hooks in parallel")
+ var trace = flag.Bool("x", false, "Trace mode")
+ flag.Parse()
+
+ if len(os.Getenv("PLUGINHOOK_TRACE")) > 0 {
+ *trace = true
+ }
+
+ pluginPath := os.Getenv("PLUGIN_PATH")
+ if pluginPath == "" {
+ log.Fatal("[ERROR] Unable to locate plugins: set $PLUGIN_PATH\n")
+ os.Exit(1)
+ }
+ if flag.NArg() < 1 {
+ log.Fatal("[ERROR] Hook name argument is required\n")
+ os.Exit(1)
+ }
+ cmds := make([]exec.Cmd, 0)
+ var matches, _ = filepath.Glob(fmt.Sprintf("%s/*/%s", pluginPath, flag.Arg(0)))
+ for _, hook := range matches {
+ cmd := exec.Command(hook, flag.Args()[1:]...)
+ cmds = append(cmds, *cmd)
+ }
+ for i := len(cmds)-1; i >= 0; i-- {
+ cmds[i].Stderr = os.Stderr
+
+ if i == len(cmds)-1 {
+ cmds[i].Stdout = os.Stdout
+ }
+ if i > 0 {
+ if *parallel {
+ stdout, err := cmds[i-1].StdoutPipe()
+ if err != nil {
+ log.Fatal(err)
+ }
+ cmds[i].Stdin = stdout
+ } else {
+ var buf bytes.Buffer
+ cmds[i-1].Stdout = &buf
+ cmds[i].Stdin = &buf
+ }
+ }
+ if i == 0 && !terminal.IsTerminal(syscall.Stdin) {
+ cmds[i].Stdin = os.Stdin
+ }
+ }
+
+ if *parallel {
+ done := make(chan bool, len(cmds))
+
+ for i := 0; i < len(cmds); i++ {
+ go func(cmd exec.Cmd, i int) {
+ if *trace {
+ fmt.Fprintln(os.Stderr, "+", strings.Join(cmds[i].Args, " "))
+ }
+ err := cmd.Run()
+ if msg, ok := err.(*exec.ExitError); ok { // there is error code
+ os.Exit(msg.Sys().(syscall.WaitStatus).ExitStatus())
+ }
+ done <- true
+ }(cmds[i], i)
+ }
+ for i := 0; i < len(cmds); i++ {
+ <-done
+ }
+ } else {
+ for i := 0; i < len(cmds); i++ {
+ if *trace {
+ fmt.Fprintln(os.Stderr, "+", strings.Join(cmds[i].Args, " "))
+ }
+ err := cmds[i].Run()
+ if msg, ok := err.(*exec.ExitError); ok { // there is error code
+ os.Exit(msg.Sys().(syscall.WaitStatus).ExitStatus())
+ }
+ }
+ }
+}