Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into completion_fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Joshua Rubin committed Nov 18, 2016
2 parents 3272baf + b4f4786 commit 2da4264
Show file tree
Hide file tree
Showing 14 changed files with 608 additions and 77 deletions.
42 changes: 42 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,48 @@
**ATTN**: This project uses [semantic versioning](http://semver.org/).

## [Unreleased]


## [1.19.0] - 2016-11-12
### Added
- `FlagsByName` was added to make it easy to sort flags (e.g. `sort.Sort(cli.FlagsByName(app.Flags))`)
- A `Description` field was added to `App` for a more detailed description of
the application (similar to the existing `Description` field on `Command`)
- Flag type code generation via `go generate`
- Write to stderr and exit 1 if action returns non-nil error
- Added support for TOML to the `altsrc` loader
- `SkipArgReorder` was added to allow users to skip the argument reordering.
This is useful if you want to consider all "flags" after an argument as
arguments rather than flags (the default behavior of the stdlib `flag`
library). This is backported functionality from the [removal of the flag
reordering](https://github.com/urfave/cli/pull/398) in the unreleased version
2

### Changed
- Raise minimum tested/supported Go version to 1.2+

### Fixed
- Consider empty environment variables as set (previously environment variables
with the equivalent of `""` would be skipped rather than their value used).
- Return an error if the value in a given environment variable cannot be parsed
as the flag type. Previously these errors were silently swallowed.
- Print full error when an invalid flag is specified (which includes the invalid flag)
- `App.Writer` defaults to `stdout` when `nil`
- If no action is specified on a command or app, the help is now printed instead of `panic`ing
- `App.Metadata` is initialized automatically now (previously was `nil` unless initialized)
- Correctly show help message if `-h` is provided to a subcommand
- `context.(Global)IsSet` now respects environment variables. Previously it
would return `false` if a flag was specified in the environment rather than
as an argument
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
- `altsrc`s import paths were updated to use `gopkg.in/urfave/cli.v1`. This
fixes issues that occurred when `gopkg.in/urfave/cli.v1` was imported as well
as `altsrc` where Go would complain that the types didn't match

## [1.18.1] - 2016-08-28
### Fixed
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user (backported)

## [1.18.0] - 2016-06-27
### Added
- `./runtests` test runner with coverage tracking by default
Expand All @@ -29,6 +63,10 @@
- No longer swallows `panic`s that occur within the `Action`s themselves when
detecting the signature of the `Action` field

## [1.17.1] - 2016-08-28
### Fixed
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user

## [1.17.0] - 2016-05-09
### Added
- Pluggable flag-level help text rendering via `cli.DefaultFlagStringFunc`
Expand All @@ -50,6 +88,10 @@
- cleanups based on [Go Report Card
feedback](https://goreportcard.com/report/github.com/urfave/cli)

## [1.16.1] - 2016-08-28
### Fixed
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user

## [1.16.0] - 2016-05-02
### Added
- `Hidden` field on all flag struct types to omit from generated help text
Expand Down
8 changes: 3 additions & 5 deletions altsrc/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package altsrc

import (
"fmt"
"os"
"strconv"
"strings"
"syscall"

"gopkg.in/urfave/cli.v1"
)
Expand Down Expand Up @@ -237,13 +237,11 @@ func (f *Float64Flag) ApplyInputSourceValue(context *cli.Context, isc InputSourc
func isEnvVarSet(envVars string) bool {
for _, envVar := range strings.Split(envVars, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
if _, ok := syscall.Getenv(envVar); ok {
// TODO: Can't use this for bools as
// set means that it was true or false based on
// Bool flag type, should work for other types
if len(envVal) > 0 {
return true
}
return true
}
}

Expand Down
16 changes: 14 additions & 2 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,11 @@ func (a *App) Run(arguments []string) (err error) {
shellComplete, arguments := checkShellCompleteFlag(a, arguments)

// parse flags
set := flagSet(a.Name, a.Flags)
set, err := flagSet(a.Name, a.Flags)
if err != nil {
return err
}

set.SetOutput(ioutil.Discard)
err = set.Parse(arguments[1:])
nerr := normalizeFlags(a.Flags, set)
Expand Down Expand Up @@ -247,6 +251,10 @@ func (a *App) Run(arguments []string) (err error) {
}
}

if a.Action == nil {
a.Action = helpCommand.Action
}

// Run default Action
err = HandleAction(a.Action, context)

Expand Down Expand Up @@ -289,7 +297,11 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
a.Commands = newCmds

// parse flags
set := flagSet(a.Name, a.Flags)
set, err := flagSet(a.Name, a.Flags)
if err != nil {
return err
}

set.SetOutput(ioutil.Discard)
err = set.Parse(ctx.Args().Tail())
nerr := normalizeFlags(a.Flags, set)
Expand Down
67 changes: 63 additions & 4 deletions app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,49 @@ func ExampleApp_Run_commandHelp() {
// This is how we describe describeit the function
}

func ExampleApp_Run_noAction() {
app := App{}
app.Name = "greet"
app.Run([]string{"greet"})
// Output:
// NAME:
// greet
//
// USAGE:
// [global options] command [command options] [arguments...]
//
// COMMANDS:
// help, h Shows a list of commands or help for one command
//
// GLOBAL OPTIONS:
// --help, -h show help
// --version, -v print the version
}

func ExampleApp_Run_subcommandNoAction() {
app := App{}
app.Name = "greet"
app.Commands = []Command{
{
Name: "describeit",
Aliases: []string{"d"},
Usage: "use it to see a description",
Description: "This is how we describe describeit the function",
},
}
app.Run([]string{"greet", "describeit"})
// Output:
// NAME:
// describeit - use it to see a description
//
// USAGE:
// describeit [arguments...]
//
// DESCRIPTION:
// This is how we describe describeit the function

}

func ExampleApp_Run_bashComplete() {
// set args for examples sake
os.Args = []string{"greet", "--generate-bash-completion"}
Expand Down Expand Up @@ -1480,7 +1523,11 @@ func TestApp_OnUsageError_WithWrongFlagValue_ForSubcommand(t *testing.T) {
func TestHandleAction_WithNonFuncAction(t *testing.T) {
app := NewApp()
app.Action = 42
err := HandleAction(app.Action, NewContext(app, flagSet(app.Name, app.Flags), nil))
fs, err := flagSet(app.Name, app.Flags)
if err != nil {
t.Errorf("error creating FlagSet: %s", err)
}
err = HandleAction(app.Action, NewContext(app, fs, nil))

if err == nil {
t.Fatalf("expected to receive error from Run, got none")
Expand All @@ -1504,7 +1551,11 @@ func TestHandleAction_WithNonFuncAction(t *testing.T) {
func TestHandleAction_WithInvalidFuncSignature(t *testing.T) {
app := NewApp()
app.Action = func() string { return "" }
err := HandleAction(app.Action, NewContext(app, flagSet(app.Name, app.Flags), nil))
fs, err := flagSet(app.Name, app.Flags)
if err != nil {
t.Errorf("error creating FlagSet: %s", err)
}
err = HandleAction(app.Action, NewContext(app, fs, nil))

if err == nil {
t.Fatalf("expected to receive error from Run, got none")
Expand All @@ -1528,7 +1579,11 @@ func TestHandleAction_WithInvalidFuncSignature(t *testing.T) {
func TestHandleAction_WithInvalidFuncReturnSignature(t *testing.T) {
app := NewApp()
app.Action = func(_ *Context) (int, error) { return 0, nil }
err := HandleAction(app.Action, NewContext(app, flagSet(app.Name, app.Flags), nil))
fs, err := flagSet(app.Name, app.Flags)
if err != nil {
t.Errorf("error creating FlagSet: %s", err)
}
err = HandleAction(app.Action, NewContext(app, fs, nil))

if err == nil {
t.Fatalf("expected to receive error from Run, got none")
Expand Down Expand Up @@ -1559,7 +1614,11 @@ func TestHandleAction_WithUnknownPanic(t *testing.T) {
fn(ctx)
return nil
}
HandleAction(app.Action, NewContext(app, flagSet(app.Name, app.Flags), nil))
fs, err := flagSet(app.Name, app.Flags)
if err != nil {
t.Errorf("error creating FlagSet: %s", err)
}
HandleAction(app.Action, NewContext(app, fs, nil))
}

func TestShellCompletionForIncompleteFlags(t *testing.T) {
Expand Down
9 changes: 8 additions & 1 deletion command.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ func (c Command) Run(ctx *Context) (err error) {
)
}

set := flagSet(c.Name, c.Flags)
set, err := flagSet(c.Name, c.Flags)
if err != nil {
return err
}
set.SetOutput(ioutil.Discard)

if c.SkipFlagParsing {
Expand Down Expand Up @@ -182,6 +185,10 @@ func (c Command) Run(ctx *Context) (err error) {
}
}

if c.Action == nil {
c.Action = helpSubcommand.Action
}

context.Command = c
err = HandleAction(c.Action, context)

Expand Down
9 changes: 7 additions & 2 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package cli
import (
"errors"
"flag"
"os"
"reflect"
"strings"
"syscall"
)

// Context is a type that is passed through to
Expand Down Expand Up @@ -98,7 +98,7 @@ func (c *Context) IsSet(name string) bool {

eachName(envVarValue.String(), func(envVar string) {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
if _, ok := syscall.Getenv(envVar); ok {
c.setFlags[name] = true
return
}
Expand Down Expand Up @@ -154,6 +154,11 @@ func (c *Context) Parent() *Context {
return c.parentContext
}

// value returns the value of the flag coressponding to `name`
func (c *Context) value(name string) interface{} {
return c.flagSet.Lookup(name).Value.(flag.Getter).Get()
}

// Args contains apps console arguments
type Args []string

Expand Down
Loading

0 comments on commit 2da4264

Please sign in to comment.