From 0ec53af38f2a6e10d77aedbb715290361b427a1f Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Thu, 24 Dec 2015 17:06:14 +0100 Subject: [PATCH 1/2] Vendoring codegangsta/cli dependency Signed-off-by: Vincent Demeester --- script/vendor.sh | 2 +- vendor/github.com/codegangsta/cli/.travis.yml | 9 +- vendor/github.com/codegangsta/cli/README.md | 45 +++++-- vendor/github.com/codegangsta/cli/app.go | 124 +++++++++++++----- vendor/github.com/codegangsta/cli/cli.go | 21 +++ vendor/github.com/codegangsta/cli/command.go | 70 ++++++++-- vendor/github.com/codegangsta/cli/context.go | 77 +++++++++-- vendor/github.com/codegangsta/cli/flag.go | 45 ++++++- vendor/github.com/codegangsta/cli/help.go | 119 +++++++++++------ 9 files changed, 398 insertions(+), 114 deletions(-) diff --git a/script/vendor.sh b/script/vendor.sh index 065576335..57cd43ef4 100755 --- a/script/vendor.sh +++ b/script/vendor.sh @@ -6,7 +6,7 @@ rm -rf vendor/ source 'script/.vendor-helpers.sh' clone git github.com/Sirupsen/logrus v0.8.2 -clone git github.com/codegangsta/cli 6086d7927ec35315964d9fea46df6c04e6d697c1 +clone git github.com/codegangsta/cli 70e3fa51ebed95df8c0fbe1519c1c1f9bc16bb13 clone git github.com/docker/distribution c6c9194e9c6097f84b0ff468a741086ff7704aa3 clone git github.com/docker/docker 58b270c338e831ac6668a29788c72d202f9fc251 clone git github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a diff --git a/vendor/github.com/codegangsta/cli/.travis.yml b/vendor/github.com/codegangsta/cli/.travis.yml index baf46abc6..34d39c871 100644 --- a/vendor/github.com/codegangsta/cli/.travis.yml +++ b/vendor/github.com/codegangsta/cli/.travis.yml @@ -1,5 +1,12 @@ language: go -go: 1.1 +sudo: false + +go: +- 1.0.3 +- 1.1.2 +- 1.2.2 +- 1.3.3 +- 1.4.2 script: - go vet ./... diff --git a/vendor/github.com/codegangsta/cli/README.md b/vendor/github.com/codegangsta/cli/README.md index c0bb338ab..234655710 100644 --- a/vendor/github.com/codegangsta/cli/README.md +++ b/vendor/github.com/codegangsta/cli/README.md @@ -1,18 +1,17 @@ +[![Coverage](http://gocover.io/_badge/github.com/codegangsta/cli?0)](http://gocover.io/github.com/codegangsta/cli) [![Build Status](https://travis-ci.org/codegangsta/cli.png?branch=master)](https://travis-ci.org/codegangsta/cli) +[![GoDoc](https://godoc.org/github.com/codegangsta/cli?status.svg)](https://godoc.org/github.com/codegangsta/cli) # cli.go -cli.go is simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable command line applications in an expressive way. - -You can view the API docs here: -http://godoc.org/github.com/codegangsta/cli +`cli.go` is simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable command line applications in an expressive way. ## Overview Command line apps are usually so tiny that there is absolutely no reason why your code should *not* be self-documenting. Things like generating help text and parsing command flags/options should not hinder productivity when writing a command line app. -**This is where cli.go comes into play.** cli.go makes command line programming fun, organized, and expressive! +**This is where `cli.go` comes into play.** `cli.go` makes command line programming fun, organized, and expressive! ## Installation -Make sure you have a working Go environment (go 1.1 is *required*). [See the install instructions](http://golang.org/doc/install.html). +Make sure you have a working Go environment (go 1.1+ is *required*). [See the install instructions](http://golang.org/doc/install.html). To install `cli.go`, simply run: ``` @@ -25,7 +24,7 @@ export PATH=$PATH:$GOPATH/bin ``` ## Getting Started -One of the philosophies behind cli.go is that an API should be playful and full of discovery. So a cli.go app can be as little as one line of code in `main()`. +One of the philosophies behind `cli.go` is that an API should be playful and full of discovery. So a `cli.go` app can be as little as one line of code in `main()`. ``` go package main @@ -103,7 +102,8 @@ $ greet Hello friend! ``` -cli.go also generates some bitchass help text: +`cli.go` also generates neat help text: + ``` $ greet help NAME: @@ -158,6 +158,8 @@ app.Action = func(c *cli.Context) { ... ``` +See full list of flags at http://godoc.org/github.com/codegangsta/cli + #### Alternate Names You can set alternate (or short) names for flags by providing a comma-delimited list for the `Name`. e.g. @@ -210,7 +212,7 @@ Subcommands can be defined for a more git-like command line app. app.Commands = []cli.Command{ { Name: "add", - ShortName: "a", + Aliases: []string{"a"}, Usage: "add a task to the list", Action: func(c *cli.Context) { println("added task: ", c.Args().First()) @@ -218,7 +220,7 @@ app.Commands = []cli.Command{ }, { Name: "complete", - ShortName: "c", + Aliases: []string{"c"}, Usage: "complete a task on the list", Action: func(c *cli.Context) { println("completed task: ", c.Args().First()) @@ -226,7 +228,7 @@ app.Commands = []cli.Command{ }, { Name: "template", - ShortName: "r", + Aliases: []string{"r"}, Usage: "options for task templates", Subcommands: []cli.Command{ { @@ -244,7 +246,7 @@ app.Commands = []cli.Command{ }, }, }, - }, + }, } ... ``` @@ -262,8 +264,8 @@ app := cli.NewApp() app.EnableBashCompletion = true app.Commands = []cli.Command{ { - Name: "complete", - ShortName: "c", + Name: "complete", + Aliases: []string{"c"}, Usage: "complete a task on the list", Action: func(c *cli.Context) { println("completed task: ", c.Args().First()) @@ -289,6 +291,21 @@ setting the `PROG` variable to the name of your program: `PROG=myprogram source /.../cli/autocomplete/bash_autocomplete` +#### To Distribute + +Copy `autocomplete/bash_autocomplete` into `/etc/bash_completion.d/` and rename +it to the name of the program you wish to add autocomplete support for (or +automatically install it there if you are distributing a package). Don't forget +to source the file to make it active in the current shell. + +``` + sudo cp src/bash_autocomplete /etc/bash_completion.d/ + source /etc/bash_completion.d/ +``` + +Alternatively, you can just document that users should source the generic +`autocomplete/bash_autocomplete` in their bash configuration with `$PROG` set +to the name of their program (as above). ## Contribution Guidelines Feel free to put up a pull request to fix a bug or maybe add a feature. I will give it a code review and make sure that it does not break backwards compatibility. If I or any other collaborators agree that it is in line with the vision of the project, we will work with you to get the code into a mergeable state and merge it into the master branch. diff --git a/vendor/github.com/codegangsta/cli/app.go b/vendor/github.com/codegangsta/cli/app.go index 6422345dc..9a15c0c03 100644 --- a/vendor/github.com/codegangsta/cli/app.go +++ b/vendor/github.com/codegangsta/cli/app.go @@ -5,18 +5,20 @@ import ( "io" "io/ioutil" "os" - "text/tabwriter" - "text/template" "time" ) // App is the main structure of a cli application. It is recomended that -// and app be created with the cli.NewApp() function +// an app be created with the cli.NewApp() function type App struct { // The name of the program. Defaults to os.Args[0] Name string + // Full name of command for help, defaults to Name + HelpName string // Description of the program. Usage string + // Description of the program argument format. + ArgsUsage string // Version of the program Version string // List of commands to execute @@ -34,15 +36,22 @@ 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 + // Copyright of the binary if any + Copyright string + // 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 @@ -62,34 +71,30 @@ func compileTime() time.Time { func NewApp() *App { return &App{ Name: os.Args[0], + HelpName: os.Args[0], Usage: "A new cli application", Version: "0.0.0", 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 { - if HelpPrinter == nil { - defer func() { - HelpPrinter = nil - }() +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}) + } - HelpPrinter = func(templ string, data interface{}) { - w := tabwriter.NewWriter(a.Writer, 0, 8, 1, '\t', 0) - t := template.Must(template.New("help").Parse(templ)) - err := t.Execute(w, data) - if err != nil { - panic(err) - } - w.Flush() + newCmds := []Command{} + for _, c := range a.Commands { + if c.HelpName == "" { + c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) } + newCmds = append(newCmds, c) } + a.Commands = newCmds // append help to commands if a.Command(helpCommand.Name) == nil && !a.HideHelp { @@ -111,21 +116,20 @@ 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) - context := NewContext(a, set, set) + context := NewContext(a, set, nil) ShowAppHelp(context) - fmt.Fprintln(a.Writer) return nerr } - context := NewContext(a, set, set) + context := NewContext(a, set, nil) if err != nil { - fmt.Fprintf(a.Writer, "Incorrect Usage.\n\n") - ShowAppHelp(context) + fmt.Fprintln(a.Writer, "Incorrect Usage.") fmt.Fprintln(a.Writer) + ShowAppHelp(context) return err } @@ -133,14 +137,29 @@ func (a *App) Run(arguments []string) error { return nil } - if checkHelp(context) { + if !a.HideHelp && checkHelp(context) { + ShowAppHelp(context) return nil } - if checkVersion(context) { + if !a.HideVersion && checkVersion(context) { + ShowVersion(context) return nil } + if a.After != nil { + defer func() { + afterErr := a.After(context) + if afterErr != nil { + if err != nil { + err = NewMultiError(err, afterErr) + } else { + err = afterErr + } + } + }() + } + if a.Before != nil { err := a.Before(context) if err != nil { @@ -171,7 +190,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 { @@ -182,6 +201,15 @@ func (a *App) RunAsSubcommand(ctx *Context) error { } } + newCmds := []Command{} + for _, c := range a.Commands { + if c.HelpName == "" { + c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) + } + newCmds = append(newCmds, c) + } + a.Commands = newCmds + // append flags if a.EnableBashCompletion { a.appendFlag(BashCompletionFlag) @@ -190,23 +218,24 @@ 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) + context := NewContext(a, set, ctx) if nerr != nil { fmt.Fprintln(a.Writer, nerr) + fmt.Fprintln(a.Writer) if len(a.Commands) > 0 { ShowSubcommandHelp(context) } else { ShowCommandHelp(ctx, context.Args().First()) } - fmt.Fprintln(a.Writer) return nerr } if err != nil { - fmt.Fprintf(a.Writer, "Incorrect Usage.\n\n") + fmt.Fprintln(a.Writer, "Incorrect Usage.") + fmt.Fprintln(a.Writer) ShowSubcommandHelp(context) return err } @@ -225,6 +254,19 @@ func (a *App) RunAsSubcommand(ctx *Context) error { } } + if a.After != nil { + defer func() { + afterErr := a.After(context) + if afterErr != nil { + if err != nil { + err = NewMultiError(err, afterErr) + } else { + err = afterErr + } + } + }() + } + if a.Before != nil { err := a.Before(context) if err != nil { @@ -273,3 +315,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/vendor/github.com/codegangsta/cli/cli.go b/vendor/github.com/codegangsta/cli/cli.go index b74254581..31dc9124d 100644 --- a/vendor/github.com/codegangsta/cli/cli.go +++ b/vendor/github.com/codegangsta/cli/cli.go @@ -17,3 +17,24 @@ // app.Run(os.Args) // } package cli + +import ( + "strings" +) + +type MultiError struct { + Errors []error +} + +func NewMultiError(err ...error) MultiError { + return MultiError{Errors: err} +} + +func (m MultiError) Error() string { + errs := make([]string, len(m.Errors)) + for i, err := range m.Errors { + errs[i] = err.Error() + } + + return strings.Join(errs, "\n") +} diff --git a/vendor/github.com/codegangsta/cli/command.go b/vendor/github.com/codegangsta/cli/command.go index ffd3ef81d..fac754deb 100644 --- a/vendor/github.com/codegangsta/cli/command.go +++ b/vendor/github.com/codegangsta/cli/command.go @@ -10,17 +10,24 @@ import ( type Command struct { // The name of the command Name string - // short name of the command. Typically one character + // short name of the command. Typically one character (deprecated, use `Aliases`) ShortName string + // A list of aliases for the command + Aliases []string // A short description of the usage of this command Usage string // A longer explanation of how the command works Description string + // A short description of the arguments of this command + ArgsUsage string // The function to call when checking for bash command completions BashComplete func(context *Context) // 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 @@ -31,12 +38,24 @@ type Command struct { SkipFlagParsing bool // Boolean to hide built-in help command HideHelp bool + + // Full name of command for help, defaults to full command name, including parent commands. + HelpName string + commandNamePath []string +} + +// Returns the full name of the command. +// For subcommands this ensures that parent commands are part of the command path +func (c Command) FullName() string { + if c.commandNamePath == nil { + return c.Name + } + return strings.Join(c.commandNamePath, " ") } // 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) } @@ -86,9 +105,9 @@ func (c Command) Run(ctx *Context) error { } if err != nil { - fmt.Fprint(ctx.App.Writer, "Incorrect Usage.\n\n") - ShowCommandHelp(ctx, c.Name) + fmt.Fprintln(ctx.App.Writer, "Incorrect Usage.") fmt.Fprintln(ctx.App.Writer) + ShowCommandHelp(ctx, c.Name) return err } @@ -97,10 +116,9 @@ func (c Command) Run(ctx *Context) error { fmt.Fprintln(ctx.App.Writer, nerr) fmt.Fprintln(ctx.App.Writer) ShowCommandHelp(ctx, c.Name) - fmt.Fprintln(ctx.App.Writer) return nerr } - context := NewContext(ctx.App, set, ctx.globalSet) + context := NewContext(ctx.App, set, ctx) if checkCommandCompletions(context, c.Name) { return nil @@ -114,9 +132,24 @@ func (c Command) Run(ctx *Context) error { return nil } +func (c Command) Names() []string { + names := []string{c.Name} + + if c.ShortName != "" { + names = append(names, c.ShortName) + } + + return append(names, c.Aliases...) +} + // 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 + for _, n := range c.Names() { + if n == name { + return true + } + } + return false } func (c Command) startApp(ctx *Context) error { @@ -124,6 +157,12 @@ func (c Command) startApp(ctx *Context) error { // set the name and usage app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name) + if c.HelpName == "" { + app.HelpName = c.HelpName + } else { + app.HelpName = fmt.Sprintf("%s %s", ctx.App.Name, c.Name) + } + if c.Description != "" { app.Usage = c.Description } else { @@ -138,6 +177,13 @@ func (c Command) startApp(ctx *Context) error { app.Flags = c.Flags app.HideHelp = c.HideHelp + app.Version = ctx.App.Version + app.HideVersion = ctx.App.HideVersion + app.Compiled = ctx.App.Compiled + app.Author = ctx.App.Author + app.Email = ctx.App.Email + app.Writer = ctx.App.Writer + // bash completion app.EnableBashCompletion = ctx.App.EnableBashCompletion if c.BashComplete != nil { @@ -146,11 +192,19 @@ 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 { app.Action = helpSubcommand.Action } + var newCmds []Command + for _, cc := range app.Commands { + cc.commandNamePath = []string{c.Name, cc.Name} + newCmds = append(newCmds, cc) + } + app.Commands = newCmds + return app.RunAsSubcommand(ctx) } diff --git a/vendor/github.com/codegangsta/cli/context.go b/vendor/github.com/codegangsta/cli/context.go index c9f645b18..f541f41c3 100644 --- a/vendor/github.com/codegangsta/cli/context.go +++ b/vendor/github.com/codegangsta/cli/context.go @@ -16,14 +16,14 @@ type Context struct { App *App Command Command flagSet *flag.FlagSet - globalSet *flag.FlagSet setFlags map[string]bool globalSetFlags map[string]bool + parentContext *Context } // Creates a new context. For use in when invoking an App or Command action. -func NewContext(app *App, set *flag.FlagSet, globalSet *flag.FlagSet) *Context { - return &Context{App: app, flagSet: set, globalSet: globalSet} +func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context { + return &Context{App: app, flagSet: set, parentContext: parentCtx} } // Looks up the value of a local int flag, returns 0 if no int flag exists @@ -73,37 +73,63 @@ func (c *Context) Generic(name string) interface{} { // Looks up the value of a global int flag, returns 0 if no int flag exists func (c *Context) GlobalInt(name string) int { - return lookupInt(name, c.globalSet) + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupInt(name, fs) + } + return 0 } // Looks up the value of a global time.Duration flag, returns 0 if no time.Duration flag exists func (c *Context) GlobalDuration(name string) time.Duration { - return lookupDuration(name, c.globalSet) + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupDuration(name, fs) + } + return 0 } // Looks up the value of a global bool flag, returns false if no bool flag exists func (c *Context) GlobalBool(name string) bool { - return lookupBool(name, c.globalSet) + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupBool(name, fs) + } + return false } // Looks up the value of a global string flag, returns "" if no string flag exists func (c *Context) GlobalString(name string) string { - return lookupString(name, c.globalSet) + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupString(name, fs) + } + return "" } // Looks up the value of a global string slice flag, returns nil if no string slice flag exists func (c *Context) GlobalStringSlice(name string) []string { - return lookupStringSlice(name, c.globalSet) + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupStringSlice(name, fs) + } + return nil } // Looks up the value of a global int slice flag, returns nil if no int slice flag exists func (c *Context) GlobalIntSlice(name string) []int { - return lookupIntSlice(name, c.globalSet) + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupIntSlice(name, fs) + } + return nil } // Looks up the value of a global generic flag, returns nil if no generic flag exists func (c *Context) GlobalGeneric(name string) interface{} { - return lookupGeneric(name, c.globalSet) + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupGeneric(name, fs) + } + return nil +} + +// Returns the number of flags set +func (c *Context) NumFlags() int { + return c.flagSet.NFlag() } // Determines if the flag was actually set @@ -121,11 +147,17 @@ func (c *Context) IsSet(name string) bool { func (c *Context) GlobalIsSet(name string) bool { if c.globalSetFlags == nil { c.globalSetFlags = make(map[string]bool) - c.globalSet.Visit(func(f *flag.Flag) { - c.globalSetFlags[f.Name] = true - }) + ctx := c + if ctx.parentContext != nil { + ctx = ctx.parentContext + } + for ; ctx != nil && c.globalSetFlags[name] == false; ctx = ctx.parentContext { + ctx.flagSet.Visit(func(f *flag.Flag) { + c.globalSetFlags[f.Name] = true + }) + } } - return c.globalSetFlags[name] == true + return c.globalSetFlags[name] } // Returns a slice of flag names used in this context. @@ -152,6 +184,11 @@ func (c *Context) GlobalFlagNames() (names []string) { return } +// Returns the parent context, if any +func (c *Context) Parent() *Context { + return c.parentContext +} + type Args []string // Returns the command line arguments associated with the context. @@ -196,6 +233,18 @@ func (a Args) Swap(from, to int) error { return nil } +func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet { + if ctx.parentContext != nil { + ctx = ctx.parentContext + } + for ; ctx != nil; ctx = ctx.parentContext { + if f := ctx.flagSet.Lookup(name); f != nil { + return ctx.flagSet + } + } + return nil +} + func lookupInt(name string, set *flag.FlagSet) int { f := set.Lookup(name) if f != nil { diff --git a/vendor/github.com/codegangsta/cli/flag.go b/vendor/github.com/codegangsta/cli/flag.go index 251158667..531b09130 100644 --- a/vendor/github.com/codegangsta/cli/flag.go +++ b/vendor/github.com/codegangsta/cli/flag.go @@ -99,21 +99,27 @@ func (f GenericFlag) getName() string { return f.Name } +// StringSlice is an opaque type for []string to satisfy flag.Value type StringSlice []string +// Set appends the string value to the list of values func (f *StringSlice) Set(value string) error { *f = append(*f, value) return nil } +// String returns a readable representation of this value (for usage defaults) func (f *StringSlice) String() string { return fmt.Sprintf("%s", *f) } +// Value returns the slice of strings set by this flag func (f *StringSlice) Value() []string { return *f } +// StringSlice is a string flag that can be specified multiple times on the +// command-line type StringSliceFlag struct { Name string Value *StringSlice @@ -121,12 +127,14 @@ type StringSliceFlag struct { EnvVar string } +// String returns the usage func (f StringSliceFlag) String() string { firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ") pref := prefixFor(firstName) return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage)) } +// Apply populates the flag given the flag set and environment func (f StringSliceFlag) Apply(set *flag.FlagSet) { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { @@ -144,6 +152,9 @@ func (f StringSliceFlag) Apply(set *flag.FlagSet) { } eachName(f.Name, func(name string) { + if f.Value == nil { + f.Value = &StringSlice{} + } set.Var(f.Value, name, f.Usage) }) } @@ -152,10 +163,11 @@ func (f StringSliceFlag) getName() string { return f.Name } +// StringSlice is an opaque type for []int to satisfy flag.Value type IntSlice []int +// Set parses the value into an integer and appends it to the list of values func (f *IntSlice) Set(value string) error { - tmp, err := strconv.Atoi(value) if err != nil { return err @@ -165,14 +177,18 @@ func (f *IntSlice) Set(value string) error { return nil } +// String returns a readable representation of this value (for usage defaults) func (f *IntSlice) String() string { return fmt.Sprintf("%d", *f) } +// Value returns the slice of ints set by this flag func (f *IntSlice) Value() []int { return *f } +// IntSliceFlag is an int flag that can be specified multiple times on the +// command-line type IntSliceFlag struct { Name string Value *IntSlice @@ -180,12 +196,14 @@ type IntSliceFlag struct { EnvVar string } +// String returns the usage func (f IntSliceFlag) String() string { firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ") pref := prefixFor(firstName) return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage)) } +// Apply populates the flag given the flag set and environment func (f IntSliceFlag) Apply(set *flag.FlagSet) { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { @@ -206,6 +224,9 @@ func (f IntSliceFlag) Apply(set *flag.FlagSet) { } eachName(f.Name, func(name string) { + if f.Value == nil { + f.Value = &IntSlice{} + } set.Var(f.Value, name, f.Usage) }) } @@ -214,16 +235,19 @@ func (f IntSliceFlag) getName() string { return f.Name } +// BoolFlag is a switch that defaults to false type BoolFlag struct { Name string Usage string EnvVar string } +// String returns a readable representation of this value (for usage defaults) func (f BoolFlag) String() string { return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage)) } +// Apply populates the flag given the flag set and environment func (f BoolFlag) Apply(set *flag.FlagSet) { val := false if f.EnvVar != "" { @@ -248,16 +272,20 @@ func (f BoolFlag) getName() string { return f.Name } +// BoolTFlag this represents a boolean flag that is true by default, but can +// still be set to false by --some-flag=false type BoolTFlag struct { Name string Usage string EnvVar string } +// String returns a readable representation of this value (for usage defaults) func (f BoolTFlag) String() string { return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage)) } +// Apply populates the flag given the flag set and environment func (f BoolTFlag) Apply(set *flag.FlagSet) { val := true if f.EnvVar != "" { @@ -282,6 +310,7 @@ func (f BoolTFlag) getName() string { return f.Name } +// StringFlag represents a flag that takes as string value type StringFlag struct { Name string Value string @@ -289,6 +318,7 @@ type StringFlag struct { EnvVar string } +// String returns the usage func (f StringFlag) String() string { var fmtString string fmtString = "%s %v\t%v" @@ -302,6 +332,7 @@ func (f StringFlag) String() string { return withEnvHint(f.EnvVar, fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage)) } +// Apply populates the flag given the flag set and environment func (f StringFlag) Apply(set *flag.FlagSet) { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { @@ -322,6 +353,8 @@ func (f StringFlag) getName() string { return f.Name } +// IntFlag is a flag that takes an integer +// Errors if the value provided cannot be parsed type IntFlag struct { Name string Value int @@ -329,10 +362,12 @@ type IntFlag struct { EnvVar string } +// String returns the usage func (f IntFlag) String() string { return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage)) } +// Apply populates the flag given the flag set and environment func (f IntFlag) Apply(set *flag.FlagSet) { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { @@ -356,6 +391,8 @@ func (f IntFlag) getName() string { return f.Name } +// DurationFlag is a flag that takes a duration specified in Go's duration +// format: https://golang.org/pkg/time/#ParseDuration type DurationFlag struct { Name string Value time.Duration @@ -363,10 +400,12 @@ type DurationFlag struct { EnvVar string } +// String returns a readable representation of this value (for usage defaults) func (f DurationFlag) String() string { return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage)) } +// Apply populates the flag given the flag set and environment func (f DurationFlag) Apply(set *flag.FlagSet) { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { @@ -390,6 +429,8 @@ func (f DurationFlag) getName() string { return f.Name } +// Float64Flag is a flag that takes an float value +// Errors if the value provided cannot be parsed type Float64Flag struct { Name string Value float64 @@ -397,10 +438,12 @@ type Float64Flag struct { EnvVar string } +// String returns the usage func (f Float64Flag) String() string { return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage)) } +// Apply populates the flag given the flag set and environment func (f Float64Flag) Apply(set *flag.FlagSet) { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { diff --git a/vendor/github.com/codegangsta/cli/help.go b/vendor/github.com/codegangsta/cli/help.go index bfb278851..a246f63ac 100644 --- a/vendor/github.com/codegangsta/cli/help.go +++ b/vendor/github.com/codegangsta/cli/help.go @@ -1,6 +1,12 @@ package cli -import "fmt" +import ( + "fmt" + "io" + "strings" + "text/tabwriter" + "text/template" +) // The text template for the Default help topic. // cli.go uses text/template to render templates. You can @@ -9,31 +15,33 @@ var AppHelpTemplate = `NAME: {{.Name}} - {{.Usage}} USAGE: - {{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] - + {{.HelpName}} {{if .Flags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} + {{if .Version}} VERSION: - {{.Version}}{{if or .Author .Email}} - -AUTHOR:{{if .Author}} - {{.Author}}{{if .Email}} - <{{.Email}}>{{end}}{{else}} - {{.Email}}{{end}}{{end}} - + {{.Version}} + {{end}}{{if len .Authors}} +AUTHOR(S): + {{range .Authors}}{{ . }}{{end}} + {{end}}{{if .Commands}} COMMANDS: - {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} - {{end}}{{if .Flags}} + {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} + {{end}}{{end}}{{if .Flags}} GLOBAL OPTIONS: {{range .Flags}}{{.}} - {{end}}{{end}} + {{end}}{{end}}{{if .Copyright }} +COPYRIGHT: + {{.Copyright}} + {{end}} ` // The text template for the command help topic. // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var CommandHelpTemplate = `NAME: - {{.Name}} - {{.Usage}} + {{.HelpName}} - {{.Usage}} USAGE: - command {{.Name}}{{if .Flags}} [command options]{{end}} [arguments...]{{if .Description}} + {{.HelpName}}{{if .Flags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Description}} DESCRIPTION: {{.Description}}{{end}}{{if .Flags}} @@ -47,13 +55,13 @@ OPTIONS: // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var SubcommandHelpTemplate = `NAME: - {{.Name}} - {{.Usage}} + {{.HelpName}} - {{.Usage}} USAGE: - {{.Name}} command{{if .Flags}} [command options]{{end}} [arguments...] + {{.HelpName}} command{{if .Flags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} COMMANDS: - {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} + {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} {{end}}{{if .Flags}} OPTIONS: {{range .Flags}}{{.}} @@ -62,8 +70,9 @@ OPTIONS: var helpCommand = Command{ Name: "help", - ShortName: "h", + Aliases: []string{"h"}, Usage: "Shows a list of commands or help for one command", + ArgsUsage: "[command]", Action: func(c *Context) { args := c.Args() if args.Present() { @@ -76,8 +85,9 @@ var helpCommand = Command{ var helpSubcommand = Command{ Name: "help", - ShortName: "h", + Aliases: []string{"h"}, Usage: "Shows a list of commands or help for one command", + ArgsUsage: "[command]", Action: func(c *Context) { args := c.Args() if args.Present() { @@ -88,41 +98,46 @@ var helpSubcommand = Command{ }, } -// Prints help for the App -type helpPrinter func(templ string, data interface{}) +// Prints help for the App or Command +type helpPrinter func(w io.Writer, templ string, data interface{}) -var HelpPrinter helpPrinter = nil +var HelpPrinter helpPrinter = printHelp // Prints version for the App var VersionPrinter = printVersion func ShowAppHelp(c *Context) { - HelpPrinter(AppHelpTemplate, c.App) + HelpPrinter(c.App.Writer, AppHelpTemplate, c.App) } // Prints the list of subcommands as the default app completion method func DefaultAppComplete(c *Context) { for _, command := range c.App.Commands { - fmt.Fprintln(c.App.Writer, command.Name) - if command.ShortName != "" { - fmt.Fprintln(c.App.Writer, command.ShortName) + for _, name := range command.Names() { + fmt.Fprintln(c.App.Writer, name) } } } // Prints help for the given command -func ShowCommandHelp(c *Context, command string) { - for _, c := range c.App.Commands { +func ShowCommandHelp(ctx *Context, command string) { + // show the subcommand help for a command with subcommands + if command == "" { + HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App) + return + } + + for _, c := range ctx.App.Commands { if c.HasName(command) { - HelpPrinter(CommandHelpTemplate, c) + HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c) return } } - if c.App.CommandNotFound != nil { - c.App.CommandNotFound(c, command) + if ctx.App.CommandNotFound != nil { + ctx.App.CommandNotFound(ctx, command) } else { - fmt.Fprintf(c.App.Writer, "No help topic for '%v'\n", command) + fmt.Fprintf(ctx.App.Writer, "No help topic for '%v'\n", command) } } @@ -156,22 +171,42 @@ func ShowCommandCompletions(ctx *Context, command string) { } } -func checkVersion(c *Context) bool { - if c.GlobalBool("version") { - ShowVersion(c) - return true +func printHelp(out io.Writer, templ string, data interface{}) { + funcMap := template.FuncMap{ + "join": strings.Join, } - return false + w := tabwriter.NewWriter(out, 0, 8, 1, '\t', 0) + t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) + err := t.Execute(w, data) + if err != nil { + panic(err) + } + w.Flush() } -func checkHelp(c *Context) bool { - if c.GlobalBool("h") || c.GlobalBool("help") { - ShowAppHelp(c) - return true +func checkVersion(c *Context) bool { + found := false + if VersionFlag.Name != "" { + eachName(VersionFlag.Name, func(name string) { + if c.GlobalBool(name) || c.Bool(name) { + found = true + } + }) } + return found +} - return false +func checkHelp(c *Context) bool { + found := false + if HelpFlag.Name != "" { + eachName(HelpFlag.Name, func(name string) { + if c.GlobalBool(name) || c.Bool(name) { + found = true + } + }) + } + return found } func checkCommandHelp(c *Context, name string) bool { From 789578850c3b378d2df6ecdac7ac3566ce298164 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Fri, 25 Dec 2015 13:58:20 +0100 Subject: [PATCH 2/2] Help command improvements Big thanks to @bohai :) Signed-off-by: Vincent Demeester --- cli/command/command.go | 107 ++++++++++++++++++++++++------------- cli/command/help.go | 20 ++++--- integration/common_test.go | 2 +- integration/down_test.go | 2 +- 4 files changed, 80 insertions(+), 51 deletions(-) diff --git a/cli/command/command.go b/cli/command/command.go index ffb6ca7ac..54188a486 100644 --- a/cli/command/command.go +++ b/cli/command/command.go @@ -9,17 +9,22 @@ import ( // CreateCommand defines the libcompose create subcommand. func CreateCommand(factory app.ProjectFactory) cli.Command { return cli.Command{ - Name: "create", - Usage: "Create all services but do not start", - Action: app.WithProject(factory, app.ProjectCreate), + Name: "create", + Usage: "Create all services but do not start", + ArgsUsage: "[SERVICE...]", + Action: app.WithProject(factory, app.ProjectCreate), } } // BuildCommand defines the libcompose build subcommand. func BuildCommand(factory app.ProjectFactory) cli.Command { return cli.Command{ - Name: "build", - Usage: "Build or rebuild services.", + Name: "build", + Usage: "Build or rebuild services.", + ArgsUsage: "[SERVICE...]", + Description: "Services are built once and then tagged as `project_service`,\n" + + "e.g. `composetest_db`. If you change a service's `Dockerfile` or the\n" + + "contents of its build directory, you can run `libcompose-cli build` to rebuild it.", Action: app.WithProject(factory, app.ProjectBuild), Flags: []cli.Flag{ cli.BoolFlag{ @@ -33,9 +38,10 @@ func BuildCommand(factory app.ProjectFactory) cli.Command { // PsCommand defines the libcompose ps subcommand. func PsCommand(factory app.ProjectFactory) cli.Command { return cli.Command{ - Name: "ps", - Usage: "List containers", - Action: app.WithProject(factory, app.ProjectPs), + Name: "ps", + Usage: "List containers", + ArgsUsage: "[SERVICE...]", + Action: app.WithProject(factory, app.ProjectPs), Flags: []cli.Flag{ cli.BoolFlag{ Name: "q", @@ -48,9 +54,10 @@ func PsCommand(factory app.ProjectFactory) cli.Command { // PortCommand defines the libcompose port subcommand. func PortCommand(factory app.ProjectFactory) cli.Command { return cli.Command{ - Name: "port", - Usage: "Print the public port for a port binding", - Action: app.WithProject(factory, app.ProjectPort), + Name: "port", + Usage: "Print the public port for a port binding", + ArgsUsage: "SERVICE PRIVATE_PORT", + Action: app.WithProject(factory, app.ProjectPort), Flags: []cli.Flag{ cli.StringFlag{ Name: "protocol", @@ -69,8 +76,20 @@ func PortCommand(factory app.ProjectFactory) cli.Command { // UpCommand defines the libcompose up subcommand. func UpCommand(factory app.ProjectFactory) cli.Command { return cli.Command{ - Name: "up", - Usage: "Bring all services up", + Name: "up", + Usage: "Builds, (re)creates, starts, and attaches to containers for a service.", + ArgsUsage: "[SERVICE...]", + Description: "Unless they are already running, this command also starts any linked services.\n\n" + + "The `libcompose-cli up` command aggregates the output of each container. When\n" + + "the command exits, all containers are stopped. Running `libcompose-cli up -d`\n" + + "starts the containers in the background and leaves them running.\n\n" + + "If there are existing containers for a service, and the service's configuration\n" + + "or image was changed after the container's creation, `libcompose-cli up` picks\n" + + "up the changes by stopping and recreating the containers (preserving mounted\n" + + "volumes). To prevent Compose from picking up changes, use the `--no-recreate`\n" + + "flag.\n\n" + + "If you want to force Compose to stop and recreate all containers, use the\n" + + "`--force-recreate` flag.", Action: app.WithProject(factory, app.ProjectUp), Flags: []cli.Flag{ cli.BoolFlag{ @@ -92,9 +111,10 @@ func UpCommand(factory app.ProjectFactory) cli.Command { // StartCommand defines the libcompose start subcommand. func StartCommand(factory app.ProjectFactory) cli.Command { return cli.Command{ - Name: "start", - Usage: "Start services", - Action: app.WithProject(factory, app.ProjectStart), + Name: "start", + Usage: "Start existing containers.", + ArgsUsage: "[SERVICE...]", + Action: app.WithProject(factory, app.ProjectStart), Flags: []cli.Flag{ cli.BoolTFlag{ Name: "d", @@ -107,18 +127,20 @@ func StartCommand(factory app.ProjectFactory) cli.Command { // PullCommand defines the libcompose pull subcommand. func PullCommand(factory app.ProjectFactory) cli.Command { return cli.Command{ - Name: "pull", - Usage: "Pulls images for services", - Action: app.WithProject(factory, app.ProjectPull), + Name: "pull", + Usage: "Pulls images for services.", + ArgsUsage: "[SERVICE...]", + Action: app.WithProject(factory, app.ProjectPull), } } // LogsCommand defines the libcompose logs subcommand. func LogsCommand(factory app.ProjectFactory) cli.Command { return cli.Command{ - Name: "logs", - Usage: "Get service logs", - Action: app.WithProject(factory, app.ProjectLog), + Name: "logs", + Usage: "View output from containers.", + ArgsUsage: "[SERVICE...]", + Action: app.WithProject(factory, app.ProjectLog), Flags: []cli.Flag{ cli.IntFlag{ Name: "lines", @@ -132,12 +154,13 @@ func LogsCommand(factory app.ProjectFactory) cli.Command { // RestartCommand defines the libcompose restart subcommand. func RestartCommand(factory app.ProjectFactory) cli.Command { return cli.Command{ - Name: "restart", - Usage: "Restart services", - Action: app.WithProject(factory, app.ProjectRestart), + Name: "restart", + Usage: "Restart running containers.", + ArgsUsage: "[SERVICE...]", + Action: app.WithProject(factory, app.ProjectRestart), Flags: []cli.Flag{ cli.IntFlag{ - Name: "timeout,t", + Name: "timeout, t", Usage: "Specify a shutdown timeout in seconds.", Value: 10, }, @@ -148,10 +171,12 @@ func RestartCommand(factory app.ProjectFactory) cli.Command { // StopCommand defines the libcompose stop subcommand. func StopCommand(factory app.ProjectFactory) cli.Command { return cli.Command{ - Name: "stop", - ShortName: "down", - Usage: "Stop services", - Action: app.WithProject(factory, app.ProjectDown), + Name: "stop", + ShortName: "down", // FIXME shouldn't we deprecate that one ? + Usage: "Stop running containers without removing them.", + ArgsUsage: "[SERVICE...]", + Description: "They can be started again with `libcompose-cli start`.", + Action: app.WithProject(factory, app.ProjectDown), Flags: []cli.Flag{ cli.IntFlag{ Name: "timeout,t", @@ -165,8 +190,12 @@ func StopCommand(factory app.ProjectFactory) cli.Command { // ScaleCommand defines the libcompose scale subcommand. func ScaleCommand(factory app.ProjectFactory) cli.Command { return cli.Command{ - Name: "scale", - Usage: "Scale services", + Name: "scale", + Usage: "Set number of containers to run for a service.", + ArgsUsage: "[SERVICE=NUM...]", + Description: "Numbers are specified in the form `service=num` as arguments.\n" + + "For example:\n\n" + + " $ libcompose-cli scale web=2 worker=3", Action: app.WithProject(factory, app.ProjectScale), Flags: []cli.Flag{ cli.IntFlag{ @@ -181,9 +210,10 @@ func ScaleCommand(factory app.ProjectFactory) cli.Command { // RmCommand defines the libcompose rm subcommand. func RmCommand(factory app.ProjectFactory) cli.Command { return cli.Command{ - Name: "rm", - Usage: "Delete services", - Action: app.WithProject(factory, app.ProjectDelete), + Name: "rm", + Usage: "Remove stopped service containers.", + ArgsUsage: "[SERVICE...]", + Action: app.WithProject(factory, app.ProjectDelete), Flags: []cli.Flag{ cli.BoolFlag{ Name: "force,f", @@ -200,9 +230,10 @@ func RmCommand(factory app.ProjectFactory) cli.Command { // KillCommand defines the libcompose kill subcommand. func KillCommand(factory app.ProjectFactory) cli.Command { return cli.Command{ - Name: "kill", - Usage: "Force stop service containers", - Action: app.WithProject(factory, app.ProjectKill), + Name: "kill", + Usage: "Force stop service containers.", + ArgsUsage: "[SERVICE...]", + Action: app.WithProject(factory, app.ProjectKill), Flags: []cli.Flag{ cli.StringFlag{ Name: "signal,s", diff --git a/cli/command/help.go b/cli/command/help.go index 414b620d0..58067fc40 100644 --- a/cli/command/help.go +++ b/cli/command/help.go @@ -1,21 +1,17 @@ package command import ( - "github.com/codegangsta/cli" "os" "path" + + "github.com/codegangsta/cli" ) func init() { - cli.AppHelpTemplate = `Usage: {{.Name}} {{if .Flags}}[OPTIONS] {{end}}COMMAND [arg...] + cli.AppHelpTemplate = `{{.Usage}} -{{.Usage}} +Usage: {{.Name}} {{if .Flags}}[options] {{end}}COMMAND [arg...] -Version: {{.Version}}{{if or .Author .Email}} - -Author:{{if .Author}} - {{.Author}}{{if .Email}} - <{{.Email}}>{{end}}{{else}} - {{.Email}}{{end}}{{end}} {{if .Flags}} Options: {{range .Flags}}{{.}} @@ -25,11 +21,13 @@ Commands: {{end}} Run '{{.Name}} COMMAND --help' for more information on a command. ` - cli.CommandHelpTemplate = `Usage: ` + path.Base(os.Args[0]) + ` {{.Name}}{{if .Flags}} [OPTIONS] + cli.CommandHelpTemplate = `{{.Usage}}{{if .Description}} -{{.Usage}} +{{.Description}}{{end}} -Options: +Usage: ` + path.Base(os.Args[0]) + ` {{.Name}}{{if .Flags}} [options]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{end}} + +{{if .Flags}}Options: {{range .Flags}}{{.}} {{end}}{{end}} ` diff --git a/integration/common_test.go b/integration/common_test.go index b2f099bd2..21dd8ea7b 100644 --- a/integration/common_test.go +++ b/integration/common_test.go @@ -146,7 +146,7 @@ func (s *RunSuite) createCommand(c *C, projectName, command string, argsAndInput if command == "up" { args = append(args, "-d") - } else if command == "down" { + } else if command == "stop" { args = append(args, "--timeout", "0") } else if command == "restart" { args = append(args, "--timeout", "0") diff --git a/integration/down_test.go b/integration/down_test.go index d481b2c7b..cb091e4b0 100644 --- a/integration/down_test.go +++ b/integration/down_test.go @@ -15,7 +15,7 @@ func (s *RunSuite) TestDown(c *C) { c.Assert(cn, NotNil) c.Assert(cn.State.Running, Equals, true) - s.FromText(c, p, "down", SimpleTemplate) + s.FromText(c, p, "stop", SimpleTemplate) cn = s.GetContainerByName(c, name) c.Assert(cn, NotNil)