From a4b11d8c8e35bfd62ea0a4b5e24b3ebdf5579bea Mon Sep 17 00:00:00 2001 From: seanseannery Date: Sat, 7 Mar 2026 11:50:41 -0800 Subject: [PATCH] fix(flags): preserve parsed flags when --help is combined with -D ParseOpsFlags was returning a zero-value OpsFlags when ErrHelp was triggered, discarding any flags parsed before --help/-h/-?. This caused the --help path in main.go to ignore -D and fail to find the Opsfile. --- internal/flag_parser.go | 25 +++++++++++++++++++++---- internal/flag_parser_test.go | 19 +++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/internal/flag_parser.go b/internal/flag_parser.go index 9e3e91f..cae1599 100644 --- a/internal/flag_parser.go +++ b/internal/flag_parser.go @@ -64,20 +64,37 @@ Flags:`) fs.PrintDefaults() } - // -? is not a valid flag name; handle it before fs.Parse. + // -? is not a valid pflag name; strip it before fs.Parse so other flags + // (like -D) are still parsed and returned alongside ErrHelp. + helpQuestion := false for _, a := range osArgs { if a == "-?" { - fs.Usage() - return OpsFlags{}, nil, ErrHelp + helpQuestion = true + break } } + if helpQuestion { + filtered := make([]string, 0, len(osArgs)) + for _, a := range osArgs { + if a != "-?" { + filtered = append(filtered, a) + } + } + osArgs = filtered + } if err := fs.Parse(osArgs); err != nil { if errors.Is(err, pflag.ErrHelp) { - return OpsFlags{}, nil, ErrHelp + return OpsFlags{Directory: *dir, DryRun: *dryRun, List: *list, Silent: *silent, Version: *ver}, nil, ErrHelp } return OpsFlags{}, nil, err } + + if helpQuestion { + fs.Usage() + return OpsFlags{Directory: *dir, DryRun: *dryRun, List: *list, Silent: *silent, Version: *ver}, nil, ErrHelp + } + return OpsFlags{Directory: *dir, DryRun: *dryRun, List: *list, Silent: *silent, Version: *ver}, fs.Args(), nil } diff --git a/internal/flag_parser_test.go b/internal/flag_parser_test.go index 1350a3c..ba9fe34 100644 --- a/internal/flag_parser_test.go +++ b/internal/flag_parser_test.go @@ -125,6 +125,24 @@ func TestParseOpsFlags(t *testing.T) { input: []string{"-?", "prod", "cmd"}, wantErr: ErrHelp, }, + { + name: "-D combined with --help preserves Directory", + input: []string{"-D", "/some/path", "--help"}, + wantFlags: OpsFlags{Directory: "/some/path"}, + wantErr: ErrHelp, + }, + { + name: "-D combined with -? preserves Directory", + input: []string{"-D", "/some/path", "-?"}, + wantFlags: OpsFlags{Directory: "/some/path"}, + wantErr: ErrHelp, + }, + { + name: "-D combined with -h preserves Directory", + input: []string{"-D", "/some/path", "-h"}, + wantFlags: OpsFlags{Directory: "/some/path"}, + wantErr: ErrHelp, + }, { name: "-D with empty string value", input: []string{"-D", "", "prod", "cmd"}, @@ -163,6 +181,7 @@ func TestParseOpsFlags(t *testing.T) { if tc.wantErr != nil { require.ErrorIs(t, err, tc.wantErr) + assert.Equal(t, tc.wantFlags, gotFlags) return } if tc.wantErrSub != "" {