From 3a2c95cc2f1f808bfd41136cc80289f39d602637 Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Sun, 15 Mar 2015 02:31:41 -0700 Subject: [PATCH] Godep updates --- Godeps/Godeps.json | 4 +- .../src/github.com/codegangsta/cli/app.go | 57 +++++++++++++--- .../github.com/codegangsta/cli/app_test.go | 68 +++++++++++++++++++ .../src/github.com/codegangsta/cli/command.go | 8 ++- .../src/github.com/codegangsta/cli/context.go | 5 ++ .../codegangsta/cli/context_test.go | 12 ++++ .../src/github.com/codegangsta/cli/help.go | 13 ++-- 7 files changed, 151 insertions(+), 16 deletions(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 19d7394b..eaec7c41 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -9,8 +9,8 @@ }, { "ImportPath": "github.com/codegangsta/cli", - "Comment": "1.2.0-66-g6086d79", - "Rev": "6086d7927ec35315964d9fea46df6c04e6d697c1" + "Comment": "1.2.0-87-g8ce64f1", + "Rev": "8ce64f19ff08029a69d11b7615c9b591245450ad" }, { "ImportPath": "github.com/coreos/coreos-cloudinit/config", diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/app.go b/Godeps/_workspace/src/github.com/codegangsta/cli/app.go index 6422345d..3d4ed120 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/app.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/app.go @@ -34,15 +34,20 @@ type App struct { // An action to execute before any subcommands are run, but after the context is ready // If a non-nil error is returned, no subcommands are run Before func(context *Context) error + // An action to execute after any subcommands are run, but after the subcommand has finished + // It is run even if Action() panics + After func(context *Context) error // The action to execute when no subcommands are specified Action func(context *Context) // Execute this function if the proper command cannot be found CommandNotFound func(context *Context, command string) // Compilation date Compiled time.Time - // Author + // List of all authors who contributed + Authors []Author + // Name of Author (Note: Use App.Authors, this is deprecated) Author string - // Author e-mail + // Email of Author (Note: Use App.Authors, this is deprecated) Email string // Writer writer to write output to Writer io.Writer @@ -67,14 +72,16 @@ func NewApp() *App { BashComplete: DefaultAppComplete, Action: helpCommand.Action, Compiled: compileTime(), - Author: "Author", - Email: "unknown@email", Writer: os.Stdout, } } // Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination -func (a *App) Run(arguments []string) error { +func (a *App) Run(arguments []string) (err error) { + if a.Author != "" || a.Email != "" { + a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email}) + } + if HelpPrinter == nil { defer func() { HelpPrinter = nil @@ -111,7 +118,7 @@ func (a *App) Run(arguments []string) error { // parse flags set := flagSet(a.Name, a.Flags) set.SetOutput(ioutil.Discard) - err := set.Parse(arguments[1:]) + err = set.Parse(arguments[1:]) nerr := normalizeFlags(a.Flags, set) if nerr != nil { fmt.Fprintln(a.Writer, nerr) @@ -141,6 +148,15 @@ func (a *App) Run(arguments []string) error { return nil } + if a.After != nil { + defer func() { + // err is always nil here. + // There is a check to see if it is non-nil + // just few lines before. + err = a.After(context) + }() + } + if a.Before != nil { err := a.Before(context) if err != nil { @@ -171,7 +187,7 @@ func (a *App) RunAndExitOnError() { } // Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags -func (a *App) RunAsSubcommand(ctx *Context) error { +func (a *App) RunAsSubcommand(ctx *Context) (err error) { // append help to commands if len(a.Commands) > 0 { if a.Command(helpCommand.Name) == nil && !a.HideHelp { @@ -190,7 +206,7 @@ func (a *App) RunAsSubcommand(ctx *Context) error { // parse flags set := flagSet(a.Name, a.Flags) set.SetOutput(ioutil.Discard) - err := set.Parse(ctx.Args().Tail()) + err = set.Parse(ctx.Args().Tail()) nerr := normalizeFlags(a.Flags, set) context := NewContext(a, set, ctx.globalSet) @@ -225,6 +241,15 @@ func (a *App) RunAsSubcommand(ctx *Context) error { } } + if a.After != nil { + defer func() { + // err is always nil here. + // There is a check to see if it is non-nil + // just few lines before. + err = a.After(context) + }() + } + if a.Before != nil { err := a.Before(context) if err != nil { @@ -273,3 +298,19 @@ func (a *App) appendFlag(flag Flag) { a.Flags = append(a.Flags, flag) } } + +// Author represents someone who has contributed to a cli project. +type Author struct { + Name string // The Authors name + Email string // The Authors email +} + +// String makes Author comply to the Stringer interface, to allow an easy print in the templating process +func (a Author) String() string { + e := "" + if a.Email != "" { + e = "<" + a.Email + "> " + } + + return fmt.Sprintf("%v %v", a.Name, e) +} diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/app_test.go b/Godeps/_workspace/src/github.com/codegangsta/cli/app_test.go index 2cbb0e3a..6143d364 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/app_test.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/app_test.go @@ -21,6 +21,9 @@ func ExampleApp() { app.Action = func(c *cli.Context) { fmt.Printf("Hello %v\n", c.String("name")) } + app.Author = "Harrison" + app.Email = "harrison@lolwut.com" + app.Authors = []cli.Author{{"Oliver Allen", "oliver@toyshop.com"}} app.Run(os.Args) // Output: // Hello Jeremy @@ -446,6 +449,71 @@ func TestApp_BeforeFunc(t *testing.T) { } +func TestApp_AfterFunc(t *testing.T) { + afterRun, subcommandRun := false, false + afterError := fmt.Errorf("fail") + var err error + + app := cli.NewApp() + + app.After = func(c *cli.Context) error { + afterRun = true + s := c.String("opt") + if s == "fail" { + return afterError + } + + return nil + } + + app.Commands = []cli.Command{ + cli.Command{ + Name: "sub", + Action: func(c *cli.Context) { + subcommandRun = true + }, + }, + } + + app.Flags = []cli.Flag{ + cli.StringFlag{Name: "opt"}, + } + + // run with the After() func succeeding + err = app.Run([]string{"command", "--opt", "succeed", "sub"}) + + if err != nil { + t.Fatalf("Run error: %s", err) + } + + if afterRun == false { + t.Errorf("After() not executed when expected") + } + + if subcommandRun == false { + t.Errorf("Subcommand not executed when expected") + } + + // reset + afterRun, subcommandRun = false, false + + // run with the Before() func failing + err = app.Run([]string{"command", "--opt", "fail", "sub"}) + + // should be the same error produced by the Before func + if err != afterError { + t.Errorf("Run error expected, but not received") + } + + if afterRun == false { + t.Errorf("After() not executed when expected") + } + + if subcommandRun == false { + t.Errorf("Subcommand not executed when expected") + } +} + func TestAppNoHelpFlag(t *testing.T) { oldFlag := cli.HelpFlag defer func() { diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/command.go b/Godeps/_workspace/src/github.com/codegangsta/cli/command.go index ffd3ef81..07c919a8 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/command.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/command.go @@ -21,6 +21,9 @@ type Command struct { // An action to execute before any sub-subcommands are run, but after the context is ready // If a non-nil error is returned, no sub-subcommands are run Before func(context *Context) error + // An action to execute after any subcommands are run, but after the subcommand has finished + // It is run even if Action() panics + After func(context *Context) error // The function to call when this command is invoked Action func(context *Context) // List of child commands @@ -36,7 +39,7 @@ type Command struct { // Invokes the command given the context, parses ctx.Args() to generate command-specific flags func (c Command) Run(ctx *Context) error { - if len(c.Subcommands) > 0 || c.Before != nil { + if len(c.Subcommands) > 0 || c.Before != nil || c.After != nil { return c.startApp(ctx) } @@ -116,7 +119,7 @@ func (c Command) Run(ctx *Context) error { // Returns true if Command.Name or Command.ShortName matches given name func (c Command) HasName(name string) bool { - return c.Name == name || c.ShortName == name + return c.Name == name || (c.ShortName != "" && c.ShortName == name) } func (c Command) startApp(ctx *Context) error { @@ -146,6 +149,7 @@ func (c Command) startApp(ctx *Context) error { // set the actions app.Before = c.Before + app.After = c.After if c.Action != nil { app.Action = c.Action } else { diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/context.go b/Godeps/_workspace/src/github.com/codegangsta/cli/context.go index c9f645b1..37221bdc 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/context.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/context.go @@ -106,6 +106,11 @@ func (c *Context) GlobalGeneric(name string) interface{} { return lookupGeneric(name, c.globalSet) } +// Returns the number of flags set +func (c *Context) NumFlags() int { + return c.flagSet.NFlag() +} + // Determines if the flag was actually set func (c *Context) IsSet(name string) bool { if c.setFlags == nil { diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/context_test.go b/Godeps/_workspace/src/github.com/codegangsta/cli/context_test.go index 7c9a4436..d4a1877f 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/context_test.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/context_test.go @@ -97,3 +97,15 @@ func TestContext_GlobalIsSet(t *testing.T) { expect(t, c.GlobalIsSet("myflagGlobalUnset"), false) expect(t, c.GlobalIsSet("bogusGlobal"), false) } + +func TestContext_NumFlags(t *testing.T) { + set := flag.NewFlagSet("test", 0) + set.Bool("myflag", false, "doc") + set.String("otherflag", "hello world", "doc") + globalSet := flag.NewFlagSet("test", 0) + globalSet.Bool("myflagGlobal", true, "doc") + c := cli.NewContext(nil, set, globalSet) + set.Parse([]string{"--myflag", "--otherflag=foo"}) + globalSet.Parse([]string{"--myflagGlobal"}) + expect(t, c.NumFlags(), 2) +} diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/help.go b/Godeps/_workspace/src/github.com/codegangsta/cli/help.go index bfb27885..8d176556 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/help.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/help.go @@ -12,11 +12,10 @@ USAGE: {{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] VERSION: - {{.Version}}{{if or .Author .Email}} + {{.Version}} -AUTHOR:{{if .Author}} - {{.Author}}{{if .Email}} - <{{.Email}}>{{end}}{{else}} - {{.Email}}{{end}}{{end}} +AUTHOR(S): + {{range .Authors}}{{ . }} {{end}} COMMANDS: {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} @@ -112,6 +111,12 @@ func DefaultAppComplete(c *Context) { // Prints help for the given command func ShowCommandHelp(c *Context, command string) { + // show the subcommand help for a command with subcommands + if command == "" { + HelpPrinter(SubcommandHelpTemplate, c.App) + return + } + for _, c := range c.App.Commands { if c.HasName(command) { HelpPrinter(CommandHelpTemplate, c)