github.com/gobuffalo/buffalo-cli/v2@v2.0.0-alpha.15.0.20200919213536-a7350c8e6799/cli/cmds/newapp/cmd.go (about) 1 package newapp 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "io" 8 "os" 9 "os/exec" 10 "path" 11 "path/filepath" 12 "text/template" 13 14 "github.com/gobuffalo/buffalo-cli/v2/cli/cmds/newapp/presets" 15 "github.com/gobuffalo/buffalo-cli/v2/cli/internal/cligen" 16 "github.com/gobuffalo/plugins" 17 "github.com/gobuffalo/plugins/plugcmd" 18 "github.com/gobuffalo/plugins/plugio" 19 "github.com/spf13/pflag" 20 ) 21 22 var _ plugins.Plugin = &Cmd{} 23 var _ plugcmd.Commander = &Cmd{} 24 var _ plugcmd.Namer = &Cmd{} 25 var _ plugins.Needer = &Cmd{} 26 var _ plugins.Scoper = &Cmd{} 27 28 type Cmd struct { 29 pluginsFn plugins.Feeder 30 flags *pflag.FlagSet 31 help bool 32 force bool 33 presets []string 34 usePlugs map[string]string 35 } 36 37 func (Cmd) PluginName() string { 38 return "newapp/cmd" 39 } 40 41 func (Cmd) CmdName() string { 42 return "new" 43 } 44 45 func (cmd *Cmd) WithPlugins(f plugins.Feeder) { 46 cmd.pluginsFn = f 47 } 48 49 func (cmd *Cmd) ScopedPlugins() []plugins.Plugin { 50 if cmd.pluginsFn == nil { 51 return nil 52 } 53 54 var plugs []plugins.Plugin 55 56 for _, p := range cmd.pluginsFn() { 57 switch p.(type) { 58 case Stdouter: 59 plugs = append(plugs, p) 60 case Stdiner: 61 plugs = append(plugs, p) 62 case Stderrer: 63 plugs = append(plugs, p) 64 case NewCommandRunner: 65 plugs = append(plugs, p) 66 } 67 } 68 69 return plugs 70 } 71 72 func (cmd *Cmd) Main(ctx context.Context, root string, args []string) error { 73 flags := cmd.Flags() 74 flags.BoolVarP(&cmd.help, "help", "h", false, "print this help") 75 if err := flags.Parse(args); err != nil { 76 return plugins.Wrap(cmd, err) 77 } 78 79 var modName string 80 plugs := cmd.ScopedPlugins() 81 if cmd.help { 82 modName = "clitmp" 83 defer os.RemoveAll(filepath.Join(root, modName)) 84 } 85 86 if len(modName) == 0 { 87 modName = flags.Args()[0] 88 } 89 90 if len(args) == 0 { 91 return plugins.Wrap(cmd, fmt.Errorf("missing application name")) 92 } 93 94 sargs := make([]string, 0, len(args)) 95 for _, a := range args { 96 if a == modName { 97 continue 98 } 99 sargs = append(sargs, a) 100 } 101 args = sargs 102 103 dirName := path.Base(modName) 104 105 root = filepath.Join(root, dirName) 106 if cmd.force { 107 os.RemoveAll(root) 108 } 109 110 if err := os.MkdirAll(root, 0755); err != nil { 111 return plugins.Wrap(cmd, err) 112 } 113 114 os.Chdir(root) 115 116 if err := cmd.modInit(ctx, root, modName); err != nil { 117 return plugins.Wrap(cmd, err) 118 } 119 120 if cmd.usePlugs == nil { 121 cmd.usePlugs = map[string]string{} 122 } 123 if len(cmd.presets) == 0 { 124 cmd.presets = append(cmd.presets, "web") 125 } 126 127 pres := presets.Presets() 128 for _, p := range cmd.presets { 129 if v, ok := pres[p]; ok { 130 cmd.usePlugs[p] = v 131 continue 132 } 133 cmd.usePlugs[path.Base(p)] = p 134 } 135 136 tmpl, err := template.New("").Parse(cliMain) 137 if err != nil { 138 return plugins.Wrap(cmd, err) 139 } 140 141 cd := filepath.Join(root, "cmd", "newapp") 142 if err := os.MkdirAll(cd, 0755); err != nil { 143 return plugins.Wrap(cmd, err) 144 } 145 146 w, err := os.Create(filepath.Join(cd, "main.go")) 147 if err != nil { 148 return err 149 } 150 defer w.Close() 151 152 err = tmpl.Execute(w, map[string]interface{}{ 153 "Plugs": cmd.usePlugs, 154 "Args": fmt.Sprintf("%#v", args), 155 "Name": modName, 156 }) 157 if err != nil { 158 return plugins.Wrap(cmd, err) 159 } 160 161 g := &cligen.Generator{ 162 Plugins: cmd.usePlugs, 163 } 164 if err := g.Generate(ctx, root, args); err != nil { 165 return plugins.Wrap(cmd, err) 166 } 167 168 os.Chdir(root) 169 170 c := exec.CommandContext(ctx, "go", "run", "./cmd/newapp") 171 c.Args = append(c.Args, args...) 172 c.Stdout = plugio.Stdout(plugs...) 173 c.Stderr = plugio.Stderr(plugs...) 174 c.Stdin = plugio.Stdin(plugs...) 175 176 for _, p := range plugs { 177 if vr, ok := p.(NewCommandRunner); ok { 178 if err := vr.RunNewCommand(ctx, root, c); err != nil { 179 return plugins.Wrap(cmd, err) 180 } 181 return nil 182 } 183 } 184 185 bb := &bytes.Buffer{} 186 c.Stderr = io.MultiWriter(bb, c.Stderr) 187 if err := c.Run(); err != nil { 188 return plugins.Wrap(cmd, fmt.Errorf("%w: %s", err, bb.String())) 189 } 190 return nil 191 } 192 193 const cliMain = ` 194 package main 195 196 import ( 197 "context" 198 "log" 199 "os" 200 201 "github.com/gobuffalo/buffalo-cli/v2/cli/cmds/newapp" 202 "github.com/gobuffalo/plugins" 203 {{range $k,$v := .Plugs }} 204 {{$k}} "{{$v}}"{{end}} 205 ) 206 207 func main() { 208 ctx := context.Background() 209 pwd, err := os.Getwd() 210 if err != nil { 211 log.Fatal(err) 212 } 213 214 var plugs []plugins.Plugin 215 {{range $k,$v := .Plugs }} 216 plugs = append(plugs, {{$k}}.Plugins()...){{end}} 217 218 args := {{.Args}} 219 if err := newapp.Execute(plugs, ctx, pwd, "{{.Name}}", args); err != nil { 220 log.Fatal(err) 221 } 222 } 223 `