gitlab.com/pidrakin/dotfiles-cli@v1.7.5/cmd/link/hooks.go (about) 1 package link 2 3 import ( 4 log "github.com/sirupsen/logrus" 5 "gitlab.com/pidrakin/dotfiles-cli/exec" 6 "gitlab.com/pidrakin/dotfiles-cli/text" 7 "gitlab.com/pidrakin/go/sysfs" 8 "os" 9 exec2 "os/exec" 10 "path" 11 ) 12 13 type HookType int 14 15 func (h HookType) String() string { 16 return [...]string{"pre-link", "post-link"}[h-1] 17 } 18 19 type HookEnum struct { 20 PRE HookType 21 POST HookType 22 } 23 24 var hook = HookEnum{ 25 PRE: 1, 26 POST: 2, 27 } 28 29 func runHook(basepath string, hooktype HookType, collection string) (found bool, succeeded bool, err error) { 30 var hookpath string 31 found, hookpath = findHook(basepath, hooktype, collection) 32 if err != nil { 33 return 34 } 35 if found { 36 succeeded = true 37 if err = executeHook(hookpath); err != nil { 38 if _, ok := err.(*exec2.ExitError); ok { 39 succeeded = false 40 err = nil 41 } 42 } 43 } 44 return 45 } 46 47 func isExecutable(mode os.FileMode) bool { 48 return mode&0111 != 0 49 } 50 51 func findHook(basepath string, hooktype HookType, collection string) (found bool, hookpath string) { 52 dir := path.Join(basepath, ".dotfiles/hooks") 53 if collection != "" { 54 dir = path.Join(dir, collection) 55 } 56 hookpath = path.Join(dir, hooktype.String()) 57 58 if info, osErr := os.Stat(hookpath); !os.IsNotExist(osErr) { 59 found = true 60 if !isExecutable(info.Mode()) { 61 log.WithField("hook", hookpath).Debug(text.HookNotExecutable) 62 } 63 return 64 } 65 return 66 } 67 68 func executeHook(hook string) error { 69 log.WithField("hook", hook).Info(text.ExecuteHook) 70 if !sysfs.DryRun { 71 out, err := exec.Command(hook) 72 if err != nil { 73 log.WithField("hook", hook).Errorf("hook failed\n%s", out) 74 if _, ok := err.(*exec2.ExitError); ok { 75 return err 76 } 77 } else { 78 log.WithField("hook", hook).Debugf("hook succeeded\n%s", out) 79 } 80 } 81 return nil 82 }