Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for an optional --version flag #34

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
}