Exemple #1
0
func executeCommand(name string, cmd *command, args []string, a *app.App) (err error) {
	// Parse command flags
	set := flag.NewFlagSet(name, flag.ContinueOnError)
	set.Usage = func() {
		commandHelp(name, -1, os.Stderr)
	}
	flags := map[string]interface{}{}
	for _, arg := range cmd.opts.Flags {
		switch arg.typ {
		case typBool:
			var b bool
			set.BoolVar(&b, arg.name, arg.def.(bool), arg.help)
			flags[arg.name] = &b
		case typInt:
			var i int
			set.IntVar(&i, arg.name, arg.def.(int), arg.help)
			flags[arg.name] = &i
		case typString:
			var s string
			set.StringVar(&s, arg.name, arg.def.(string), arg.help)
			flags[arg.name] = &s
		default:
			panic("invalid arg type")
		}
	}
	// Print error/help messages ourselves
	set.SetOutput(ioutil.Discard)
	err = set.Parse(args)
	if err != nil {
		if err == flag.ErrHelp {
			return
		}
		if strings.Contains(err.Error(), "provided but not defined") {
			flagName := strings.TrimSpace(strings.Split(err.Error(), ":")[1])
			fmt.Fprintf(os.Stderr, "command %s does not accept flag %s\n", name, flagName)
			return
		}
		return err
	}
	var params []string
	paramValues := make(map[string]string)
	for _, arg := range cmd.opts.Flags {
		params = append(params, arg.name)
		paramValues[arg.name] = fmt.Sprintf("%v", reflect.ValueOf(flags[arg.name]).Elem().Interface())
	}
	provider := &contextProvider{
		args:        set.Args(),
		params:      params,
		paramValues: paramValues,
	}
	if os.Getenv("GONDOLA_COMMANDS_NO_RECOVER") == "" {
		defer func() {
			if r := recover(); r != nil {
				if e, ok := r.(error); ok {
					err = e
				} else {
					err = fmt.Errorf("%v", r)
				}
				if file, line, ok := runtimeutil.PanicLocation(); ok {
					err = fmt.Errorf("%v (at %s:%d)", err, file, line)
				}
			}
		}()
	}
	ctx := a.NewContext(provider)
	defer a.CloseContext(ctx)
	cmd.handler(ctx)
	return
}