~ubuntu-branches/ubuntu/saucy/juju-core/saucy

« back to all changes in this revision

Viewing changes to src/launchpad.net/juju-core/cmd/supercommand.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 16:02:16 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20130820160216-5yu1llasa2e2youn
Tags: 1.13.1-0ubuntu1
* New upstream release.
  - Build and install juju metadata plugin.
  - d/NEWS: Add some guidance on upgrading environments from 1.11.x
    to 1.13.x.
* d/NEWS: Add details about lack of upgrade path from juju < 1.11
  and how to interact with older juju environments.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
import (
7
7
        "bytes"
8
8
        "fmt"
 
9
        "io/ioutil"
9
10
        "sort"
10
11
        "strings"
11
12
 
34
35
// SuperCommandParams provides a way to have default parameter to the
35
36
// `NewSuperCommand` call.
36
37
type SuperCommandParams struct {
 
38
        UsagePrefix     string
37
39
        Name            string
38
40
        Purpose         string
39
41
        Doc             string
49
51
                Purpose:         params.Purpose,
50
52
                Doc:             params.Doc,
51
53
                Log:             params.Log,
 
54
                usagePrefix:     params.UsagePrefix,
52
55
                missingCallback: params.MissingCallback}
53
56
        command.init()
54
57
        return command
64
67
        Purpose         string
65
68
        Doc             string
66
69
        Log             *Log
 
70
        usagePrefix     string
67
71
        subcmds         map[string]Command
 
72
        commonflags     *gnuflag.FlagSet
68
73
        flags           *gnuflag.FlagSet
69
74
        subcmd          Command
70
75
        showHelp        bool
 
76
        showDescription bool
 
77
        showVersion     bool
71
78
        missingCallback MissingCallback
72
79
}
73
80
 
172
179
 
173
180
const helpPurpose = "show help on a command or other topic"
174
181
 
 
182
// setCommonFlags creates a new "commonflags" flagset, whose
 
183
// flags are shared with the argument f; this enables us to
 
184
// add non-global flags to f, which do not carry into subcommands.
 
185
func (c *SuperCommand) setCommonFlags(f *gnuflag.FlagSet) {
 
186
        if c.Log != nil {
 
187
                c.Log.AddFlags(f)
 
188
        }
 
189
        f.BoolVar(&c.showHelp, "h", false, helpPurpose)
 
190
        f.BoolVar(&c.showHelp, "help", false, "")
 
191
        // In the case where we are providing the basis for a plugin,
 
192
        // plugins are required to support the --description argument.
 
193
        // The Purpose attribute will be printed (if defined), allowing
 
194
        // plugins to provide a sensible line of text for 'juju help plugins'.
 
195
        f.BoolVar(&c.showDescription, "description", false, "")
 
196
 
 
197
        c.commonflags = gnuflag.NewFlagSet(c.Info().Name, gnuflag.ContinueOnError)
 
198
        c.commonflags.SetOutput(ioutil.Discard)
 
199
        f.VisitAll(func(flag *gnuflag.Flag) {
 
200
                c.commonflags.Var(flag.Value, flag.Name, flag.Usage)
 
201
        })
 
202
}
 
203
 
175
204
// SetFlags adds the options that apply to all commands, particularly those
176
205
// due to logging.
177
206
func (c *SuperCommand) SetFlags(f *gnuflag.FlagSet) {
178
 
        if c.Log != nil {
179
 
                c.Log.AddFlags(f)
180
 
        }
181
 
        f.BoolVar(&c.showHelp, "h", false, helpPurpose)
182
 
        f.BoolVar(&c.showHelp, "help", false, "")
183
 
 
 
207
        c.setCommonFlags(f)
 
208
        // Only flags set by setCommonFlags are passed on to subcommands.
 
209
        // Any flags added below only take effect when no subcommand is
 
210
        // specified (e.g. juju --version).
 
211
        f.BoolVar(&c.showVersion, "version", false, "Show the version of juju")
184
212
        c.flags = f
185
213
}
186
214
 
187
215
// Init initializes the command for running.
188
216
func (c *SuperCommand) Init(args []string) error {
 
217
        if c.showDescription {
 
218
                return CheckEmpty(args)
 
219
        }
189
220
        if len(args) == 0 {
190
221
                c.subcmd = c.subcmds["help"]
191
222
                return nil
207
238
                return fmt.Errorf("unrecognized command: %s %s", c.Name, args[0])
208
239
        }
209
240
        args = args[1:]
210
 
        c.subcmd.SetFlags(c.flags)
211
 
        if err := c.flags.Parse(true, args); err != nil {
 
241
        c.subcmd.SetFlags(c.commonflags)
 
242
        if err := c.commonflags.Parse(true, args); err != nil {
212
243
                return err
213
244
        }
214
 
        args = c.flags.Args()
 
245
        args = c.commonflags.Args()
215
246
        if c.showHelp {
216
247
                // We want to treat help for the command the same way we would if we went "help foo".
217
248
                args = []string{c.subcmd.Info().Name}
222
253
 
223
254
// Run executes the subcommand that was selected in Init.
224
255
func (c *SuperCommand) Run(ctx *Context) error {
 
256
        if c.showDescription {
 
257
                if c.Purpose != "" {
 
258
                        fmt.Fprintf(ctx.Stdout, "%s\n", c.Purpose)
 
259
                } else {
 
260
                        fmt.Fprintf(ctx.Stdout, "%s: no description available\n", c.Info().Name)
 
261
                }
 
262
                return nil
 
263
        }
225
264
        if c.subcmd == nil {
226
265
                panic("Run: missing subcommand; Init failed or not called")
227
266
        }
264
303
 
265
304
type helpCommand struct {
266
305
        CommandBase
267
 
        super  *SuperCommand
268
 
        topic  string
269
 
        topics map[string]topic
 
306
        super     *SuperCommand
 
307
        topic     string
 
308
        topicArgs []string
 
309
        topics    map[string]topic
270
310
}
271
311
 
272
312
func (c *helpCommand) init() {
307
347
`)
308
348
 
309
349
        f := gnuflag.NewFlagSet("", gnuflag.ContinueOnError)
310
 
        c.super.SetFlags(f)
 
350
        c.super.setCommonFlags(f)
311
351
        f.SetOutput(buf)
312
352
        f.PrintDefaults()
313
353
        return buf.String()
349
389
        case 1:
350
390
                c.topic = args[0]
351
391
        default:
352
 
                return fmt.Errorf("extra arguments to command help: %q", args[2:])
 
392
                if c.super.missingCallback == nil {
 
393
                        return fmt.Errorf("extra arguments to command help: %q", args[1:])
 
394
                } else {
 
395
                        c.topic = args[0]
 
396
                        c.topicArgs = args[1:]
 
397
                }
353
398
        }
354
399
        return nil
355
400
}
356
401
 
357
402
func (c *helpCommand) Run(ctx *Context) error {
 
403
        if c.super.showVersion {
 
404
                var v VersionCommand
 
405
                v.SetFlags(c.super.flags)
 
406
                v.Init(nil)
 
407
                return v.Run(ctx)
 
408
        }
 
409
 
358
410
        // If there is no help topic specified, print basic usage.
359
411
        if c.topic == "" {
360
412
                if _, ok := c.topics["basics"]; ok {
376
428
        if helpcmd, ok := c.super.subcmds[c.topic]; ok {
377
429
                info := helpcmd.Info()
378
430
                info.Name = fmt.Sprintf("%s %s", c.super.Name, info.Name)
 
431
                if c.super.usagePrefix != "" {
 
432
                        info.Name = fmt.Sprintf("%s %s", c.super.usagePrefix, info.Name)
 
433
                }
379
434
                f := gnuflag.NewFlagSet(info.Name, gnuflag.ContinueOnError)
380
435
                helpcmd.SetFlags(f)
381
436
                ctx.Stdout.Write(info.Help(f))
389
444
        }
390
445
        // If we have a missing callback, call that with --help
391
446
        if c.super.missingCallback != nil {
 
447
                helpArgs := []string{"--", "--help"}
 
448
                if len(c.topicArgs) > 0 {
 
449
                        helpArgs = append(helpArgs, c.topicArgs...)
 
450
                }
392
451
                subcmd := &missingCommand{
393
452
                        callback:  c.super.missingCallback,
394
453
                        superName: c.super.Name,
395
454
                        name:      c.topic,
396
 
                        args:      []string{"--", "--help"},
 
455
                        args:      helpArgs,
397
456
                }
398
457
                err := subcmd.Run(ctx)
399
458
                _, isUnrecognized := err.(*UnrecognizedCommand)