github.com/mayra-cabrera/buffalo@v0.9.4-0.20170814145312-66d2e7772f11/plugins/plugins.go (about) 1 package plugins 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "fmt" 8 "os" 9 "os/exec" 10 "path/filepath" 11 "runtime" 12 "strings" 13 "time" 14 15 "github.com/pkg/errors" 16 ) 17 18 // List maps a Buffalo command to a slice of Command 19 type List map[string]Commands 20 21 // Available plugins for the `buffalo` command. 22 // It will look in $PATH and the `./plugins` directory. 23 // 24 // Requirements: 25 // * file/command must be executable 26 // * file/command must start with `buffalo-` 27 // * file/command must respond to `available` and return JSON of 28 // plugins.Commands{} 29 // 30 // Caveats: 31 // * The C:\Windows directory is excluded 32 func Available() (List, error) { 33 list := List{} 34 paths := []string{"plugins"} 35 if runtime.GOOS == "windows" { 36 paths = append(paths, strings.Split(os.Getenv("PATH"), ";")...) 37 } else { 38 paths = append(paths, strings.Split(os.Getenv("PATH"), ":")...) 39 } 40 for _, p := range paths { 41 if strings.HasPrefix(strings.ToLower(p), `c:\windows`) { 42 continue 43 } 44 if _, err := os.Stat(p); err != nil { 45 continue 46 } 47 err := filepath.Walk(p, func(path string, info os.FileInfo, err error) error { 48 if err != nil { 49 // May indicate a permissions problem with the path, skip it 50 return nil 51 } 52 if info.IsDir() { 53 return nil 54 } 55 base := filepath.Base(path) 56 if strings.HasPrefix(base, "buffalo-") { 57 commands := askBin(path) 58 for _, c := range commands { 59 bc := c.BuffaloCommand 60 if _, ok := list[bc]; !ok { 61 list[bc] = Commands{} 62 } 63 c.Binary = path 64 list[bc] = append(list[bc], c) 65 } 66 } 67 return nil 68 }) 69 if err != nil { 70 return nil, errors.WithStack(err) 71 } 72 } 73 return list, nil 74 } 75 76 func askBin(path string) Commands { 77 commands := Commands{} 78 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 79 defer cancel() 80 cmd := exec.CommandContext(ctx, path, "available") 81 bb := &bytes.Buffer{} 82 cmd.Stdout = bb 83 cmd.Stderr = bb 84 err := cmd.Run() 85 if err != nil { 86 fmt.Printf("[PLUGIN] error loading plugin %s: %s\n%s\n", path, err, bb.String()) 87 return commands 88 } 89 err = json.NewDecoder(bb).Decode(&commands) 90 if err != nil { 91 fmt.Printf("[PLUGIN] error loading plugin %s: %s\n", path, err) 92 return commands 93 } 94 return commands 95 }