From de3880c95678896da00f6b4a8cfc4d484c6bd6e9 Mon Sep 17 00:00:00 2001 From: Mikhail Grachev Date: Thu, 18 Apr 2019 14:07:05 +0300 Subject: [PATCH] Use os.UserHomeDir() for Go version 1.12+ --- README.md | 3 +- cobra/cmd/init_go1.10_test.go | 51 ++++++ .../cmd/{init_test.go => init_go1.12_test.go} | 11 +- cobra/cmd/root.go | 2 + cobra/cmd/root_go1.12.go | 82 ++++++++++ .../{root.go.golden => root.go1.10.golden} | 2 - cobra/cmd/testdata/root.go1.12.golden | 94 +++++++++++ cobra/tpl/go1.12.go | 154 ++++++++++++++++++ cobra/tpl/main.go | 6 +- 9 files changed, 398 insertions(+), 7 deletions(-) create mode 100644 cobra/cmd/init_go1.10_test.go rename cobra/cmd/{init_test.go => init_go1.12_test.go} (71%) create mode 100644 cobra/cmd/root_go1.12.go rename cobra/cmd/testdata/{root.go.golden => root.go1.10.golden} (99%) create mode 100644 cobra/cmd/testdata/root.go1.12.golden create mode 100644 cobra/tpl/go1.12.go diff --git a/README.md b/README.md index 60c5a425b..c56f37b39 100644 --- a/README.md +++ b/README.md @@ -212,7 +212,6 @@ import ( "fmt" "os" - homedir "github.com/mitchellh/go-homedir" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -238,7 +237,7 @@ func initConfig() { viper.SetConfigFile(cfgFile) } else { // Find home directory. - home, err := homedir.Dir() + home, err := os.UserHomeDir() if err != nil { fmt.Println(err) os.Exit(1) diff --git a/cobra/cmd/init_go1.10_test.go b/cobra/cmd/init_go1.10_test.go new file mode 100644 index 000000000..2f3262eb4 --- /dev/null +++ b/cobra/cmd/init_go1.10_test.go @@ -0,0 +1,51 @@ +// +build !go1.12 + +package cmd + +import ( + "fmt" + "os" + "path/filepath" + "testing" +) + +func TestGoldenInitCmd(t *testing.T) { + + wd, _ := os.Getwd() + project := &Project{ + AbsolutePath: fmt.Sprintf("%s/testproject", wd), + PkgName: "github.com/spf13/testproject", + Legal: getLicense(), + Copyright: copyrightLine(), + Viper: true, + AppName: "testproject", + } + + err := project.Create() + if err != nil { + t.Fatal(err) + } + + defer func() { + if _, err := os.Stat(project.AbsolutePath); err == nil { + os.RemoveAll(project.AbsolutePath) + } + }() + + expectedFiles := []string{"LICENSE", "main.go"} + for _, f := range expectedFiles { + generatedFile := fmt.Sprintf("%s/%s", project.AbsolutePath, f) + goldenFile := fmt.Sprintf("testdata/%s.golden", filepath.Base(f)) + err := compareFiles(generatedFile, goldenFile) + if err != nil { + t.Fatal(err) + } + } + + rootCmd := "cmd/root.go" + generatedFile := fmt.Sprintf("%s/%s", project.AbsolutePath, rootCmd) + goldenFile := fmt.Sprintf("testdata/%s1.10.golden", filepath.Base(rootCmd)) + if err = compareFiles(generatedFile, goldenFile); err != nil { + t.Fatal(err) + } +} diff --git a/cobra/cmd/init_test.go b/cobra/cmd/init_go1.12_test.go similarity index 71% rename from cobra/cmd/init_test.go rename to cobra/cmd/init_go1.12_test.go index 9540b2d30..84a4c4c8c 100644 --- a/cobra/cmd/init_test.go +++ b/cobra/cmd/init_go1.12_test.go @@ -1,3 +1,5 @@ +// +build go1.12 + package cmd import ( @@ -30,7 +32,7 @@ func TestGoldenInitCmd(t *testing.T) { } }() - expectedFiles := []string{"LICENSE", "main.go", "cmd/root.go"} + expectedFiles := []string{"LICENSE", "main.go"} for _, f := range expectedFiles { generatedFile := fmt.Sprintf("%s/%s", project.AbsolutePath, f) goldenFile := fmt.Sprintf("testdata/%s.golden", filepath.Base(f)) @@ -39,4 +41,11 @@ func TestGoldenInitCmd(t *testing.T) { t.Fatal(err) } } + + rootCmd := "cmd/root.go" + generatedFile := fmt.Sprintf("%s/%s", project.AbsolutePath, rootCmd) + goldenFile := fmt.Sprintf("testdata/%s1.12.golden", filepath.Base(rootCmd)) + if err = compareFiles(generatedFile, goldenFile); err != nil { + t.Fatal(err) + } } diff --git a/cobra/cmd/root.go b/cobra/cmd/root.go index 624c717c1..b206d528d 100644 --- a/cobra/cmd/root.go +++ b/cobra/cmd/root.go @@ -1,3 +1,5 @@ +// +build !go1.12 + // Copyright © 2015 Steve Francia . // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/cobra/cmd/root_go1.12.go b/cobra/cmd/root_go1.12.go new file mode 100644 index 000000000..54b838319 --- /dev/null +++ b/cobra/cmd/root_go1.12.go @@ -0,0 +1,82 @@ +// +build go1.12 + +// Copyright © 2015 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ( + // Used for flags. + cfgFile string + userLicense string + + rootCmd = &cobra.Command{ + Use: "cobra", + Short: "A generator for Cobra based Applications", + Long: `Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.`, + } +) + +// Execute executes the root command. +func Execute() { + rootCmd.Execute() +} + +func init() { + cobra.OnInitialize(initConfig) + + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") + rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution") + rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project") + rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration") + viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) + viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper")) + viper.SetDefault("author", "NAME HERE ") + viper.SetDefault("license", "apache") + + rootCmd.AddCommand(addCmd) + rootCmd.AddCommand(initCmd) +} + +func initConfig() { + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := os.UserHomeDir() + if err != nil { + er(err) + } + + // Search config in home directory with name ".cobra" (without extension). + viper.AddConfigPath(home) + viper.SetConfigName(".cobra") + } + + viper.AutomaticEnv() + + if err := viper.ReadInConfig(); err == nil { + fmt.Println("Using config file:", viper.ConfigFileUsed()) + } +} diff --git a/cobra/cmd/testdata/root.go.golden b/cobra/cmd/testdata/root.go1.10.golden similarity index 99% rename from cobra/cmd/testdata/root.go.golden rename to cobra/cmd/testdata/root.go1.10.golden index d3b889baa..f05ee2236 100644 --- a/cobra/cmd/testdata/root.go.golden +++ b/cobra/cmd/testdata/root.go1.10.golden @@ -19,10 +19,8 @@ import ( "fmt" "os" "github.com/spf13/cobra" - homedir "github.com/mitchellh/go-homedir" "github.com/spf13/viper" - ) diff --git a/cobra/cmd/testdata/root.go1.12.golden b/cobra/cmd/testdata/root.go1.12.golden new file mode 100644 index 000000000..4ae1ffd57 --- /dev/null +++ b/cobra/cmd/testdata/root.go1.12.golden @@ -0,0 +1,94 @@ +/* +Copyright © 2019 NAME HERE + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package cmd + +import ( + "fmt" + "os" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + + +var cfgFile string + + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "testproject", + Short: "A brief description of your application", + Long: `A longer description that spans multiple lines and likely contains +examples and usage of using your application. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.`, + // Uncomment the following line if your bare application + // has an action associated with it: + // Run: func(cmd *cobra.Command, args []string) { }, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func init() { + cobra.OnInitialize(initConfig) + + // Here you will define your flags and configuration settings. + // Cobra supports persistent flags, which, if defined here, + // will be global for your application. + + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.testproject.yaml)") + + + // Cobra also supports local flags, which will only run + // when this action is called directly. + rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} + + +// initConfig reads in config file and ENV variables if set. +func initConfig() { + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := os.UserHomeDir() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // Search config in home directory with name ".testproject" (without extension). + viper.AddConfigPath(home) + viper.SetConfigName(".testproject") + } + + viper.AutomaticEnv() // read in environment variables that match + + // If a config file is found, read it in. + if err := viper.ReadInConfig(); err == nil { + fmt.Println("Using config file:", viper.ConfigFileUsed()) + } +} + diff --git a/cobra/tpl/go1.12.go b/cobra/tpl/go1.12.go new file mode 100644 index 000000000..b1c581dec --- /dev/null +++ b/cobra/tpl/go1.12.go @@ -0,0 +1,154 @@ +// +build go1.12 + +package tpl + +func MainTemplate() []byte { + return []byte(`/* +{{ .Copyright }} +{{ if .Legal.Header }}{{ .Legal.Header }}{{ end }} +*/ +package main + +import "{{ .PkgName }}/cmd" + +func main() { + cmd.Execute() +} +`) +} + +func RootTemplate() []byte { + return []byte(`/* +{{ .Copyright }} +{{ if .Legal.Header }}{{ .Legal.Header }}{{ end }} +*/ +package cmd + +import ( + "fmt" + "os" + "github.com/spf13/cobra" +{{- if .Viper }} + "github.com/spf13/viper" +{{ end -}} +) + +{{ if .Viper }} +var cfgFile string +{{ end }} + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "{{ .AppName }}", + Short: "A brief description of your application", + Long: ` + "`" + `A longer description that spans multiple lines and likely contains +examples and usage of using your application. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.` + "`" + `, + // Uncomment the following line if your bare application + // has an action associated with it: + // Run: func(cmd *cobra.Command, args []string) { }, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func init() { +{{- if .Viper }} + cobra.OnInitialize(initConfig) +{{ end }} + // Here you will define your flags and configuration settings. + // Cobra supports persistent flags, which, if defined here, + // will be global for your application. +{{ if .Viper }} + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .AppName }}.yaml)") +{{ else }} + // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .AppName }}.yaml)") +{{ end }} + + // Cobra also supports local flags, which will only run + // when this action is called directly. + rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} + +{{ if .Viper }} +// initConfig reads in config file and ENV variables if set. +func initConfig() { + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := os.UserHomeDir() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // Search config in home directory with name ".{{ .AppName }}" (without extension). + viper.AddConfigPath(home) + viper.SetConfigName(".{{ .AppName }}") + } + + viper.AutomaticEnv() // read in environment variables that match + + // If a config file is found, read it in. + if err := viper.ReadInConfig(); err == nil { + fmt.Println("Using config file:", viper.ConfigFileUsed()) + } +} +{{ end }} +`) +} + +func AddCommandTemplate() []byte { + return []byte(`/* +{{ .Project.Copyright }} +{{ if .Legal.Header }}{{ .Legal.Header }}{{ end }} +*/ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +// {{ .CmdName }}Cmd represents the {{ .CmdName }} command +var {{ .CmdName }}Cmd = &cobra.Command{ + Use: "{{ .CmdName }}", + Short: "A brief description of your command", + Long: ` + "`" + `A longer description that spans multiple lines and likely contains examples +and usage of using your command. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.` + "`" + `, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("{{ .CmdName }} called") + }, +} + +func init() { + {{ .CmdParent }}.AddCommand({{ .CmdName }}Cmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // {{ .CmdName }}Cmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // {{ .CmdName }}Cmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} +`) +} diff --git a/cobra/tpl/main.go b/cobra/tpl/main.go index 5e5a0fae2..50127fbab 100644 --- a/cobra/tpl/main.go +++ b/cobra/tpl/main.go @@ -1,3 +1,5 @@ +// +build !go1.12 + package tpl func MainTemplate() []byte { @@ -26,10 +28,10 @@ import ( "fmt" "os" "github.com/spf13/cobra" -{{ if .Viper }} +{{- if .Viper }} homedir "github.com/mitchellh/go-homedir" "github.com/spf13/viper" -{{ end }} +{{ end -}} ) {{ if .Viper }}