Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(575)

Delta Between Two Patch Sets: cmd/cmd.go

Issue 12603047: Extra options for ssh/scp don't cause errors.
Left Patch Set: Created 11 years, 7 months ago
Right Patch Set: Extra options for ssh/scp don't cause errors. Created 11 years, 7 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « [revision details] ('k') | cmd/juju/debuglog.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // Copyright 2012, 2013 Canonical Ltd. 1 // Copyright 2012, 2013 Canonical Ltd.
2 // Licensed under the AGPLv3, see LICENCE file for details. 2 // Licensed under the AGPLv3, see LICENCE file for details.
3 3
4 package cmd 4 package cmd
5 5
6 import ( 6 import (
7 "bytes" 7 "bytes"
8 "errors" 8 "errors"
9 "fmt" 9 "fmt"
10 "io" 10 "io"
(...skipping 16 matching lines...) Expand all
27 27
28 // SetFlags adds command specific flags to the flag set. 28 // SetFlags adds command specific flags to the flag set.
29 SetFlags(f *gnuflag.FlagSet) 29 SetFlags(f *gnuflag.FlagSet)
30 30
31 // Init initializes the Command before running. 31 // Init initializes the Command before running.
32 Init(args []string) error 32 Init(args []string) error
33 33
34 // Run will execute the Command as directed by the options and positiona l 34 // Run will execute the Command as directed by the options and positiona l
35 // arguments passed to Init. 35 // arguments passed to Init.
36 Run(ctx *Context) error 36 Run(ctx *Context) error
37
38 // AllowInterspersedFlags returns whether the command allows flag
39 // arguments to be interspersed with non-flag arguments.
40 AllowInterspersedFlags() bool
37 } 41 }
38 42
39 // CommandBase provides the default implementation for SetFlags, Init, and Help. 43 // CommandBase provides the default implementation for SetFlags, Init, and Help.
40 type CommandBase struct{} 44 type CommandBase struct{}
41 45
42 // SetFlags does nothing in the simplest case. 46 // SetFlags does nothing in the simplest case.
43 func (c *CommandBase) SetFlags(f *gnuflag.FlagSet) {} 47 func (c *CommandBase) SetFlags(f *gnuflag.FlagSet) {}
44 48
45 // Init in the simplest case makes sure there are no args. 49 // Init in the simplest case makes sure there are no args.
46 func (c *CommandBase) Init(args []string) error { 50 func (c *CommandBase) Init(args []string) error {
47 return CheckEmpty(args) 51 return CheckEmpty(args)
52 }
53
54 // AllowInterspersedFlags returns true by default. Some subcommands
55 // may want to override this.
56 func (c *CommandBase) AllowInterspersedFlags() bool {
57 return true
48 } 58 }
49 59
50 // Context represents the run context of a Command. Command implementations 60 // Context represents the run context of a Command. Command implementations
51 // should interpret file names relative to Dir (see AbsPath below), and print 61 // should interpret file names relative to Dir (see AbsPath below), and print
52 // output and errors to Stdout and Stderr respectively. 62 // output and errors to Stdout and Stderr respectively.
53 type Context struct { 63 type Context struct {
54 Dir string 64 Dir string
55 Stdin io.Reader 65 Stdin io.Reader
56 Stdout io.Writer 66 Stdout io.Writer
57 Stderr io.Writer 67 Stderr io.Writer
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 f.SetOutput(ioutil.Discard) 119 f.SetOutput(ioutil.Discard)
110 if i.Doc != "" { 120 if i.Doc != "" {
111 fmt.Fprintf(buf, "\n%s\n", strings.TrimSpace(i.Doc)) 121 fmt.Fprintf(buf, "\n%s\n", strings.TrimSpace(i.Doc))
112 } 122 }
113 if len(i.Aliases) > 0 { 123 if len(i.Aliases) > 0 {
114 fmt.Fprintf(buf, "\naliases: %s\n", strings.Join(i.Aliases, ", " )) 124 fmt.Fprintf(buf, "\naliases: %s\n", strings.Join(i.Aliases, ", " ))
115 } 125 }
116 return buf.Bytes() 126 return buf.Bytes()
117 } 127 }
118 128
119 // ParseArgs encapsulate the parsing of the args so this function can be
120 // called from the testing module too.
121 func ParseArgs(c Command, f *gnuflag.FlagSet, args []string) error {
122 // If the command is a SuperCommand, we want to parse the args with
123 // allowIntersperse=false (i.e. the first parameter to Parse. This will
124 // mean that the args may contain other options that haven't been define d
125 // yet, and that only options that relate to the SuperCommand itself can
126 // come prior to the subcommand name.
127 _, isSuperCommand := c.(*SuperCommand)
128 return f.Parse(!isSuperCommand, args)
129 }
130
131 // Errors from commands can be either ErrHelp, which means "show the help" or 129 // Errors from commands can be either ErrHelp, which means "show the help" or
132 // some other error related to needed flags missing, or needed positional args 130 // some other error related to needed flags missing, or needed positional args
133 // missing, in which case we should print the error and return a non-zero 131 // missing, in which case we should print the error and return a non-zero
134 // return code. 132 // return code.
135 func handleCommandError(c Command, ctx *Context, err error, f *gnuflag.FlagSet) (int, bool) { 133 func handleCommandError(c Command, ctx *Context, err error, f *gnuflag.FlagSet) (int, bool) {
136 if err == gnuflag.ErrHelp { 134 if err == gnuflag.ErrHelp {
137 ctx.Stdout.Write(c.Info().Help(f)) 135 ctx.Stdout.Write(c.Info().Help(f))
138 return 0, true 136 return 0, true
139 } 137 }
140 if err != nil { 138 if err != nil {
141 fmt.Fprintf(ctx.Stderr, "error: %v\n", err) 139 fmt.Fprintf(ctx.Stderr, "error: %v\n", err)
142 return 2, true 140 return 2, true
143 } 141 }
144 return 0, false 142 return 0, false
145 } 143 }
146 144
147 // Main runs the given Command in the supplied Context with the given 145 // Main runs the given Command in the supplied Context with the given
148 // arguments, which should not include the command name. It returns a code 146 // arguments, which should not include the command name. It returns a code
149 // suitable for passing to os.Exit. 147 // suitable for passing to os.Exit.
150 func Main(c Command, ctx *Context, args []string) int { 148 func Main(c Command, ctx *Context, args []string) int {
151 f := gnuflag.NewFlagSet(c.Info().Name, gnuflag.ContinueOnError) 149 f := gnuflag.NewFlagSet(c.Info().Name, gnuflag.ContinueOnError)
152 f.SetOutput(ioutil.Discard) 150 f.SetOutput(ioutil.Discard)
153 c.SetFlags(f) 151 c.SetFlags(f)
154 » if rc, done := handleCommandError(c, ctx, ParseArgs(c, f, args), f); don e { 152 » if rc, done := handleCommandError(c, ctx, f.Parse(c.AllowInterspersedFla gs(), args), f); done {
155 return rc 153 return rc
156 } 154 }
157 // Since SuperCommands can also return gnuflag.ErrHelp errors, we need t o 155 // Since SuperCommands can also return gnuflag.ErrHelp errors, we need t o
158 // handle both those types of errors as well as "real" errors. 156 // handle both those types of errors as well as "real" errors.
159 if rc, done := handleCommandError(c, ctx, c.Init(f.Args()), f); done { 157 if rc, done := handleCommandError(c, ctx, c.Init(f.Args()), f); done {
160 return rc 158 return rc
161 } 159 }
162 if err := c.Run(ctx); err != nil { 160 if err := c.Run(ctx); err != nil {
163 if err != ErrSilent { 161 if err != ErrSilent {
164 fmt.Fprintf(ctx.Stderr, "error: %v\n", err) 162 fmt.Fprintf(ctx.Stderr, "error: %v\n", err)
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 func ZeroOrOneArgs(args []string) (string, error) { 197 func ZeroOrOneArgs(args []string) (string, error) {
200 var result string 198 var result string
201 if len(args) > 0 { 199 if len(args) > 0 {
202 result, args = args[0], args[1:] 200 result, args = args[0], args[1:]
203 } 201 }
204 if err := CheckEmpty(args); err != nil { 202 if err := CheckEmpty(args); err != nil {
205 return "", err 203 return "", err
206 } 204 }
207 return result, nil 205 return result, nil
208 } 206 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b