Skip to content
Merged
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func main() {
| `flagrun.Version(version string)` | バージョン表示に使用する文字列を指定します。 |
| `flagrun.Commit(commit string)` | コミットハッシュなどを指定します(デフォルト: `dev`)。 |
| `flagrun.ArgsRequired()` | コマンドライン引数を必須にします。引数がない場合は UNKNOWN で終了します。 |
| `flagrun.AlwaysStdout()` | `Run` の戻り値を、終了コードに関係なく標準出力へ出力します。 |

## 終了コード

Expand Down
49 changes: 39 additions & 10 deletions flagrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"reflect"
"runtime"
"runtime/debug"
"strings"

"github.com/jessevdk/go-flags"
Expand All @@ -27,6 +28,7 @@ type Flagrun struct {
ArgsRequired bool
Version string
Commit string
AlwaysStdout bool
}

type FlagrunOptions func(*Flagrun)
Expand All @@ -53,6 +55,12 @@ func ArgsRequired() FlagrunOptions {
}
}

func AlwaysStdout() FlagrunOptions {
return func(f *Flagrun) {
f.AlwaysStdout = true
}
}

func printLine(w io.Writer, s string) error {
if w == nil {
return nil
Expand All @@ -65,9 +73,9 @@ func printLine(w io.Writer, s string) error {
}

func Go(opt Runner, options ...FlagrunOptions) int {
msg, code := internalGo(os.Args[1:], os.Stdout, os.Stderr, opt, options...)
f, msg, code := internalGo(os.Args[1:], os.Stdout, os.Stderr, opt, options...)
if msg != "" {
if code == OK {
if code == OK || f.AlwaysStdout {
_ = printLine(os.Stdout, msg)
} else {
_ = printLine(os.Stderr, msg)
Expand Down Expand Up @@ -105,15 +113,36 @@ func hasBooleanVersionField(opt Runner) bool {
return ok && field.Type.Kind() == reflect.Bool && v.FieldByName("Version").Bool()
}

func buildCommitHash() string {
commit := "dev"
dirty := false
if info, ok := debug.ReadBuildInfo(); ok {
for _, setting := range info.Settings {
if setting.Key == "vcs.revision" && setting.Value != "" {
commit = setting.Value
} else if setting.Key == "vcs.modified" && setting.Value == "true" {
dirty = true
}
}
Comment thread
kazeburo marked this conversation as resolved.
}
if len(commit) > 7 {
commit = commit[:7]
}
if dirty {
commit += "-dirty"
}
return commit
}

func internalGo(
argv []string,
stdout io.Writer,
stderr io.Writer,
opt Runner,
options ...FlagrunOptions,
) (string, int) {
) (*Flagrun, string, int) {
f := &Flagrun{
Commit: "dev",
Commit: buildCommitHash(),
Version: "unknown",
}
for _, option := range options {
Expand All @@ -136,18 +165,18 @@ func internalGo(
runtime.GOARCH,
runtime.Version(),
f.Commit)
return "", OK
return f, "", OK
} else if flags.WroteHelp(err) {
fmt.Fprintf(stdout, "%v\n", err)
return "", OK
return f, "", OK
} else if err != nil {
fmt.Fprintf(stderr, "%v\n", err)
return "", UNKNOWN
return f, "", UNKNOWN
} else if f.ArgsRequired && len(args) == 0 {
fmt.Fprintf(stderr, "command is required\n")
psr.WriteHelp(stderr)
return "", UNKNOWN
return f, "", UNKNOWN
}

return opt.Run(args)
msg, code := opt.Run(args)
return f, msg, code
}
8 changes: 5 additions & 3 deletions flagrun_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

type testRunner struct {
Expand Down Expand Up @@ -84,10 +85,10 @@ func TestInternalGo(t *testing.T) {
}
var stdout bytes.Buffer
var stderr bytes.Buffer
msg, code := internalGo(tt.args, &stdout, &stderr, o, options...)
f, msg, code := internalGo(tt.args, &stdout, &stderr, o, options...)
stdoutStr := stdout.String()
stderrStr := stderr.String()

require.NotNil(t, f, "%s Flagrun instance should not be nil", tt.name)
assert.Equal(t, tt.wantMsg, msg, "%s msg", tt.name)
assert.Contains(t, stdoutStr, tt.wantStdout, "%s stdout", tt.name)
assert.Contains(t, stderrStr, tt.wantStderr, "%s stderr", tt.name)
Expand All @@ -112,10 +113,11 @@ func TestInternalGoWithRequiredParameters(t *testing.T) {
o := &requiredRunner{}
var stdout bytes.Buffer
var stderr bytes.Buffer
msg, code := internalGo([]string{}, &stdout, &stderr, o)
f, msg, code := internalGo([]string{}, &stdout, &stderr, o)
stdoutStr := stdout.String()
stderrStr := stderr.String()

assert.NotNil(t, f, "Flagrun instance should not be nil")
assert.Equal(t, "", msg)
assert.Contains(t, stdoutStr, "")
assert.Contains(t, stderrStr, "the required flag `-r, --required")
Expand Down