diff --git a/turbo/app/import.go b/turbo/app/import.go index 66336cd49d7..58ba1c81bb0 100644 --- a/turbo/app/import.go +++ b/turbo/app/import.go @@ -30,7 +30,7 @@ const ( ) var importCommand = cli.Command{ - Action: importChain, + Action: MigrateFlags(importChain), Name: "import", Usage: "Import a blockchain file", ArgsUsage: " ( ... ) ", diff --git a/turbo/app/init.go b/turbo/app/init.go index c4460547f4a..886ede8bdf2 100644 --- a/turbo/app/init.go +++ b/turbo/app/init.go @@ -14,7 +14,7 @@ import ( ) var initCommand = cli.Command{ - Action: initGenesis, + Action: MigrateFlags(initGenesis), Name: "init", Usage: "Bootstrap and initialize a new genesis block", ArgsUsage: "", diff --git a/turbo/app/make_app.go b/turbo/app/make_app.go index aa0173c206d..139709b128d 100644 --- a/turbo/app/make_app.go +++ b/turbo/app/make_app.go @@ -2,6 +2,8 @@ package app import ( + "strings" + "github.com/urfave/cli/v2" "github.com/ledgerwatch/erigon/cmd/utils" @@ -33,6 +35,63 @@ func MakeApp(action cli.ActionFunc, cliFlags []cli.Flag) *cli.App { return app } +// MigrateFlags makes all global flag values available in the +// context. This should be called as early as possible in app.Before. +// +// Example: +// +// geth account new --keystore /tmp/mykeystore --lightkdf +// +// is equivalent after calling this method with: +// +// geth --keystore /tmp/mykeystore --lightkdf account new +// +// i.e. in the subcommand Action function of 'account new', ctx.Bool("lightkdf) +// will return true even if --lightkdf is set as a global option. +// +// This function may become unnecessary when https://github.com/urfave/cli/pull/1245 is merged. +func MigrateFlags(action cli.ActionFunc) cli.ActionFunc { + return func(ctx *cli.Context) error { + doMigrateFlags(ctx) + return action(ctx) + } +} + +func doMigrateFlags(ctx *cli.Context) { + // Figure out if there are any aliases of commands. If there are, we want + // to ignore them when iterating over the flags. + var aliases = make(map[string]bool) + for _, fl := range ctx.Command.Flags { + for _, alias := range fl.Names()[1:] { + aliases[alias] = true + } + } + for _, name := range ctx.FlagNames() { + for _, parent := range ctx.Lineage()[1:] { + if parent.IsSet(name) { + // When iterating across the lineage, we will be served both + // the 'canon' and alias formats of all commands. In most cases, + // it's fine to set it in the ctx multiple times (one for each + // name), however, the Slice-flags are not fine. + // The slice-flags accumulate, so if we set it once as + // "foo" and once as alias "F", then both will be present in the slice. + if _, isAlias := aliases[name]; isAlias { + continue + } + // If it is a string-slice, we need to set it as + // "alfa, beta, gamma" instead of "[alfa beta gamma]", in order + // for the backing StringSlice to parse it properly. + if result := parent.StringSlice(name); len(result) > 0 { + ctx.Set(name, strings.Join(result, ",")) + } else { + ctx.Set(name, parent.String(name)) + } + break + } + } + } +} + func NewNodeConfig(ctx *cli.Context) *nodecfg.Config { nodeConfig := nodecfg.DefaultConfig // see simiar changes in `cmd/geth/config.go#defaultNodeConfig`