Skip to content

Commit

Permalink
multi: Explicitly handle help requests.
Browse files Browse the repository at this point in the history
Checking for --help as an explicit step before parsing any other configs
makes the code more intuitive by removing a convoluted bit of error
handling, which happened to be unnecessarily duplicated in three places.

Moving it to a function in the internal package makes it reusable by
multiple binaries.

This also enables the IgnoreUnknown option to be used whilst parsing for
help, which ensures the presence of --help will always result in the
help message being printed. This fixes a minor inconsistency where the
help message would be printed if the flag was placed before an invalid
config, but placing it after would cause an invalid config error to be
written instead. For example, `vspd --help --fakeflag` vs `vspd
--fakeflag --help`.
  • Loading branch information
jholdstock committed May 18, 2024
1 parent ea6f5e8 commit 2bd340b
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 24 deletions.
15 changes: 7 additions & 8 deletions cmd/vote-validator/main.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022-2023 The Decred developers
// Copyright (c) 2022-2024 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

Expand Down Expand Up @@ -48,15 +48,14 @@ func main() {
}

func run() int {
// Load config, display help if requested.
// If command line options are requesting help, write it to stdout and exit.
if config.WriteHelp(&cfg) {
return 0
}

// Parse command line options.
_, err := flags.Parse(&cfg)
if err != nil {
var e *flags.Error
if errors.As(err, &e) {
if e.Type == flags.ErrHelp {
return 0
}
}
return 1
}

Expand Down
27 changes: 11 additions & 16 deletions cmd/vspd/config.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021-2023 The Decred developers
// Copyright (c) 2021-2024 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

Expand Down Expand Up @@ -190,20 +190,18 @@ func loadConfig() (*vspdConfig, error) {
Designation: defaultDesignation,
}

// Pre-parse the command line options to see if an alternative config
// file or the version flag was specified. Any errors aside from the
// help message error can be ignored here since they will be caught by
// the final parse below.
// If command line options are requesting help, write it to stdout and exit.
if config.WriteHelp(&cfg) {
os.Exit(0)
}

// Pre-parse the command line options to see if an alternative config file,
// home dir, or the version flag were specified.
preCfg := cfg

preParser := flags.NewParser(&preCfg, flags.HelpFlag)
preParser := flags.NewParser(&preCfg, flags.None)
_, err := preParser.Parse()
if err != nil {
var e *flags.Error
if errors.As(err, &e) && e.Type == flags.ErrHelp {
fmt.Fprintln(os.Stdout, err)
os.Exit(0)
}
return nil, err
}

Expand Down Expand Up @@ -261,7 +259,7 @@ func loadConfig() (*vspdConfig, error) {
}

// Load additional config from file.
parser := flags.NewParser(&cfg, flags.Default)
parser := flags.NewParser(&cfg, flags.None)

err = flags.NewIniParser(parser).ParseFile(preCfg.ConfigFile)
if err != nil {
Expand All @@ -271,10 +269,7 @@ func loadConfig() (*vspdConfig, error) {
// Parse command line options again to ensure they take precedence.
_, err = parser.Parse()
if err != nil {
var e *flags.Error
if !errors.As(err, &e) || e.Type != flags.ErrHelp {
fmt.Fprintln(os.Stderr, usageMessage)
}
fmt.Fprintln(os.Stderr, usageMessage)
return nil, err
}

Expand Down
19 changes: 19 additions & 0 deletions internal/config/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) 2024 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package config

import (
"github.com/jessevdk/go-flags"
)

// WriteHelp will write the application help to stdout if it has been requested
// via command line options. Only the help option is evaluated, any invalid
// options are ignored. The return value indicates whether the help message was
// printed or not.
func WriteHelp(cfg interface{}) bool {
helpOpts := flags.Options(flags.HelpFlag | flags.PrintErrors | flags.IgnoreUnknown)
_, err := flags.NewParser(cfg, helpOpts).Parse()
return flags.WroteHelp(err)
}

0 comments on commit 2bd340b

Please sign in to comment.