@@ -9,7 +9,10 @@ import (
99 "fmt"
1010 "io/ioutil"
1111 "os"
12+ "os/exec"
1213 "path/filepath"
14+ "regexp"
15+ "runtime"
1316 "strings"
1417 "time"
1518
@@ -556,10 +559,44 @@ func ConfigRemove(settings map[string]string, wd ...string) error {
556559 return nil
557560}
558561
562+ // GitHook is the Command with options to be added/removed from a git hook
563+ // Exe is the executable file name for Linux/MacOS
564+ // RE is the regex to match on for the command
565+ type GitHook struct {
566+ Exe string
567+ Command string
568+ RE * regexp.Regexp
569+ }
570+
571+ func (g GitHook ) getCommandPath () string {
572+ // save current dir & change to root
573+ // to guarantee we get the full path
574+ wd , err := os .Getwd ()
575+ defer os .Chdir (wd )
576+ os .Chdir (string (filepath .Separator ))
577+
578+ p , err := exec .LookPath (g .getExeForOS ())
579+ if err != nil {
580+ return g .Command
581+ }
582+ if runtime .GOOS == "windows" {
583+ // put "" around file path
584+ return strings .Replace (g .Command , g .Exe , fmt .Sprintf ("\" %s\" " , p ), 1 )
585+ }
586+ return strings .Replace (g .Command , g .Exe , p , 1 )
587+ }
588+
589+ func (g GitHook ) getExeForOS () string {
590+ if runtime .GOOS == "windows" {
591+ return fmt .Sprintf ("gtm.%s" , "exe" )
592+ }
593+ return g .Exe
594+ }
595+
559596// SetHooks creates git hooks
560- func SetHooks (hooks map [string ]string , wd ... string ) error {
597+ func SetHooks (hooks map [string ]GitHook , wd ... string ) error {
561598 const shebang = "#!/bin/sh"
562- for hook , command := range hooks {
599+ for ghfile , hook := range hooks {
563600 var (
564601 p string
565602 err error
@@ -573,7 +610,7 @@ func SetHooks(hooks map[string]string, wd ...string) error {
573610 return err
574611 }
575612 }
576- fp := filepath .Join (p , ".git" , "hooks" , hook )
613+ fp := filepath .Join (p , ".git" , "hooks" , ghfile )
577614 hooksDir := filepath .Join (p , ".git" , "hooks" )
578615
579616 var output string
@@ -596,8 +633,10 @@ func SetHooks(hooks map[string]string, wd ...string) error {
596633 output = fmt .Sprintf ("%s\n %s" , shebang , output )
597634 }
598635
599- if ! strings .Contains (output , command ) {
600- output = fmt .Sprintf ("%s\n %s\n " , output , command )
636+ if hook .RE .MatchString (output ) {
637+ output = hook .RE .ReplaceAllString (output , fmt .Sprintf ("%s" , hook .getCommandPath ()))
638+ } else {
639+ output = fmt .Sprintf ("%s\n %s" , output , hook .getCommandPath ())
601640 }
602641
603642 if err = ioutil .WriteFile (fp , []byte (output ), 0755 ); err != nil {
@@ -613,8 +652,8 @@ func SetHooks(hooks map[string]string, wd ...string) error {
613652}
614653
615654// RemoveHooks remove matching git hook commands
616- func RemoveHooks (hooks map [string ]string , wd ... string ) error {
617- for hook , command := range hooks {
655+ func RemoveHooks (hooks map [string ]GitHook , wd ... string ) error {
656+ for ghfile , hook := range hooks {
618657 var (
619658 p string
620659 err error
@@ -628,7 +667,7 @@ func RemoveHooks(hooks map[string]string, wd ...string) error {
628667 return err
629668 }
630669 }
631- fp := filepath .Join (p , ".git" , "hooks" , hook )
670+ fp := filepath .Join (p , ".git" , "hooks" , ghfile )
632671
633672 if _ , err := os .Stat (fp ); os .IsNotExist (err ) {
634673 continue
@@ -640,8 +679,12 @@ func RemoveHooks(hooks map[string]string, wd ...string) error {
640679 }
641680 output := string (b )
642681
643- if strings .Contains (output , command ) {
644- output = strings .Replace (output , command , "" , - 1 )
682+ if hook .RE .MatchString (output ) {
683+ output := hook .RE .ReplaceAllString (output , "" )
684+ i := strings .LastIndexAny (output , "\n " )
685+ if i > - 1 {
686+ output = output [0 :i ]
687+ }
645688 if err = ioutil .WriteFile (fp , []byte (output ), 0755 ); err != nil {
646689 return err
647690 }
0 commit comments