github.com/gfleury/gobbs@v0.0.0-20200831213239-44ca2b94c1a1/cmd/root.go (about)

     1  package cmd
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  
     7  	"github.com/gfleury/gobbs/common"
     8  	"github.com/gfleury/gobbs/common/log"
     9  	"github.com/gfleury/gobbs/pullrequests"
    10  	"github.com/gfleury/gobbs/repos"
    11  	"github.com/gfleury/gobbs/search"
    12  	"github.com/gfleury/gobbs/users"
    13  
    14  	homedir "github.com/mitchellh/go-homedir"
    15  	"github.com/spf13/cobra"
    16  	"github.com/spf13/viper"
    17  )
    18  
    19  var (
    20  	cfgFile        string
    21  	verbosity      int
    22  	stashInfo      common.StashInfo
    23  	storePWDGoPass bool
    24  )
    25  var rootCmd = &cobra.Command{Use: common.AppName}
    26  
    27  func init() {
    28  	cobra.OnInitialize(initConfig)
    29  
    30  	rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.gobbs.yaml)")
    31  	rootCmd.PersistentFlags().IntVarP(stashInfo.Timeout(), "timeout", "t", 30, "timeout for api requests")
    32  	rootCmd.PersistentFlags().IntVarP(&verbosity, "verbose", "v", 1, "Increase verbosity for debugging")
    33  
    34  	rootCmd.PersistentFlags().StringVarP(stashInfo.Host(), "host", "H", *stashInfo.Host(), "Stash host (https://stash.example.com)")
    35  	rootCmd.PersistentFlags().StringVarP(stashInfo.Project(), "project", "P", *stashInfo.Project(), "Stash project slug (PRJ)")
    36  	rootCmd.PersistentFlags().StringVarP(stashInfo.Repo(), "repository", "r", *stashInfo.Repo(), "Stash repository slug (repo01)")
    37  
    38  	rootCmd.PersistentFlags().BoolVarP(&storePWDGoPass, "gopass", "g", false, "Enable password to be stored with gopass (gopass must be installed, https://www.gopass.pw/)")
    39  	rootCmd.PersistentFlags().StringVarP(stashInfo.Credential().User(), "user", "u", *stashInfo.Credential().User(), "Stash username")
    40  	rootCmd.PersistentFlags().StringVarP(stashInfo.Credential().Passwd(), "passwd", "p", *stashInfo.Credential().Passwd(), "Stash username password")
    41  
    42  	rootCmd.AddCommand(pullrequests.PullRequestRoot)
    43  	rootCmd.AddCommand(repos.ReposRoot)
    44  	rootCmd.AddCommand(users.UserRoot)
    45  	rootCmd.AddCommand(search.Search)
    46  }
    47  
    48  func initConfig() {
    49  	os.Setenv("GOBBS_DEBUG", fmt.Sprintf("%d", verbosity))
    50  	log.IncreaseLogLevel(verbosity)
    51  
    52  	common.SetConfig(viper.NewWithOptions(viper.KeyDelimiter("::")))
    53  
    54  	common.Config().SetEnvPrefix("GOBBS")
    55  	common.Config().AutomaticEnv()
    56  
    57  	if cfgFile == "" {
    58  		cfgFile = common.Config().GetString("config")
    59  	}
    60  
    61  	if *stashInfo.Host() == "" {
    62  		stashInfo.SetHost(common.Config().GetString("host"))
    63  	}
    64  	if *stashInfo.Credential().User() == "" {
    65  		stashInfo.Credential().SetUser(common.Config().GetString("user"))
    66  	}
    67  	if *stashInfo.Credential().Passwd() == "" {
    68  		stashInfo.Credential().SetPasswd(common.Config().GetString("passwd"))
    69  	}
    70  
    71  	if cfgFile != "" {
    72  		// Use config file from the flag.
    73  		common.Config().SetConfigFile(cfgFile)
    74  	} else {
    75  		// Find home directory.
    76  		home, err := homedir.Dir()
    77  		if err != nil {
    78  			log.Fatal(err.Error())
    79  		}
    80  
    81  		// Search config in home directory with name ".gobbs" (without extension).
    82  		common.Config().AddConfigPath(home)
    83  		common.Config().SetConfigName(fmt.Sprintf(".%s", common.AppName))
    84  		cfgFile = fmt.Sprintf("%s/.%s.yaml", home, common.AppName)
    85  	}
    86  
    87  	if err := common.Config().ReadInConfig(); err == nil {
    88  		log.Debugf("Using config file:", common.Config().ConfigFileUsed())
    89  	} else {
    90  		log.Debugf("Config file not found, creating empty file:", cfgFile)
    91  		file, err := os.Create(cfgFile)
    92  		if err != nil {
    93  			log.Fatal(err.Error())
    94  		}
    95  		file.Close()
    96  	}
    97  }
    98  
    99  func persistConfig() error {
   100  	// common.Config() is only initialized if rootCmd ran (false if only help mode was shown)
   101  	if common.Config() != nil {
   102  		err := common.Config().BindPFlag(fmt.Sprintf(common.UserNameKey, *stashInfo.Host()), rootCmd.PersistentFlags().Lookup("user"))
   103  		if err != nil {
   104  			return err
   105  		}
   106  		if common.Config().GetString("password_method") == "" && !storePWDGoPass && stashInfo.Credential().IsNew() {
   107  			err = common.Config().BindPFlag(fmt.Sprintf(common.PasswdKey, *stashInfo.Host()), rootCmd.PersistentFlags().Lookup("passwd"))
   108  			if err != nil {
   109  				return err
   110  			}
   111  		} else if (storePWDGoPass || common.Config().GetString("password_method") == "gopass") && stashInfo.Credential().IsNew() {
   112  			err = common.SavePasswdExternal(*stashInfo.Host(), rootCmd.PersistentFlags().Lookup("passwd").Value.String())
   113  			if err != nil {
   114  				return err
   115  			}
   116  		}
   117  		if storePWDGoPass {
   118  			common.Config().Set("password_method", "gopass")
   119  		}
   120  		err = common.Config().WriteConfig()
   121  		return err
   122  	}
   123  	return nil
   124  }
   125  
   126  func Execute() error {
   127  	ctx := common.APIClientContext(&stashInfo)
   128  
   129  	err := rootCmd.ExecuteContext(ctx)
   130  	if err != nil {
   131  		return err
   132  	}
   133  
   134  	return persistConfig()
   135  }