Skip to content

Commit

Permalink
add support for an optional --version flag
Browse files Browse the repository at this point in the history
  • Loading branch information
costela committed Jan 30, 2019
1 parent 08d48f0 commit 79bd756
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 9 deletions.
4 changes: 4 additions & 0 deletions flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ func parseFlagsToMap(s *setup, args []string) (map[string]string, error) {
printHelpAndExit(s)
}

if s.conf.VersionString != "" && arg == "--version" {
printVersionAndExit(s)
}

if arg == "--" {
// separator that indicates end of flags
return result, nil
Expand Down
4 changes: 4 additions & 0 deletions gonfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ type Conf struct {
// HelpDescription is the description to print for the help flag.
// By default, this is "show this help menu".
HelpDescription string

// VersionString is the current program version printed when the --version
// flag is passed. If left empty, the --version flag is disabled.
VersionString string
}

// setup is the struct that keeps track of the state of the program throughout
Expand Down
48 changes: 43 additions & 5 deletions gonfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package gonfig

import (
"bytes"
"encoding/hex"
"errors"
"io/ioutil"
Expand All @@ -21,9 +22,14 @@ import (
var (
testTimeStr = "2009-11-10T23:00:00Z"
testTime *time.Time
testOutput bytes.Buffer
)

type exitCode int

func init() {
helpOutput = &testOutput
exiter = func(i int) { panic(exitCode(i)) }
testTime = &time.Time{}
if err := testTime.UnmarshalText([]byte(testTimeStr)); err != nil {
panic(err)
Expand Down Expand Up @@ -140,10 +146,12 @@ func TestGonfig(t *testing.T) {

conf Conf

config interface{}
shouldError bool
shouldPanic bool
validate func(t *testing.T, config interface{})
config interface{}
shouldError bool
shouldPanic bool
shouldExit bool
validate func(t *testing.T, config interface{})
validateOutput func(t *testing.T, output string)
}{
{
desc: "only defaults",
Expand Down Expand Up @@ -786,6 +794,21 @@ func TestGonfig(t *testing.T) {
config: &TestStruct{},
shouldError: true,
},
{
desc: "show version",
args: []string{"--version"},
env: map[string]string{},
conf: Conf{
FileDisable: true,
VersionString: "v0.0.0",
},
config: &TestStruct{},
shouldError: false,
shouldExit: true,
validateOutput: func(t *testing.T, output string) {
assert.Equal(t, output, "v0.0.0\n")
},
},
}

for _, tc := range testCases {
Expand All @@ -807,16 +830,31 @@ func TestGonfig(t *testing.T) {

conf := tc.conf
conf.FileDefaultFilename = filename
testOutput.Reset()

if tc.shouldPanic {
require.Panics(t, func() { Load(tc.config, conf) })
} else if tc.shouldError {
require.Error(t, Load(tc.config, conf))
} else {
require.NoError(t, Load(tc.config, conf))
require.NoError(t, func() error {
defer func() {
r := recover()
// got an exitCode or no panic AND this doesn't match expectations => error
if _, ok := r.(exitCode); (ok || r == nil) && (r != nil) != tc.shouldExit {
t.Errorf("expected to exit? %v, exited? %v", tc.shouldExit, r != nil)
} else if !ok && r != nil {
panic(r) // avoid shadowing actual panics
}
}()
return Load(tc.config, conf)
}())
if tc.validate != nil {
tc.validate(t, tc.config)
}
if tc.validateOutput != nil {
tc.validateOutput(t, testOutput.String())
}
}
})
}
Expand Down
23 changes: 19 additions & 4 deletions help.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import (
)

const (
defaultHelpDescription = "print this help menu"
defaultHelpMessage = "Usage of __EXEC__:"
defaultHelpDescription = "print this help menu"
defaultHelpMessage = "Usage of __EXEC__:"
defaultVersionDescription = "print the program version"
)

func typeString(t reflect.Type) string {
Expand Down Expand Up @@ -200,6 +201,10 @@ func writeHelpMessage(s *setup, w io.Writer) {
}
lines = append(lines, " -h, --help\x00"+helpFlagDesc)

if s.conf.VersionString != "" {
lines = append(lines, " --version\x00"+defaultVersionDescription)
}

message := s.conf.HelpMessage
if message == "" {
exec := path.Base(os.Args[0])
Expand All @@ -219,8 +224,18 @@ func writeHelpMessage(s *setup, w io.Writer) {
}
}

// used to capture output for tests
var helpOutput io.Writer = os.Stdout
var exiter = os.Exit

// printHelpAndExit prints the help message and exits the program.
func printHelpAndExit(s *setup) {
writeHelpMessage(s, os.Stdout)
os.Exit(2)
writeHelpMessage(s, helpOutput)
exiter(2)
}

// printHelpAndExit prints the help message and exits the program.
func printVersionAndExit(s *setup) {
fmt.Fprintln(helpOutput, s.conf.VersionString)
exiter(0)
}

0 comments on commit 79bd756

Please sign in to comment.