github.com/kekek/gb@v0.4.5-0.20170222120241-d4ba64b0b297/cmd/cmd.go (about) 1 // Package command holds support functions and types for writing gb and gb plugins 2 package cmd 3 4 import ( 5 "flag" 6 "os" 7 8 "github.com/constabulary/gb" 9 "github.com/constabulary/gb/internal/debug" 10 "github.com/pkg/errors" 11 ) 12 13 // Command represents a subcommand, or plugin that is executed within 14 // a gb project. 15 type Command struct { 16 // Name of the command 17 Name string 18 19 // UsageLine demonstrates how to use this command 20 UsageLine string 21 22 // Single line description of the purpose of the command 23 Short string 24 25 // Description of this command 26 Long string 27 28 // Run is invoked with a Context derived from the Project and arguments 29 // left over after flag parsing. 30 Run func(ctx *gb.Context, args []string) error 31 32 // AddFlags installs additional flags to be parsed before Run. 33 AddFlags func(fs *flag.FlagSet) 34 35 // Allow plugins to modify arguments 36 FlagParse func(fs *flag.FlagSet, args []string) error 37 38 // SkipParseArgs avoids parsing arguments as import paths. 39 SkipParseArgs bool 40 } 41 42 // Runnable indicates this is a command that can be involved. 43 // Non runnable commands are only informational. 44 func (c *Command) Runnable() bool { return c.Run != nil } 45 46 // Hidden indicates this is a command which is hidden from help / alldoc.go. 47 func (c *Command) Hidden() bool { return c.Name == "depset" } 48 49 // RunCommand detects the project root, parses flags and runs the Command. 50 func RunCommand(fs *flag.FlagSet, cmd *Command, projectroot, goroot string, args []string) error { 51 if cmd.AddFlags != nil { 52 cmd.AddFlags(fs) 53 } 54 if err := fs.Parse(args); err != nil { 55 fs.Usage() 56 os.Exit(1) 57 } 58 args = fs.Args() // reset to the remaining arguments 59 60 ctx, err := NewContext(projectroot, gb.GcToolchain()) 61 if err != nil { 62 return errors.Wrap(err, "unable to construct context") 63 } 64 defer ctx.Destroy() 65 66 debug.Debugf("args: %v", args) 67 return cmd.Run(ctx, args) 68 } 69 70 // NewContext creates a gb.Context for the project root. 71 func NewContext(projectroot string, options ...func(*gb.Context) error) (*gb.Context, error) { 72 if projectroot == "" { 73 return nil, errors.New("project root is blank") 74 } 75 76 root, err := FindProjectroot(projectroot) 77 if err != nil { 78 return nil, errors.Wrap(err, "could not locate project root") 79 } 80 proj := gb.NewProject(root) 81 82 debug.Debugf("project root %q", proj.Projectdir()) 83 return gb.NewContext(proj, options...) 84 }