code.cestus.io/tools/fabricator@v0.4.3/pkg/cmd/plugin.go (about) 1 package cmd 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "os" 8 "path/filepath" 9 "runtime" 10 "strings" 11 12 "code.cestus.io/tools/fabricator/pkg/fabricator" 13 "code.cestus.io/tools/fabricator/pkg/helpers" 14 ) 15 16 // DefaultPluginHandler implements PluginHandler 17 type DefaultPluginHandler struct { 18 ValidPrefixes []string 19 IO fabricator.IOStreams 20 } 21 22 // NewDefaultPluginHandler instantiates the DefaultPluginHandler with a list of 23 // given filename prefixes used to identify valid plugin filenames. 24 func NewDefaultPluginHandler(validPrefixes []string, io fabricator.IOStreams) *DefaultPluginHandler { 25 return &DefaultPluginHandler{ 26 ValidPrefixes: validPrefixes, 27 IO: io, 28 } 29 } 30 31 func findExecutable(file string) error { 32 d, err := os.Stat(file) 33 if err != nil { 34 return err 35 } 36 if runtime.GOOS == "windows" { 37 fileExt := strings.ToLower(filepath.Ext(file)) 38 39 switch fileExt { 40 case ".bat", ".cmd", ".com", ".exe", ".ps1": 41 return nil 42 } 43 return errors.New("not an executable") 44 } 45 if m := d.Mode(); !m.IsDir() && m&0111 != 0 { 46 return nil 47 } 48 return errors.New("not an executable") 49 } 50 51 // Lookup implements PluginHandler 52 func (h *DefaultPluginHandler) Lookup(ctx context.Context, filename string, paths []string) (string, bool) { 53 for _, prefix := range h.ValidPrefixes { 54 for _, dir := range paths { 55 if dir == "" { 56 // Unix shell semantics: path element "" means "." 57 dir = "." 58 } 59 path := filepath.Join(dir, fmt.Sprintf("%s-%s", prefix, filename)) 60 if err := findExecutable(path); err == nil { 61 return path, true 62 } 63 if runtime.GOOS == "windows" { 64 ext := []string{".bat", ".cmd", ".com", ".exe", ".ps1"} 65 for _, e := range ext { 66 np := fmt.Sprintf("%s%s", path, e) 67 if err := findExecutable(np); err == nil { 68 return path, true 69 } 70 } 71 } 72 } 73 } 74 return "", false 75 } 76 77 // Execute implements PluginHandler 78 func (h *DefaultPluginHandler) Execute(ctx context.Context, executablePath string, cmdArgs []string, environment fabricator.Environment) error { 79 executor := helpers.NewExecutor("", h.IO).WithEnvMap(environment) 80 err := executor.Run(ctx, executablePath, cmdArgs...) 81 return err 82 }