diff --git a/cmd/common.go b/cmd/common.go deleted file mode 100644 index 098bb6c7d..000000000 --- a/cmd/common.go +++ /dev/null @@ -1,120 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - "strings" - - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/viper" - data "github.com/tendermint/go-wire/data" - "github.com/tendermint/go-wire/data/base58" -) - -/******* - -TODO - -This file should move into go-common or the like as a basis for all cli tools. -It is here for experimentation of re-use between go-keys and light-client. - -*********/ - -const ( - RootFlag = "root" - OutputFlag = "output" - EncodingFlag = "encoding" -) - -func PrepareMainCmd(cmd *cobra.Command, envPrefix, defautRoot string) func() { - cobra.OnInitialize(func() { initEnv(envPrefix) }) - cmd.PersistentFlags().StringP(RootFlag, "r", defautRoot, "root directory for config and data") - cmd.PersistentFlags().StringP(EncodingFlag, "e", "hex", "Binary encoding (hex|b64|btc)") - cmd.PersistentFlags().StringP(OutputFlag, "o", "text", "Output format (text|json)") - cmd.PersistentPreRunE = multiE(bindFlags, setEncoding, validateOutput, cmd.PersistentPreRunE) - return func() { execute(cmd) } -} - -// initEnv sets to use ENV variables if set. -func initEnv(prefix string) { - // env variables with TM prefix (eg. TM_ROOT) - viper.SetEnvPrefix(prefix) - viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) - viper.AutomaticEnv() -} - -// execute adds all child commands to the root command sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. -func execute(cmd *cobra.Command) { - if err := cmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(-1) - } -} - -type wrapE func(cmd *cobra.Command, args []string) error - -func multiE(fs ...wrapE) wrapE { - return func(cmd *cobra.Command, args []string) error { - for _, f := range fs { - if f != nil { - if err := f(cmd, args); err != nil { - return err - } - } - } - return nil - } -} - -func bindFlags(cmd *cobra.Command, args []string) error { - // cmd.Flags() includes flags from this command and all persistent flags from the parent - if err := viper.BindPFlags(cmd.Flags()); err != nil { - return err - } - - // rootDir is command line flag, env variable, or default $HOME/.tlc - rootDir := viper.GetString("root") - viper.SetConfigName("config") // name of config file (without extension) - viper.AddConfigPath(rootDir) // search root directory - - // If a config file is found, read it in. - if err := viper.ReadInConfig(); err == nil { - // stderr, so if we redirect output to json file, this doesn't appear - // fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) - } else if _, ok := err.(viper.ConfigFileNotFoundError); !ok { - // we ignore not found error, only parse error - // stderr, so if we redirect output to json file, this doesn't appear - fmt.Fprintf(os.Stderr, "%#v", err) - } - return nil -} - -// setEncoding reads the encoding flag -func setEncoding(cmd *cobra.Command, args []string) error { - // validate and set encoding - enc := viper.GetString("encoding") - switch enc { - case "hex": - data.Encoder = data.HexEncoder - case "b64": - data.Encoder = data.B64Encoder - case "btc": - data.Encoder = base58.BTCEncoder - default: - return errors.Errorf("Unsupported encoding: %s", enc) - } - return nil -} - -func validateOutput(cmd *cobra.Command, args []string) error { - // validate output format - output := viper.GetString(OutputFlag) - switch output { - case "text", "json": - default: - return errors.Errorf("Unsupported output format: %s", output) - } - return nil -} diff --git a/cmd/get.go b/cmd/get.go index 9b8718996..6e8c620d0 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -15,7 +15,7 @@ package cmd import ( - "fmt" + "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -25,20 +25,17 @@ var getCmd = &cobra.Command{ Use: "get ", Short: "Get details of one key", Long: `Return public details of one local key.`, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { if len(args) != 1 || len(args[0]) == 0 { - fmt.Println("You must provide a name for the key") - return + return errors.New("You must provide a name for the key") } name := args[0] info, err := GetKeyManager().Get(name) - if err != nil { - fmt.Println(err.Error()) - return + if err == nil { + printInfo(info) } - - printInfo(info) + return err }, } diff --git a/cmd/keys/main.go b/cmd/keys/main.go index 0b0d93dec..82b355346 100644 --- a/cmd/keys/main.go +++ b/cmd/keys/main.go @@ -22,7 +22,6 @@ import ( ) func main() { - cli.PrepareMainCmd(cmd.RootCmd, "TM", os.ExpandEnv("$HOME/.tlc")) - cmd.RootCmd.Execute() - // exec() + root := cli.PrepareMainCmd(cmd.RootCmd, "TM", os.ExpandEnv("$HOME/.tlc")) + root.Execute() } diff --git a/cmd/list.go b/cmd/list.go index 875520159..b0419a1e4 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -14,11 +14,7 @@ package cmd -import ( - "fmt" - - "github.com/spf13/cobra" -) +import "github.com/spf13/cobra" // listCmd represents the list command var listCmd = &cobra.Command{ @@ -26,14 +22,12 @@ var listCmd = &cobra.Command{ Short: "List all keys", Long: `Return a list of all public keys stored by this key manager along with their associated name and address.`, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { infos, err := GetKeyManager().List() - if err != nil { - fmt.Println(err.Error()) - return + if err == nil { + printInfos(infos) } - - printInfos(infos) + return err }, } diff --git a/cmd/new.go b/cmd/new.go index b59874bb0..033410e6a 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -15,7 +15,7 @@ package cmd import ( - "fmt" + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -28,7 +28,7 @@ var newCmd = &cobra.Command{ Long: `Add a public/private key pair to the key store. The password muts be entered in the terminal and not passed as a command line argument for security.`, - Run: newPassword, + RunE: newPassword, } func init() { @@ -36,25 +36,21 @@ func init() { newCmd.Flags().StringP("type", "t", "ed25519", "Type of key (ed25519|secp256k1)") } -func newPassword(cmd *cobra.Command, args []string) { +func newPassword(cmd *cobra.Command, args []string) error { if len(args) != 1 || len(args[0]) == 0 { - fmt.Println("You must provide a name for the key") - return + return errors.New("You must provide a name for the key") } name := args[0] algo := viper.GetString("type") pass, err := getCheckPassword("Enter a passphrase:", "Repeat the passphrase:") if err != nil { - fmt.Println(err.Error()) - return + return err } info, err := GetKeyManager().Create(name, pass, algo) - if err != nil { - fmt.Println(err.Error()) - return + if err == nil { + printInfo(info) } - - printInfo(info) + return err } diff --git a/cmd/root.go b/cmd/root.go index 401e7ec38..33153d850 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -22,6 +22,7 @@ import ( keys "github.com/tendermint/go-crypto/keys" "github.com/tendermint/go-crypto/keys/cryptostore" "github.com/tendermint/go-crypto/keys/storage/filestorage" + "github.com/tendermint/tmlibs/cli" ) const KeySubdir = "keys" @@ -45,7 +46,7 @@ needs to sign with a private key.`, func GetKeyManager() keys.Manager { if manager == nil { // store the keys directory - rootDir := viper.GetString("root") + rootDir := viper.GetString(cli.HomeFlag) keyDir := filepath.Join(rootDir, KeySubdir) // and construct the key manager manager = cryptostore.New( diff --git a/cmd/update.go b/cmd/update.go index 3835242c5..c046af126 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -17,6 +17,8 @@ package cmd import ( "fmt" + "github.com/pkg/errors" + "github.com/spf13/cobra" ) @@ -25,35 +27,32 @@ var updateCmd = &cobra.Command{ Use: "update ", Short: "Change the password for a private key", Long: `Change the password for a private key.`, - Run: updatePassword, + RunE: updatePassword, } func init() { RootCmd.AddCommand(updateCmd) } -func updatePassword(cmd *cobra.Command, args []string) { +func updatePassword(cmd *cobra.Command, args []string) error { if len(args) != 1 || len(args[0]) == 0 { - fmt.Println("You must provide a name for the key") - return + return errors.New("You must provide a name for the key") } name := args[0] oldpass, err := getPassword("Enter the current passphrase:") if err != nil { - fmt.Println(err.Error()) - return + return err } newpass, err := getCheckPassword("Enter the new passphrase:", "Repeat the new passphrase:") if err != nil { - fmt.Println(err.Error()) - return + return err } err = GetKeyManager().Update(name, oldpass, newpass) if err != nil { - fmt.Println(err.Error()) - } else { - fmt.Println("Password successfully updated!") + return err } + fmt.Println("Password successfully updated!") + return nil } diff --git a/cmd/utils.go b/cmd/utils.go index a75262676..f2faa892b 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/viper" keys "github.com/tendermint/go-crypto/keys" data "github.com/tendermint/go-wire/data" + "github.com/tendermint/tmlibs/cli" ) const PassLength = 10 @@ -40,7 +41,7 @@ func getCheckPassword(prompt, prompt2 string) (string, error) { } func printInfo(info keys.Info) { - switch viper.Get(OutputFlag) { + switch viper.Get(cli.OutputFlag) { case "text": addr, err := data.ToText(info.Address) if err != nil { @@ -61,7 +62,7 @@ func printInfo(info keys.Info) { } func printInfos(infos keys.Infos) { - switch viper.Get(OutputFlag) { + switch viper.Get(cli.OutputFlag) { case "text": fmt.Println("All keys:") for _, i := range infos { diff --git a/glide.lock b/glide.lock index 485e75c76..7b3087993 100644 --- a/glide.lock +++ b/glide.lock @@ -1,10 +1,10 @@ hash: 3bcee9fbccf29d21217b24b6a83ec51e1514f37b2ae5d8718cf6c5df80f4fb2c -updated: 2017-04-21T16:09:28.762932633-04:00 +updated: 2017-05-05T19:07:08.418096598+02:00 imports: - name: github.com/bgentry/speakeasy version: 675b82c74c0ed12283ee81ba8a534c8982c07b85 - name: github.com/btcsuite/btcd - version: 583684b21bfbde9b5fc4403916fd7c807feb0289 + version: 4b348c1d33373d672edd83fc576892d0e46686d2 subpackages: - btcec - chaincfg @@ -28,7 +28,7 @@ imports: - name: github.com/go-playground/universal-translator version: b32fa301c9fe55953584134cb6853a13c87ec0a1 - name: github.com/go-stack/stack - version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 + version: 7a2f19628aabfe68f0766b59e74d6315f8347d22 - name: github.com/gorilla/context version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 - name: github.com/gorilla/handlers @@ -36,7 +36,7 @@ imports: - name: github.com/gorilla/mux version: 392c28fe23e1c45ddba891b0320b3b5df220beea - name: github.com/hashicorp/hcl - version: 630949a3c5fa3c613328e1b8256052cbc2327c9b + version: a4b07c25de5ff55ad3b8936cea69a79a3d95a855 subpackages: - hcl/ast - hcl/parser @@ -51,17 +51,17 @@ imports: - name: github.com/magiconair/properties version: 51463bfca2576e06c62a8504b5c0f06d61312647 - name: github.com/mattn/go-colorable - version: d228849504861217f796da67fae4f6e347643f15 + version: ded68f7a9561c023e790de24279db7ebf473ea80 - name: github.com/mattn/go-isatty - version: 30a891c33c7cde7b02a981314b4228ec99380cca + version: fc9e8d8ef48496124e79ae0df75490096eccf6fe - name: github.com/mitchellh/mapstructure - version: 53818660ed4955e899c0bcafa97299a388bd7c8e + version: cc8532a8e9a55ea36402aa21efdf403a60d34096 - name: github.com/pelletier/go-buffruneio version: c37440a7cf42ac63b919c752ca73a85067e05992 - name: github.com/pelletier/go-toml - version: 13d49d4606eb801b8f01ae542b4afc4c6ee3d84a + version: 97253b98df84f9eef872866d079e74b8265150f1 - name: github.com/pkg/errors - version: bfd5150e4e41705ded2129ec33379de1cb90b513 + version: c605e284fe17294bda444b34710735b29d1a9d90 - name: github.com/spf13/afero version: 9be650865eab0c12963d8753212f4f9c66cdcf12 subpackages: @@ -69,35 +69,34 @@ imports: - name: github.com/spf13/cast version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 - name: github.com/spf13/cobra - version: fcd0c5a1df88f5d6784cb4feead962c3f3d0b66c + version: 8f0203be891287870100e4af46262cdf4a4261d1 - name: github.com/spf13/jwalterweatherman version: fa7ca7e836cf3a8bb4ebf799f472c12d7e903d66 - name: github.com/spf13/pflag - version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7 + version: c990990ab4981d84da820b7b00c85139ca150b5f - name: github.com/spf13/viper - version: 5d46e70da8c0b6f812e0b170b7a985753b5c63cb + version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2 - name: github.com/tendermint/ed25519 version: 1f52c6f8b8a5c7908aff4497c186af344b428925 subpackages: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 334005c236d19c632fb5f073f9de3b0fab6a522b + version: b53add0b622662731985485f3a19be7f684660b8 subpackages: - data - data/base58 - name: github.com/tendermint/log15 - version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 + version: f91285dece9f4875421b481da3e613d83d44f29b subpackages: - term - name: github.com/tendermint/tmlibs - version: d4ab9679d71c8fc174284696d15930cb799fa24f + version: 706b9fbd671d5d49ecf1b2ea3bb34e51d61ff091 subpackages: - - common - - logger - cli + - common - name: golang.org/x/crypto - version: 7c6cc321c680f03b9ef0764448e780704f486b51 + version: 5a033cc77e57eca05bdb50522851d29e03569cbe subpackages: - bcrypt - blowfish @@ -109,11 +108,11 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/sys - version: d75a52659825e75fff6158388dddc6a5b04f9ba5 + version: 9ccfe848b9db8435a24c424abbc07a921adf1df5 subpackages: - unix - name: golang.org/x/text - version: f4b4367115ec2de254587813edaa901bc1c723a8 + version: 470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4 subpackages: - transform - unicode/norm