mirror of https://github.com/ethereum/go-ethereum
cmd: migrate to urfave/cli/v2 (#24751)
This change updates our urfave/cli dependency to the v2 branch of the library. There are some Go API changes in cli v2: - Flag values can now be accessed using the methods ctx.Bool, ctx.Int, ctx.String, ... regardless of whether the flag is 'local' or 'global'. - v2 has built-in support for flag categories. Our home-grown category system is removed and the categories of flags are assigned as part of the flag definition. For users, there is only one observable difference with cli v2: flags must now strictly appear before regular arguments. For example, the following command is now invalid: geth account import mykey.json --password file.txt Instead, the command must be invoked as follows: geth account import --password file.txt mykey.jsonpull/25185/head
parent
119f955686
commit
52ed3570c4
@ -0,0 +1,21 @@ |
||||
#! /bin/bash |
||||
|
||||
: ${PROG:=$(basename ${BASH_SOURCE})} |
||||
|
||||
_cli_bash_autocomplete() { |
||||
if [[ "${COMP_WORDS[0]}" != "source" ]]; then |
||||
local cur opts base |
||||
COMPREPLY=() |
||||
cur="${COMP_WORDS[COMP_CWORD]}" |
||||
if [[ "$cur" == "-"* ]]; then |
||||
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} ${cur} --generate-bash-completion ) |
||||
else |
||||
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion ) |
||||
fi |
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) |
||||
return 0 |
||||
fi |
||||
} |
||||
|
||||
complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete $PROG |
||||
unset PROG |
@ -0,0 +1,20 @@ |
||||
#compdef $PROG |
||||
|
||||
_cli_zsh_autocomplete() { |
||||
local -a opts |
||||
local cur |
||||
cur=${words[-1]} |
||||
if [[ "$cur" == "-"* ]]; then |
||||
opts=("${(@f)$(${words[@]:0:#words[@]-1} ${cur} --generate-bash-completion)}") |
||||
else |
||||
opts=("${(@f)$(${words[@]:0:#words[@]-1} --generate-bash-completion)}") |
||||
fi |
||||
|
||||
if [[ "${opts[1]}" != "" ]]; then |
||||
_describe 'values' opts |
||||
else |
||||
_files |
||||
fi |
||||
} |
||||
|
||||
compdef _cli_zsh_autocomplete $PROG |
@ -1,301 +0,0 @@ |
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Contains the geth command usage template and generator.
|
||||
|
||||
package main |
||||
|
||||
import ( |
||||
"io" |
||||
"sort" |
||||
|
||||
"github.com/ethereum/go-ethereum/cmd/utils" |
||||
"github.com/ethereum/go-ethereum/internal/debug" |
||||
"github.com/ethereum/go-ethereum/internal/flags" |
||||
"gopkg.in/urfave/cli.v1" |
||||
) |
||||
|
||||
// AppHelpFlagGroups is the application flags, grouped by functionality.
|
||||
var AppHelpFlagGroups = []flags.FlagGroup{ |
||||
{ |
||||
Name: "ETHEREUM", |
||||
Flags: utils.GroupFlags([]cli.Flag{ |
||||
configFileFlag, |
||||
utils.MinFreeDiskSpaceFlag, |
||||
utils.KeyStoreDirFlag, |
||||
utils.USBFlag, |
||||
utils.SmartCardDaemonPathFlag, |
||||
utils.NetworkIdFlag, |
||||
utils.SyncModeFlag, |
||||
utils.ExitWhenSyncedFlag, |
||||
utils.GCModeFlag, |
||||
utils.TxLookupLimitFlag, |
||||
utils.EthStatsURLFlag, |
||||
utils.IdentityFlag, |
||||
utils.LightKDFFlag, |
||||
utils.EthRequiredBlocksFlag, |
||||
}, utils.NetworkFlags, utils.DatabasePathFlags), |
||||
}, |
||||
{ |
||||
Name: "LIGHT CLIENT", |
||||
Flags: []cli.Flag{ |
||||
utils.LightServeFlag, |
||||
utils.LightIngressFlag, |
||||
utils.LightEgressFlag, |
||||
utils.LightMaxPeersFlag, |
||||
utils.UltraLightServersFlag, |
||||
utils.UltraLightFractionFlag, |
||||
utils.UltraLightOnlyAnnounceFlag, |
||||
utils.LightNoPruneFlag, |
||||
utils.LightNoSyncServeFlag, |
||||
}, |
||||
}, |
||||
{ |
||||
Name: "DEVELOPER CHAIN", |
||||
Flags: []cli.Flag{ |
||||
utils.DeveloperFlag, |
||||
utils.DeveloperPeriodFlag, |
||||
utils.DeveloperGasLimitFlag, |
||||
}, |
||||
}, |
||||
{ |
||||
Name: "ETHASH", |
||||
Flags: []cli.Flag{ |
||||
utils.EthashCacheDirFlag, |
||||
utils.EthashCachesInMemoryFlag, |
||||
utils.EthashCachesOnDiskFlag, |
||||
utils.EthashCachesLockMmapFlag, |
||||
utils.EthashDatasetDirFlag, |
||||
utils.EthashDatasetsInMemoryFlag, |
||||
utils.EthashDatasetsOnDiskFlag, |
||||
utils.EthashDatasetsLockMmapFlag, |
||||
}, |
||||
}, |
||||
{ |
||||
Name: "TRANSACTION POOL", |
||||
Flags: []cli.Flag{ |
||||
utils.TxPoolLocalsFlag, |
||||
utils.TxPoolNoLocalsFlag, |
||||
utils.TxPoolJournalFlag, |
||||
utils.TxPoolRejournalFlag, |
||||
utils.TxPoolPriceLimitFlag, |
||||
utils.TxPoolPriceBumpFlag, |
||||
utils.TxPoolAccountSlotsFlag, |
||||
utils.TxPoolGlobalSlotsFlag, |
||||
utils.TxPoolAccountQueueFlag, |
||||
utils.TxPoolGlobalQueueFlag, |
||||
utils.TxPoolLifetimeFlag, |
||||
}, |
||||
}, |
||||
{ |
||||
Name: "PERFORMANCE TUNING", |
||||
Flags: []cli.Flag{ |
||||
utils.CacheFlag, |
||||
utils.CacheDatabaseFlag, |
||||
utils.CacheTrieFlag, |
||||
utils.CacheTrieJournalFlag, |
||||
utils.CacheTrieRejournalFlag, |
||||
utils.CacheGCFlag, |
||||
utils.CacheSnapshotFlag, |
||||
utils.CacheNoPrefetchFlag, |
||||
utils.CachePreimagesFlag, |
||||
utils.FDLimitFlag, |
||||
}, |
||||
}, |
||||
{ |
||||
Name: "ACCOUNT", |
||||
Flags: []cli.Flag{ |
||||
utils.UnlockedAccountFlag, |
||||
utils.PasswordFileFlag, |
||||
utils.ExternalSignerFlag, |
||||
utils.InsecureUnlockAllowedFlag, |
||||
}, |
||||
}, |
||||
{ |
||||
Name: "API AND CONSOLE", |
||||
Flags: []cli.Flag{ |
||||
utils.IPCDisabledFlag, |
||||
utils.IPCPathFlag, |
||||
utils.HTTPEnabledFlag, |
||||
utils.HTTPListenAddrFlag, |
||||
utils.HTTPPortFlag, |
||||
utils.HTTPApiFlag, |
||||
utils.HTTPPathPrefixFlag, |
||||
utils.HTTPCORSDomainFlag, |
||||
utils.HTTPVirtualHostsFlag, |
||||
utils.WSEnabledFlag, |
||||
utils.WSListenAddrFlag, |
||||
utils.WSPortFlag, |
||||
utils.WSApiFlag, |
||||
utils.WSPathPrefixFlag, |
||||
utils.WSAllowedOriginsFlag, |
||||
utils.JWTSecretFlag, |
||||
utils.AuthListenFlag, |
||||
utils.AuthPortFlag, |
||||
utils.AuthVirtualHostsFlag, |
||||
utils.GraphQLEnabledFlag, |
||||
utils.GraphQLCORSDomainFlag, |
||||
utils.GraphQLVirtualHostsFlag, |
||||
utils.RPCGlobalGasCapFlag, |
||||
utils.RPCGlobalEVMTimeoutFlag, |
||||
utils.RPCGlobalTxFeeCapFlag, |
||||
utils.AllowUnprotectedTxs, |
||||
utils.JSpathFlag, |
||||
utils.ExecFlag, |
||||
utils.PreloadJSFlag, |
||||
}, |
||||
}, |
||||
{ |
||||
Name: "NETWORKING", |
||||
Flags: []cli.Flag{ |
||||
utils.BootnodesFlag, |
||||
utils.DNSDiscoveryFlag, |
||||
utils.ListenPortFlag, |
||||
utils.MaxPeersFlag, |
||||
utils.MaxPendingPeersFlag, |
||||
utils.NATFlag, |
||||
utils.NoDiscoverFlag, |
||||
utils.DiscoveryV5Flag, |
||||
utils.NetrestrictFlag, |
||||
utils.NodeKeyFileFlag, |
||||
utils.NodeKeyHexFlag, |
||||
}, |
||||
}, |
||||
{ |
||||
Name: "MINER", |
||||
Flags: []cli.Flag{ |
||||
utils.MiningEnabledFlag, |
||||
utils.MinerThreadsFlag, |
||||
utils.MinerNotifyFlag, |
||||
utils.MinerNotifyFullFlag, |
||||
utils.MinerGasPriceFlag, |
||||
utils.MinerGasLimitFlag, |
||||
utils.MinerEtherbaseFlag, |
||||
utils.MinerExtraDataFlag, |
||||
utils.MinerRecommitIntervalFlag, |
||||
utils.MinerNoVerifyFlag, |
||||
}, |
||||
}, |
||||
{ |
||||
Name: "GAS PRICE ORACLE", |
||||
Flags: []cli.Flag{ |
||||
utils.GpoBlocksFlag, |
||||
utils.GpoPercentileFlag, |
||||
utils.GpoMaxGasPriceFlag, |
||||
utils.GpoIgnoreGasPriceFlag, |
||||
}, |
||||
}, |
||||
{ |
||||
Name: "VIRTUAL MACHINE", |
||||
Flags: []cli.Flag{ |
||||
utils.VMEnableDebugFlag, |
||||
}, |
||||
}, |
||||
{ |
||||
Name: "LOGGING AND DEBUGGING", |
||||
Flags: append([]cli.Flag{ |
||||
utils.FakePoWFlag, |
||||
utils.NoCompactionFlag, |
||||
}, debug.Flags...), |
||||
}, |
||||
{ |
||||
Name: "METRICS AND STATS", |
||||
Flags: metricsFlags, |
||||
}, |
||||
{ |
||||
Name: "ALIASED (deprecated)", |
||||
Flags: []cli.Flag{ |
||||
utils.NoUSBFlag, |
||||
utils.LegacyWhitelistFlag, |
||||
}, |
||||
}, |
||||
{ |
||||
Name: "MISC", |
||||
Flags: []cli.Flag{ |
||||
utils.SnapshotFlag, |
||||
utils.BloomFilterSizeFlag, |
||||
utils.IgnoreLegacyReceiptsFlag, |
||||
cli.HelpFlag, |
||||
}, |
||||
}, |
||||
} |
||||
|
||||
func init() { |
||||
// Override the default app help template
|
||||
cli.AppHelpTemplate = flags.AppHelpTemplate |
||||
|
||||
// Override the default app help printer, but only for the global app help
|
||||
originalHelpPrinter := cli.HelpPrinter |
||||
cli.HelpPrinter = func(w io.Writer, tmpl string, data interface{}) { |
||||
if tmpl == flags.AppHelpTemplate { |
||||
// Iterate over all the flags and add any uncategorized ones
|
||||
categorized := make(map[string]struct{}) |
||||
for _, group := range AppHelpFlagGroups { |
||||
for _, flag := range group.Flags { |
||||
categorized[flag.String()] = struct{}{} |
||||
} |
||||
} |
||||
deprecated := make(map[string]struct{}) |
||||
for _, flag := range utils.DeprecatedFlags { |
||||
deprecated[flag.String()] = struct{}{} |
||||
} |
||||
// Only add uncategorized flags if they are not deprecated
|
||||
var uncategorized []cli.Flag |
||||
for _, flag := range data.(*cli.App).Flags { |
||||
if _, ok := categorized[flag.String()]; !ok { |
||||
if _, ok := deprecated[flag.String()]; !ok { |
||||
uncategorized = append(uncategorized, flag) |
||||
} |
||||
} |
||||
} |
||||
if len(uncategorized) > 0 { |
||||
// Append all ungategorized options to the misc group
|
||||
miscs := len(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags) |
||||
AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = append(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags, uncategorized...) |
||||
|
||||
// Make sure they are removed afterwards
|
||||
defer func() { |
||||
AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags[:miscs] |
||||
}() |
||||
} |
||||
// Render out custom usage screen
|
||||
originalHelpPrinter(w, tmpl, flags.HelpData{App: data, FlagGroups: AppHelpFlagGroups}) |
||||
} else if tmpl == flags.CommandHelpTemplate { |
||||
// Iterate over all command specific flags and categorize them
|
||||
categorized := make(map[string][]cli.Flag) |
||||
for _, flag := range data.(cli.Command).Flags { |
||||
if _, ok := categorized[flag.String()]; !ok { |
||||
categorized[flags.FlagCategory(flag, AppHelpFlagGroups)] = append(categorized[flags.FlagCategory(flag, AppHelpFlagGroups)], flag) |
||||
} |
||||
} |
||||
|
||||
// sort to get a stable ordering
|
||||
sorted := make([]flags.FlagGroup, 0, len(categorized)) |
||||
for cat, flgs := range categorized { |
||||
sorted = append(sorted, flags.FlagGroup{Name: cat, Flags: flgs}) |
||||
} |
||||
sort.Sort(flags.ByCategory(sorted)) |
||||
|
||||
// add sorted array to data and render with default printer
|
||||
originalHelpPrinter(w, tmpl, map[string]interface{}{ |
||||
"cmd": data, |
||||
"categorizedFlags": sorted, |
||||
}) |
||||
} else { |
||||
originalHelpPrinter(w, tmpl, data) |
||||
} |
||||
} |
||||
} |
@ -1,211 +0,0 @@ |
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package utils |
||||
|
||||
import ( |
||||
"encoding" |
||||
"errors" |
||||
"flag" |
||||
"math/big" |
||||
"os" |
||||
"os/user" |
||||
"path" |
||||
"strings" |
||||
|
||||
"github.com/ethereum/go-ethereum/common/math" |
||||
"gopkg.in/urfave/cli.v1" |
||||
) |
||||
|
||||
// Custom type which is registered in the flags library which cli uses for
|
||||
// argument parsing. This allows us to expand Value to an absolute path when
|
||||
// the argument is parsed
|
||||
type DirectoryString string |
||||
|
||||
func (s *DirectoryString) String() string { |
||||
return string(*s) |
||||
} |
||||
|
||||
func (s *DirectoryString) Set(value string) error { |
||||
*s = DirectoryString(expandPath(value)) |
||||
return nil |
||||
} |
||||
|
||||
// Custom cli.Flag type which expand the received string to an absolute path.
|
||||
// e.g. ~/.ethereum -> /home/username/.ethereum
|
||||
type DirectoryFlag struct { |
||||
Name string |
||||
Value DirectoryString |
||||
Usage string |
||||
EnvVar string |
||||
} |
||||
|
||||
func (f DirectoryFlag) String() string { |
||||
return cli.FlagStringer(f) |
||||
} |
||||
|
||||
// called by cli library, grabs variable from environment (if in env)
|
||||
// and adds variable to flag set for parsing.
|
||||
func (f DirectoryFlag) Apply(set *flag.FlagSet) { |
||||
eachName(f.Name, func(name string) { |
||||
set.Var(&f.Value, f.Name, f.Usage) |
||||
}) |
||||
} |
||||
|
||||
func (f DirectoryFlag) GetName() string { |
||||
return f.Name |
||||
} |
||||
|
||||
func (f *DirectoryFlag) Set(value string) { |
||||
f.Value.Set(value) |
||||
} |
||||
|
||||
func eachName(longName string, fn func(string)) { |
||||
parts := strings.Split(longName, ",") |
||||
for _, name := range parts { |
||||
name = strings.Trim(name, " ") |
||||
fn(name) |
||||
} |
||||
} |
||||
|
||||
type TextMarshaler interface { |
||||
encoding.TextMarshaler |
||||
encoding.TextUnmarshaler |
||||
} |
||||
|
||||
// textMarshalerVal turns a TextMarshaler into a flag.Value
|
||||
type textMarshalerVal struct { |
||||
v TextMarshaler |
||||
} |
||||
|
||||
func (v textMarshalerVal) String() string { |
||||
if v.v == nil { |
||||
return "" |
||||
} |
||||
text, _ := v.v.MarshalText() |
||||
return string(text) |
||||
} |
||||
|
||||
func (v textMarshalerVal) Set(s string) error { |
||||
return v.v.UnmarshalText([]byte(s)) |
||||
} |
||||
|
||||
// TextMarshalerFlag wraps a TextMarshaler value.
|
||||
type TextMarshalerFlag struct { |
||||
Name string |
||||
Value TextMarshaler |
||||
Usage string |
||||
EnvVar string |
||||
} |
||||
|
||||
func (f TextMarshalerFlag) GetName() string { |
||||
return f.Name |
||||
} |
||||
|
||||
func (f TextMarshalerFlag) String() string { |
||||
return cli.FlagStringer(f) |
||||
} |
||||
|
||||
func (f TextMarshalerFlag) Apply(set *flag.FlagSet) { |
||||
eachName(f.Name, func(name string) { |
||||
set.Var(textMarshalerVal{f.Value}, f.Name, f.Usage) |
||||
}) |
||||
} |
||||
|
||||
// GlobalTextMarshaler returns the value of a TextMarshalerFlag from the global flag set.
|
||||
func GlobalTextMarshaler(ctx *cli.Context, name string) TextMarshaler { |
||||
val := ctx.GlobalGeneric(name) |
||||
if val == nil { |
||||
return nil |
||||
} |
||||
return val.(textMarshalerVal).v |
||||
} |
||||
|
||||
// BigFlag is a command line flag that accepts 256 bit big integers in decimal or
|
||||
// hexadecimal syntax.
|
||||
type BigFlag struct { |
||||
Name string |
||||
Value *big.Int |
||||
Usage string |
||||
EnvVar string |
||||
} |
||||
|
||||
// bigValue turns *big.Int into a flag.Value
|
||||
type bigValue big.Int |
||||
|
||||
func (b *bigValue) String() string { |
||||
if b == nil { |
||||
return "" |
||||
} |
||||
return (*big.Int)(b).String() |
||||
} |
||||
|
||||
func (b *bigValue) Set(s string) error { |
||||
intVal, ok := math.ParseBig256(s) |
||||
if !ok { |
||||
return errors.New("invalid integer syntax") |
||||
} |
||||
*b = (bigValue)(*intVal) |
||||
return nil |
||||
} |
||||
|
||||
func (f BigFlag) GetName() string { |
||||
return f.Name |
||||
} |
||||
|
||||
func (f BigFlag) String() string { |
||||
return cli.FlagStringer(f) |
||||
} |
||||
|
||||
func (f BigFlag) Apply(set *flag.FlagSet) { |
||||
eachName(f.Name, func(name string) { |
||||
f.Value = new(big.Int) |
||||
set.Var((*bigValue)(f.Value), f.Name, f.Usage) |
||||
}) |
||||
} |
||||
|
||||
// GlobalBig returns the value of a BigFlag from the global flag set.
|
||||
func GlobalBig(ctx *cli.Context, name string) *big.Int { |
||||
val := ctx.GlobalGeneric(name) |
||||
if val == nil { |
||||
return nil |
||||
} |
||||
return (*big.Int)(val.(*bigValue)) |
||||
} |
||||
|
||||
// Expands a file path
|
||||
// 1. replace tilde with users home dir
|
||||
// 2. expands embedded environment variables
|
||||
// 3. cleans the path, e.g. /a/b/../c -> /a/c
|
||||
// Note, it has limitations, e.g. ~someuser/tmp will not be expanded
|
||||
func expandPath(p string) string { |
||||
if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") { |
||||
if home := HomeDir(); home != "" { |
||||
p = home + p[1:] |
||||
} |
||||
} |
||||
return path.Clean(os.ExpandEnv(p)) |
||||
} |
||||
|
||||
func HomeDir() string { |
||||
if home := os.Getenv("HOME"); home != "" { |
||||
return home |
||||
} |
||||
if usr, err := user.Current(); err == nil { |
||||
return usr.HomeDir |
||||
} |
||||
return "" |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,43 @@ |
||||
// Copyright 2022 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package flags |
||||
|
||||
import "github.com/urfave/cli/v2" |
||||
|
||||
const ( |
||||
EthCategory = "ETHEREUM" |
||||
LightCategory = "LIGHT CLIENT" |
||||
DevCategory = "DEVELOPER CHAIN" |
||||
EthashCategory = "ETHASH" |
||||
TxPoolCategory = "TRANSACTION POOL" |
||||
PerfCategory = "PERFORMANCE TUNING" |
||||
AccountCategory = "ACCOUNT" |
||||
APICategory = "API AND CONSOLE" |
||||
NetworkingCategory = "NETWORKING" |
||||
MinerCategory = "MINER" |
||||
GasPriceCategory = "GAS PRICE ORACLE" |
||||
VMCategory = "VIRTUAL MACHINE" |
||||
LoggingCategory = "LOGGING AND DEBUGGING" |
||||
MetricsCategory = "METRICS AND STATS" |
||||
MiscCategory = "MISC" |
||||
DeprecatedCategory = "ALIASED (deprecated)" |
||||
) |
||||
|
||||
func init() { |
||||
cli.HelpFlag.(*cli.BoolFlag).Category = MiscCategory |
||||
cli.VersionFlag.(*cli.BoolFlag).Category = MiscCategory |
||||
} |
@ -0,0 +1,340 @@ |
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package flags |
||||
|
||||
import ( |
||||
"encoding" |
||||
"errors" |
||||
"flag" |
||||
"math/big" |
||||
"os" |
||||
"os/user" |
||||
"path" |
||||
"strings" |
||||
|
||||
"github.com/ethereum/go-ethereum/common/math" |
||||
"github.com/urfave/cli/v2" |
||||
) |
||||
|
||||
// DirectoryString is custom type which is registered in the flags library which cli uses for
|
||||
// argument parsing. This allows us to expand Value to an absolute path when
|
||||
// the argument is parsed
|
||||
type DirectoryString string |
||||
|
||||
func (s *DirectoryString) String() string { |
||||
return string(*s) |
||||
} |
||||
|
||||
func (s *DirectoryString) Set(value string) error { |
||||
*s = DirectoryString(expandPath(value)) |
||||
return nil |
||||
} |
||||
|
||||
var ( |
||||
_ cli.Flag = (*DirectoryFlag)(nil) |
||||
_ cli.RequiredFlag = (*DirectoryFlag)(nil) |
||||
_ cli.VisibleFlag = (*DirectoryFlag)(nil) |
||||
_ cli.DocGenerationFlag = (*DirectoryFlag)(nil) |
||||
_ cli.CategorizableFlag = (*DirectoryFlag)(nil) |
||||
) |
||||
|
||||
// DirectoryFlag is custom cli.Flag type which expand the received string to an absolute path.
|
||||
// e.g. ~/.ethereum -> /home/username/.ethereum
|
||||
type DirectoryFlag struct { |
||||
Name string |
||||
|
||||
Category string |
||||
DefaultText string |
||||
Usage string |
||||
|
||||
Required bool |
||||
Hidden bool |
||||
HasBeenSet bool |
||||
|
||||
Value DirectoryString |
||||
|
||||
Aliases []string |
||||
} |
||||
|
||||
// For cli.Flag:
|
||||
|
||||
func (f *DirectoryFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) } |
||||
func (f *DirectoryFlag) IsSet() bool { return f.HasBeenSet } |
||||
func (f *DirectoryFlag) String() string { return cli.FlagStringer(f) } |
||||
|
||||
// Apply called by cli library, grabs variable from environment (if in env)
|
||||
// and adds variable to flag set for parsing.
|
||||
func (f *DirectoryFlag) Apply(set *flag.FlagSet) error { |
||||
eachName(f, func(name string) { |
||||
set.Var(&f.Value, f.Name, f.Usage) |
||||
}) |
||||
return nil |
||||
} |
||||
|
||||
// For cli.RequiredFlag:
|
||||
|
||||
func (f *DirectoryFlag) IsRequired() bool { return f.Required } |
||||
|
||||
// For cli.VisibleFlag:
|
||||
|
||||
func (f *DirectoryFlag) IsVisible() bool { return !f.Hidden } |
||||
|
||||
// For cli.CategorizableFlag:
|
||||
|
||||
func (f *DirectoryFlag) GetCategory() string { return f.Category } |
||||
|
||||
// For cli.DocGenerationFlag:
|
||||
|
||||
func (f *DirectoryFlag) TakesValue() bool { return true } |
||||
func (f *DirectoryFlag) GetUsage() string { return f.Usage } |
||||
func (f *DirectoryFlag) GetValue() string { return f.Value.String() } |
||||
func (f *DirectoryFlag) GetEnvVars() []string { return nil } // env not supported
|
||||
|
||||
func (f *DirectoryFlag) GetDefaultText() string { |
||||
if f.DefaultText != "" { |
||||
return f.DefaultText |
||||
} |
||||
return f.GetValue() |
||||
} |
||||
|
||||
type TextMarshaler interface { |
||||
encoding.TextMarshaler |
||||
encoding.TextUnmarshaler |
||||
} |
||||
|
||||
// textMarshalerVal turns a TextMarshaler into a flag.Value
|
||||
type textMarshalerVal struct { |
||||
v TextMarshaler |
||||
} |
||||
|
||||
func (v textMarshalerVal) String() string { |
||||
if v.v == nil { |
||||
return "" |
||||
} |
||||
text, _ := v.v.MarshalText() |
||||
return string(text) |
||||
} |
||||
|
||||
func (v textMarshalerVal) Set(s string) error { |
||||
return v.v.UnmarshalText([]byte(s)) |
||||
} |
||||
|
||||
var ( |
||||
_ cli.Flag = (*TextMarshalerFlag)(nil) |
||||
_ cli.RequiredFlag = (*TextMarshalerFlag)(nil) |
||||
_ cli.VisibleFlag = (*TextMarshalerFlag)(nil) |
||||
_ cli.DocGenerationFlag = (*TextMarshalerFlag)(nil) |
||||
_ cli.CategorizableFlag = (*TextMarshalerFlag)(nil) |
||||
) |
||||
|
||||
// TextMarshalerFlag wraps a TextMarshaler value.
|
||||
type TextMarshalerFlag struct { |
||||
Name string |
||||
|
||||
Category string |
||||
DefaultText string |
||||
Usage string |
||||
|
||||
Required bool |
||||
Hidden bool |
||||
HasBeenSet bool |
||||
|
||||
Value TextMarshaler |
||||
|
||||
Aliases []string |
||||
} |
||||
|
||||
// For cli.Flag:
|
||||
|
||||
func (f *TextMarshalerFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) } |
||||
func (f *TextMarshalerFlag) IsSet() bool { return f.HasBeenSet } |
||||
func (f *TextMarshalerFlag) String() string { return cli.FlagStringer(f) } |
||||
|
||||
func (f *TextMarshalerFlag) Apply(set *flag.FlagSet) error { |
||||
eachName(f, func(name string) { |
||||
set.Var(textMarshalerVal{f.Value}, f.Name, f.Usage) |
||||
}) |
||||
return nil |
||||
} |
||||
|
||||
// For cli.RequiredFlag:
|
||||
|
||||
func (f *TextMarshalerFlag) IsRequired() bool { return f.Required } |
||||
|
||||
// For cli.VisibleFlag:
|
||||
|
||||
func (f *TextMarshalerFlag) IsVisible() bool { return !f.Hidden } |
||||
|
||||
// For cli.CategorizableFlag:
|
||||
|
||||
func (f *TextMarshalerFlag) GetCategory() string { return f.Category } |
||||
|
||||
// For cli.DocGenerationFlag:
|
||||
|
||||
func (f *TextMarshalerFlag) TakesValue() bool { return true } |
||||
func (f *TextMarshalerFlag) GetUsage() string { return f.Usage } |
||||
func (f *TextMarshalerFlag) GetEnvVars() []string { return nil } // env not supported
|
||||
|
||||
func (f *TextMarshalerFlag) GetValue() string { |
||||
t, err := f.Value.MarshalText() |
||||
if err != nil { |
||||
return "(ERR: " + err.Error() + ")" |
||||
} |
||||
return string(t) |
||||
} |
||||
|
||||
func (f *TextMarshalerFlag) GetDefaultText() string { |
||||
if f.DefaultText != "" { |
||||
return f.DefaultText |
||||
} |
||||
return f.GetValue() |
||||
} |
||||
|
||||
// GlobalTextMarshaler returns the value of a TextMarshalerFlag from the global flag set.
|
||||
func GlobalTextMarshaler(ctx *cli.Context, name string) TextMarshaler { |
||||
val := ctx.Generic(name) |
||||
if val == nil { |
||||
return nil |
||||
} |
||||
return val.(textMarshalerVal).v |
||||
} |
||||
|
||||
var ( |
||||
_ cli.Flag = (*BigFlag)(nil) |
||||
_ cli.RequiredFlag = (*BigFlag)(nil) |
||||
_ cli.VisibleFlag = (*BigFlag)(nil) |
||||
_ cli.DocGenerationFlag = (*BigFlag)(nil) |
||||
_ cli.CategorizableFlag = (*BigFlag)(nil) |
||||
) |
||||
|
||||
// BigFlag is a command line flag that accepts 256 bit big integers in decimal or
|
||||
// hexadecimal syntax.
|
||||
type BigFlag struct { |
||||
Name string |
||||
|
||||
Category string |
||||
DefaultText string |
||||
Usage string |
||||
|
||||
Required bool |
||||
Hidden bool |
||||
HasBeenSet bool |
||||
|
||||
Value *big.Int |
||||
|
||||
Aliases []string |
||||
} |
||||
|
||||
// For cli.Flag:
|
||||
|
||||
func (f *BigFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) } |
||||
func (f *BigFlag) IsSet() bool { return f.HasBeenSet } |
||||
func (f *BigFlag) String() string { return cli.FlagStringer(f) } |
||||
|
||||
func (f *BigFlag) Apply(set *flag.FlagSet) error { |
||||
eachName(f, func(name string) { |
||||
f.Value = new(big.Int) |
||||
set.Var((*bigValue)(f.Value), f.Name, f.Usage) |
||||
}) |
||||
|
||||
return nil |
||||
} |
||||
|
||||
// For cli.RequiredFlag:
|
||||
|
||||
func (f *BigFlag) IsRequired() bool { return f.Required } |
||||
|
||||
// For cli.VisibleFlag:
|
||||
|
||||
func (f *BigFlag) IsVisible() bool { return !f.Hidden } |
||||
|
||||
// For cli.CategorizableFlag:
|
||||
|
||||
func (f *BigFlag) GetCategory() string { return f.Category } |
||||
|
||||
// For cli.DocGenerationFlag:
|
||||
|
||||
func (f *BigFlag) TakesValue() bool { return true } |
||||
func (f *BigFlag) GetUsage() string { return f.Usage } |
||||
func (f *BigFlag) GetValue() string { return f.Value.String() } |
||||
func (f *BigFlag) GetEnvVars() []string { return nil } // env not supported
|
||||
|
||||
func (f *BigFlag) GetDefaultText() string { |
||||
if f.DefaultText != "" { |
||||
return f.DefaultText |
||||
} |
||||
return f.GetValue() |
||||
} |
||||
|
||||
// bigValue turns *big.Int into a flag.Value
|
||||
type bigValue big.Int |
||||
|
||||
func (b *bigValue) String() string { |
||||
if b == nil { |
||||
return "" |
||||
} |
||||
return (*big.Int)(b).String() |
||||
} |
||||
|
||||
func (b *bigValue) Set(s string) error { |
||||
intVal, ok := math.ParseBig256(s) |
||||
if !ok { |
||||
return errors.New("invalid integer syntax") |
||||
} |
||||
*b = (bigValue)(*intVal) |
||||
return nil |
||||
} |
||||
|
||||
// GlobalBig returns the value of a BigFlag from the global flag set.
|
||||
func GlobalBig(ctx *cli.Context, name string) *big.Int { |
||||
val := ctx.Generic(name) |
||||
if val == nil { |
||||
return nil |
||||
} |
||||
return (*big.Int)(val.(*bigValue)) |
||||
} |
||||
|
||||
// Expands a file path
|
||||
// 1. replace tilde with users home dir
|
||||
// 2. expands embedded environment variables
|
||||
// 3. cleans the path, e.g. /a/b/../c -> /a/c
|
||||
// Note, it has limitations, e.g. ~someuser/tmp will not be expanded
|
||||
func expandPath(p string) string { |
||||
if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") { |
||||
if home := HomeDir(); home != "" { |
||||
p = home + p[1:] |
||||
} |
||||
} |
||||
return path.Clean(os.ExpandEnv(p)) |
||||
} |
||||
|
||||
func HomeDir() string { |
||||
if home := os.Getenv("HOME"); home != "" { |
||||
return home |
||||
} |
||||
if usr, err := user.Current(); err == nil { |
||||
return usr.HomeDir |
||||
} |
||||
return "" |
||||
} |
||||
|
||||
func eachName(f cli.Flag, fn func(string)) { |
||||
for _, name := range f.Names() { |
||||
name = strings.Trim(name, " ") |
||||
fn(name) |
||||
} |
||||
} |
@ -1,20 +1,20 @@ |
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package utils |
||||
package flags |
||||
|
||||
import ( |
||||
"os" |
Loading…
Reference in new issue