From 47de8c5fc8fae5410daee363c33216799f68db32 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Sun, 20 Sep 2020 09:29:04 -0400 Subject: [PATCH 1/4] util: Add flagConfig function flagConfig() compares the command flags and the settings in the config files. The command defaults to using any value specified on the command line regardless of the value in the config files. The function must be called by all commands, and the code only needs to verify the flag values and not the config values. For example, in the current code it is necessary to check both the config and the flag values: showComments, _ := cmd.Flags().GetBool("comments") if showComments == false { showComments = getMainConfig().GetBool(CommandPrefix + "comments") } After a command calls this function, only the flags need to be checked showComments, _ := cmd.Flags().GetBool("comments") Add flagConfig function to compare command line flags and the values in the config files. Signed-off-by: Prarit Bhargava --- cmd/issue_show.go | 2 -- cmd/mr_show.go | 2 -- cmd/root.go | 27 ++++++++++++++++++++++ cmd/util.go | 58 ++++++++++++++++++++++++++++++++++++----------- go.sum | 2 ++ 5 files changed, 74 insertions(+), 17 deletions(-) diff --git a/cmd/issue_show.go b/cmd/issue_show.go index 416784bf..494275d1 100644 --- a/cmd/issue_show.go +++ b/cmd/issue_show.go @@ -25,8 +25,6 @@ var issueShowCmd = &cobra.Command{ Long: ``, Run: func(cmd *cobra.Command, args []string) { - setCommandPrefix() - rn, issueNum, err := parseArgs(args) if err != nil { log.Fatal(err) diff --git a/cmd/mr_show.go b/cmd/mr_show.go index 68cd998c..bf8a61e3 100644 --- a/cmd/mr_show.go +++ b/cmd/mr_show.go @@ -31,8 +31,6 @@ var mrShowCmd = &cobra.Command{ Long: ``, Run: func(cmd *cobra.Command, args []string) { - setCommandPrefix() - rn, mrNum, err := parseArgs(args) if err != nil { log.Fatal(err) diff --git a/cmd/root.go b/cmd/root.go index 90cd5d02..4ce62906 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -228,6 +228,29 @@ func parseArgsRemoteRef(args []string) (string, string, error) { return rn, name, nil } +// setCommandPrefix returns a concatenated value of some of the commandline. +// For example, 'lab mr show' would return 'mr_show.', and 'lab issue list' +// would return 'issue_list.' +func setCommandPrefix(scmd *cobra.Command) { + for _, command := range RootCmd.Commands() { + if CommandPrefix != "" { + break + } + commandName := strings.Split(command.Use, " ")[0] + if scmd == command { + CommandPrefix = commandName + "." + break + } + for _, subcommand := range command.Commands() { + subCommandName := commandName + "_" + strings.Split(subcommand.Use, " ")[0] + if scmd == subcommand { + CommandPrefix = subCommandName + "." + break + } + } + } +} + var ( // Will be updated to upstream in Execute() if "upstream" remote exists forkedFromRemote = "origin" @@ -315,6 +338,10 @@ func Execute() { } } + // Set CommandPrefix + scmd, _, _ := cmd.Find(os.Args) + setCommandPrefix(scmd) + if err := RootCmd.Execute(); err != nil { // Execute has already logged the error os.Exit(1) diff --git a/cmd/util.go b/cmd/util.go index 6c62dab0..6cc89af4 100644 --- a/cmd/util.go +++ b/cmd/util.go @@ -2,10 +2,11 @@ package cmd import ( - "path" - "runtime" + "log" + "strconv" "strings" + flag "github.com/spf13/pflag" "github.com/spf13/viper" "github.com/zaquestion/lab/internal/config" ) @@ -14,23 +15,54 @@ var ( CommandPrefix string ) +// flagConfig compares command line flags and the flags set in the config +// files. The command line value will always override any value set in the +// config files. +func flagConfig(fs *flag.FlagSet) { + fs.VisitAll(func(f *flag.Flag) { + var ( + configValue interface{} + configString string + ) + + switch f.Value.Type() { + case "bool": + configValue = getMainConfig().GetBool(CommandPrefix + f.Name) + configString = strconv.FormatBool(configValue.(bool)) + case "string": + configValue = getMainConfig().GetString(CommandPrefix + f.Name) + configString = configValue.(string) + case "stringSlice": + configValue = getMainConfig().GetStringSlice(CommandPrefix + f.Name) + configString = strings.Join(configValue.([]string), " ") + + case "int": + configValue = getMainConfig().GetInt64(CommandPrefix + f.Name) + configString = strconv.FormatInt(configValue.(int64), 10) + case "stringArray": + // viper does not have support for stringArray + configString = "" + default: + log.Fatal("ERROR: found unidentified flag: ", f.Value.Type(), f) + } + + // if set, always use the command line option (flag) value + if f.Value.String() != f.DefValue { + return + } + // o/w use the value in the configfile + if configString != "" && configString != f.DefValue { + f.Value.Set(configString) + } + }) +} + // getMainConfig returns the merged config of ~/.config/lab/lab.toml and // .git/lab/lab.toml func getMainConfig() *viper.Viper { return config.MainConfig } -// setCommandPrefix sets command name that is used in the config -// files to set per-command options. For example, the "lab issue show" -// command has a prefix of "issue_show.", and "lab mr list" as a -// prefix of "mr_list." -func setCommandPrefix() { - _, file, _, _ := runtime.Caller(1) - _, filename := path.Split(file) - s := strings.Split(filename, ".") - CommandPrefix = s[0] + "." -} - // textToMarkdown converts text with markdown friendly line breaks // See https://gist.github.com/shaunlebron/746476e6e7a4d698b373 for more info. func textToMarkdown(text string) string { diff --git a/go.sum b/go.sum index c6206095..d5ed375e 100644 --- a/go.sum +++ b/go.sum @@ -346,4 +346,6 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 928ac904ac592b1d9b3acec2d0202ea7a832d181 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Sun, 20 Sep 2020 13:01:44 -0400 Subject: [PATCH 2/4] show: Convert to using flagConfig() Add a general cobra command PersistentPreRun that can be called by any lab command, and convert the 'mr show' and 'issue show' commands to use flagConfig(). Signed-off-by: Prarit Bhargava --- cmd/issue_show.go | 14 ++++++-------- cmd/mr_show.go | 14 ++++++-------- cmd/util.go | 5 +++++ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/cmd/issue_show.go b/cmd/issue_show.go index 494275d1..d42ed73c 100644 --- a/cmd/issue_show.go +++ b/cmd/issue_show.go @@ -18,11 +18,12 @@ import ( ) var issueShowCmd = &cobra.Command{ - Use: "show [remote] ", - Aliases: []string{"get"}, - ArgAliases: []string{"s"}, - Short: "Describe an issue", - Long: ``, + Use: "show [remote] ", + Aliases: []string{"get"}, + ArgAliases: []string{"s"}, + Short: "Describe an issue", + Long: ``, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, issueNum, err := parseArgs(args) @@ -44,9 +45,6 @@ var issueShowCmd = &cobra.Command{ printIssue(issue, rn, renderMarkdown) showComments, _ := cmd.Flags().GetBool("comments") - if showComments == false { - showComments = getMainConfig().GetBool(CommandPrefix + "comments") - } if showComments { discussions, err := lab.IssueListDiscussions(rn, int(issueNum)) if err != nil { diff --git a/cmd/mr_show.go b/cmd/mr_show.go index bf8a61e3..f491cae6 100644 --- a/cmd/mr_show.go +++ b/cmd/mr_show.go @@ -24,11 +24,12 @@ var ( ) var mrShowCmd = &cobra.Command{ - Use: "show [remote] ", - Aliases: []string{"get"}, - ArgAliases: []string{"s"}, - Short: "Describe a merge request", - Long: ``, + Use: "show [remote] ", + Aliases: []string{"get"}, + ArgAliases: []string{"s"}, + Short: "Describe a merge request", + Long: ``, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, mrNum, err := parseArgs(args) @@ -68,9 +69,6 @@ var mrShowCmd = &cobra.Command{ } showComments, _ := cmd.Flags().GetBool("comments") - if showComments == false { - showComments = getMainConfig().GetBool(CommandPrefix + "comments") - } if showComments { discussions, err := lab.MRListDiscussions(rn, int(mrNum)) if err != nil { diff --git a/cmd/util.go b/cmd/util.go index 6cc89af4..747499cb 100644 --- a/cmd/util.go +++ b/cmd/util.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" + "github.com/spf13/cobra" flag "github.com/spf13/pflag" "github.com/spf13/viper" "github.com/zaquestion/lab/internal/config" @@ -69,3 +70,7 @@ func textToMarkdown(text string) string { text = strings.Replace(text, "\n", " \n", -1) return text } + +func LabPersistentPreRun(cmd *cobra.Command, args []string) { + flagConfig(cmd.Flags()) +} From 9bf24520ef5301b555974bbc77454456c15216fe Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Mon, 21 Sep 2020 08:04:51 -0400 Subject: [PATCH 3/4] lab: Add LabPersistentPreRun() to all commands Add LabPersistendPreRun() to all commands so that the configs and flags are synchronized. Signed-off-by: Prarit Bhargava --- cmd/ci_lint.go | 7 ++++--- cmd/ci_run.go | 2 ++ cmd/ci_status.go | 3 ++- cmd/ci_trace.go | 9 +++++---- cmd/clone.go | 1 + cmd/fork.go | 9 +++++---- cmd/issue.go | 7 ++++--- cmd/issue_browse.go | 9 +++++---- cmd/issue_close.go | 11 ++++++----- cmd/issue_create.go | 11 ++++++----- cmd/issue_edit.go | 3 ++- cmd/issue_list.go | 1 + cmd/issue_note.go | 11 ++++++----- cmd/label.go | 7 ++++--- cmd/label_list.go | 1 + cmd/merge_request.go | 9 +++++---- cmd/mr.go | 7 ++++--- cmd/mr_approve.go | 11 ++++++----- cmd/mr_browse.go | 9 +++++---- cmd/mr_checkout.go | 9 +++++---- cmd/mr_close.go | 11 ++++++----- cmd/mr_create.go | 13 +++++++------ cmd/mr_discussion.go | 11 ++++++----- cmd/mr_list.go | 11 ++++++----- cmd/mr_merge.go | 11 ++++++----- cmd/mr_note.go | 11 ++++++----- cmd/mr_rebase.go | 9 +++++---- cmd/mr_thumb.go | 18 ++++++++++-------- cmd/project.go | 9 +++++---- cmd/project_browse.go | 9 +++++---- cmd/project_create.go | 3 ++- cmd/project_list.go | 7 ++++--- cmd/snippet.go | 9 +++++---- cmd/snippet_browse.go | 7 ++++--- cmd/snippet_create.go | 1 + cmd/snippet_list.go | 9 +++++---- cmd/version.go | 7 ++++--- 37 files changed, 166 insertions(+), 127 deletions(-) diff --git a/cmd/ci_lint.go b/cmd/ci_lint.go index ab6b4bfe..69fd56fa 100644 --- a/cmd/ci_lint.go +++ b/cmd/ci_lint.go @@ -14,9 +14,10 @@ import ( // ciLintCmd represents the lint command var ciLintCmd = &cobra.Command{ - Use: "lint", - Short: "Validate .gitlab-ci.yml against GitLab", - Long: ``, + Use: "lint", + Short: "Validate .gitlab-ci.yml against GitLab", + Long: ``, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { path := ".gitlab-ci.yml" if len(args) == 1 { diff --git a/cmd/ci_run.go b/cmd/ci_run.go index 0ffb915b..f0471e7c 100644 --- a/cmd/ci_run.go +++ b/cmd/ci_run.go @@ -27,6 +27,7 @@ Project will be inferred from branch if not provided Note: "lab ci create" differs from "lab ci trigger" which is a different API`, Example: `lab ci create feature_branch lab ci create -p engineering/integration_tests master`, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { pid, branch, err := getCIRunOptions(cmd, args) if err != nil { @@ -55,6 +56,7 @@ Note: "lab ci trigger" differs from "lab ci create" which is a different API`, Example: `lab ci trigger feature_branch lab ci trigger -p engineering/integration_tests master lab ci trigger -p engineering/integration_tests -v foo=bar master`, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { pid, branch, err := getCIRunOptions(cmd, args) if err != nil { diff --git a/cmd/ci_status.go b/cmd/ci_status.go index 174ebb25..a3b95081 100644 --- a/cmd/ci_status.go +++ b/cmd/ci_status.go @@ -23,7 +23,8 @@ var ciStatusCmd = &cobra.Command{ Long: ``, Example: `lab ci status lab ci status --wait`, - RunE: nil, + RunE: nil, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { var ( rn string diff --git a/cmd/ci_trace.go b/cmd/ci_trace.go index caaeaba2..2ce12da2 100644 --- a/cmd/ci_trace.go +++ b/cmd/ci_trace.go @@ -21,10 +21,11 @@ import ( // ciLintCmd represents the lint command var ciTraceCmd = &cobra.Command{ - Use: "trace [remote [[branch:]job]]", - Aliases: []string{"logs"}, - Short: "Trace the output of a ci job", - Long: `If a job is not specified the latest running job or last job in the pipeline is used`, + Use: "trace [remote [[branch:]job]]", + Aliases: []string{"logs"}, + Short: "Trace the output of a ci job", + Long: `If a job is not specified the latest running job or last job in the pipeline is used`, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { var ( rn string diff --git a/cmd/clone.go b/cmd/clone.go index f291b6ad..d4fdce68 100644 --- a/cmd/clone.go +++ b/cmd/clone.go @@ -20,6 +20,7 @@ var cloneCmd = &cobra.Command{ - repo - namespace/repo - namespace/group/repo`, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { project, err := gitlab.FindProject(args[0]) if err == gitlab.ErrProjectNotFound { diff --git a/cmd/fork.go b/cmd/fork.go index 000846d4..cba89101 100644 --- a/cmd/fork.go +++ b/cmd/fork.go @@ -14,10 +14,11 @@ var skipClone = false // forkCmd represents the fork command var forkCmd = &cobra.Command{ - Use: "fork [upstream-to-fork]", - Short: "Fork a remote repository on GitLab and add as remote", - Long: ``, - Args: cobra.MaximumNArgs(1), + Use: "fork [upstream-to-fork]", + Short: "Fork a remote repository on GitLab and add as remote", + Long: ``, + Args: cobra.MaximumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { skipClone, _ = cmd.Flags().GetBool("skip-clone") if len(args) == 1 { diff --git a/cmd/issue.go b/cmd/issue.go index 115d3dda..356797cf 100644 --- a/cmd/issue.go +++ b/cmd/issue.go @@ -5,9 +5,10 @@ import ( ) var issueCmd = &cobra.Command{ - Use: "issue", - Short: `Describe, list, and create issues`, - Long: ``, + Use: "issue", + Short: `Describe, list, and create issues`, + Long: ``, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { if list, _ := cmd.Flags().GetBool("list"); list { issueListCmd.Run(cmd, args) diff --git a/cmd/issue_browse.go b/cmd/issue_browse.go index 2916a8ce..3980c87f 100644 --- a/cmd/issue_browse.go +++ b/cmd/issue_browse.go @@ -14,10 +14,11 @@ import ( var browse = browser.Open var issueBrowseCmd = &cobra.Command{ - Use: "browse [remote] ", - Aliases: []string{"b"}, - Short: "View issue in a browser", - Long: ``, + Use: "browse [remote] ", + Aliases: []string{"b"}, + Short: "View issue in a browser", + Long: ``, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, num, err := parseArgs(args) if err != nil { diff --git a/cmd/issue_close.go b/cmd/issue_close.go index afd5789e..4d819378 100644 --- a/cmd/issue_close.go +++ b/cmd/issue_close.go @@ -11,11 +11,12 @@ import ( ) var issueCloseCmd = &cobra.Command{ - Use: "close [remote] ", - Aliases: []string{"delete"}, - Short: "Close issue by id", - Long: ``, - Args: cobra.MinimumNArgs(1), + Use: "close [remote] ", + Aliases: []string{"delete"}, + Short: "Close issue by id", + Long: ``, + Args: cobra.MinimumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, id, err := parseArgs(args) if err != nil { diff --git a/cmd/issue_create.go b/cmd/issue_create.go index 365c1969..9c4a4f85 100644 --- a/cmd/issue_create.go +++ b/cmd/issue_create.go @@ -19,11 +19,12 @@ import ( ) var issueCreateCmd = &cobra.Command{ - Use: "create [remote]", - Aliases: []string{"new"}, - Short: "Open an issue on GitLab", - Long: ``, - Args: cobra.MaximumNArgs(1), + Use: "create [remote]", + Aliases: []string{"new"}, + Short: "Open an issue on GitLab", + Long: ``, + Args: cobra.MaximumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { msgs, err := cmd.Flags().GetStringArray("message") if err != nil { diff --git a/cmd/issue_edit.go b/cmd/issue_edit.go index 1e9cd6eb..d30c61c9 100644 --- a/cmd/issue_edit.go +++ b/cmd/issue_edit.go @@ -28,7 +28,8 @@ lab issue update # same as above lab issue edit -m "new title" # update title lab issue edit -m "new title" -m "new desc" # update title & description lab issue edit -l newlabel --unlabel oldlabel # relabel issue`, - Args: cobra.MinimumNArgs(1), + Args: cobra.MinimumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { // get remote and issue from cmd arguments rn, issueNum, err := parseArgs(args) diff --git a/cmd/issue_list.go b/cmd/issue_list.go index 43a54ef6..f6e6de31 100644 --- a/cmd/issue_list.go +++ b/cmd/issue_list.go @@ -28,6 +28,7 @@ var issueListCmd = &cobra.Command{ lab issue list "search terms" # search issues for "search terms" lab issue search "search terms" # same as above lab issue list remote "search terms" # search "remote" for issues with "search terms"`, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { issues, err := issueList(args) if err != nil { diff --git a/cmd/issue_note.go b/cmd/issue_note.go index ee14910d..71476f0c 100644 --- a/cmd/issue_note.go +++ b/cmd/issue_note.go @@ -18,11 +18,12 @@ import ( ) var issueCreateNoteCmd = &cobra.Command{ - Use: "note [remote] ", - Aliases: []string{"comment"}, - Short: "Add a note or comment to an issue on GitLab", - Long: ``, - Args: cobra.MinimumNArgs(1), + Use: "note [remote] ", + Aliases: []string{"comment"}, + Short: "Add a note or comment to an issue on GitLab", + Long: ``, + Args: cobra.MinimumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, issueNum, err := parseArgs(args) if err != nil { diff --git a/cmd/label.go b/cmd/label.go index 6871455f..3a9dcaf6 100644 --- a/cmd/label.go +++ b/cmd/label.go @@ -5,9 +5,10 @@ import ( ) var labelCmd = &cobra.Command{ - Use: "label", - Short: `List and search labels`, - Long: ``, + Use: "label", + Short: `List and search labels`, + Long: ``, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { cmd.Help() return diff --git a/cmd/label_list.go b/cmd/label_list.go index c864885c..32251b3b 100644 --- a/cmd/label_list.go +++ b/cmd/label_list.go @@ -20,6 +20,7 @@ var labelListCmd = &cobra.Command{ lab label list "search term" # search labels for "search term" lab label search "search term" # same as above lab label list remote "search term" # search "remote" for labels with "search term"`, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, labelSearch, err := parseArgsRemoteString(args) if err != nil { diff --git a/cmd/merge_request.go b/cmd/merge_request.go index 719f4821..5480f938 100644 --- a/cmd/merge_request.go +++ b/cmd/merge_request.go @@ -7,10 +7,11 @@ import ( ) var mergeRequestCmd = &cobra.Command{ - Use: "merge-request [remote [branch]]", - Short: mrCreateCmd.Short, - Long: mrCreateCmd.Long, - Args: mrCreateCmd.Args, + Use: "merge-request [remote [branch]]", + Short: mrCreateCmd.Short, + Long: mrCreateCmd.Long, + Args: mrCreateCmd.Args, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { runMRCreate(cmd, args) }, diff --git a/cmd/mr.go b/cmd/mr.go index 4c372b69..780e2e6f 100644 --- a/cmd/mr.go +++ b/cmd/mr.go @@ -6,9 +6,10 @@ import ( // mrCmd represents the mr command var mrCmd = &cobra.Command{ - Use: "mr", - Short: `Describe, list, and create merge requests`, - Long: ``, + Use: "mr", + Short: `Describe, list, and create merge requests`, + Long: ``, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { if list, _ := cmd.Flags().GetBool("list"); list { listCmd.Run(cmd, args) diff --git a/cmd/mr_approve.go b/cmd/mr_approve.go index 32c02413..da72cd93 100644 --- a/cmd/mr_approve.go +++ b/cmd/mr_approve.go @@ -11,11 +11,12 @@ import ( ) var mrApproveCmd = &cobra.Command{ - Use: "approve [remote] ", - Aliases: []string{}, - Short: "Approve merge request", - Long: ``, - Args: cobra.MinimumNArgs(1), + Use: "approve [remote] ", + Aliases: []string{}, + Short: "Approve merge request", + Long: ``, + Args: cobra.MinimumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, id, err := parseArgs(args) if err != nil { diff --git a/cmd/mr_browse.go b/cmd/mr_browse.go index 7c9d34a8..8d9a9a31 100644 --- a/cmd/mr_browse.go +++ b/cmd/mr_browse.go @@ -15,10 +15,11 @@ import ( ) var mrBrowseCmd = &cobra.Command{ - Use: "browse [remote] ", - Aliases: []string{"b"}, - Short: "View merge request in a browser", - Long: ``, + Use: "browse [remote] ", + Aliases: []string{"b"}, + Short: "View merge request in a browser", + Long: ``, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, num, err := parseArgs(args) if err != nil { diff --git a/cmd/mr_checkout.go b/cmd/mr_checkout.go index 4b83ac17..fede4a66 100644 --- a/cmd/mr_checkout.go +++ b/cmd/mr_checkout.go @@ -25,10 +25,11 @@ var ( // listCmd represents the list command var checkoutCmd = &cobra.Command{ - Use: "checkout ", - Short: "Checkout an open merge request", - Long: ``, - Args: cobra.MinimumNArgs(1), + Use: "checkout ", + Short: "Checkout an open merge request", + Long: ``, + Args: cobra.MinimumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, mrID, err := parseArgs(args) if err != nil { diff --git a/cmd/mr_close.go b/cmd/mr_close.go index a5859aa5..969d41b6 100644 --- a/cmd/mr_close.go +++ b/cmd/mr_close.go @@ -11,11 +11,12 @@ import ( ) var mrCloseCmd = &cobra.Command{ - Use: "close [remote] ", - Aliases: []string{"delete"}, - Short: "Close merge request", - Long: ``, - Args: cobra.MinimumNArgs(1), + Use: "close [remote] ", + Aliases: []string{"delete"}, + Short: "Close merge request", + Long: ``, + Args: cobra.MinimumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, id, err := parseArgs(args) if err != nil { diff --git a/cmd/mr_create.go b/cmd/mr_create.go index bc3ce6e7..9bff03f2 100644 --- a/cmd/mr_create.go +++ b/cmd/mr_create.go @@ -24,12 +24,13 @@ import ( // mrCmd represents the mr command var mrCreateCmd = &cobra.Command{ - Use: "create [remote [branch]]", - Aliases: []string{"new"}, - Short: "Open a merge request on GitLab", - Long: `Creates a merge request (default: MR created on default branch of origin)`, - Args: cobra.MaximumNArgs(2), - Run: runMRCreate, + Use: "create [remote [branch]]", + Aliases: []string{"new"}, + Short: "Open a merge request on GitLab", + Long: `Creates a merge request (default: MR created on default branch of origin)`, + Args: cobra.MaximumNArgs(2), + PersistentPreRun: LabPersistentPreRun, + Run: runMRCreate, } func init() { diff --git a/cmd/mr_discussion.go b/cmd/mr_discussion.go index 671afd72..509829e8 100644 --- a/cmd/mr_discussion.go +++ b/cmd/mr_discussion.go @@ -19,11 +19,12 @@ import ( ) var mrCreateDiscussionCmd = &cobra.Command{ - Use: "discussion [remote] ", - Aliases: []string{"comment"}, - Short: "Start a discussion on an MR on GitLab", - Long: ``, - Args: cobra.MinimumNArgs(1), + Use: "discussion [remote] ", + Aliases: []string{"comment"}, + Short: "Start a discussion on an MR on GitLab", + Long: ``, + Args: cobra.MinimumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, mrNum, err := parseArgs(args) if err != nil { diff --git a/cmd/mr_list.go b/cmd/mr_list.go index 0c29bc17..3d14c8eb 100644 --- a/cmd/mr_list.go +++ b/cmd/mr_list.go @@ -24,11 +24,12 @@ var ( // listCmd represents the list command var listCmd = &cobra.Command{ - Use: "list [remote]", - Aliases: []string{"ls"}, - Short: "List merge requests", - Long: ``, - Args: cobra.MaximumNArgs(1), + Use: "list [remote]", + Aliases: []string{"ls"}, + Short: "List merge requests", + Long: ``, + Args: cobra.MaximumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { mrs, err := mrList(args) if err != nil { diff --git a/cmd/mr_merge.go b/cmd/mr_merge.go index 145138c2..0371fbc2 100644 --- a/cmd/mr_merge.go +++ b/cmd/mr_merge.go @@ -10,11 +10,12 @@ import ( ) var mrMergeCmd = &cobra.Command{ - Use: "merge [remote] ", - Aliases: []string{"delete"}, - Short: "Merge an open merge request", - Long: `If the pipeline for the mr is still running, lab sets merge on success`, - Args: cobra.MinimumNArgs(1), + Use: "merge [remote] ", + Aliases: []string{"delete"}, + Short: "Merge an open merge request", + Long: `If the pipeline for the mr is still running, lab sets merge on success`, + Args: cobra.MinimumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, id, err := parseArgs(args) if err != nil { diff --git a/cmd/mr_note.go b/cmd/mr_note.go index 4c2fb1a8..fd8cc36d 100644 --- a/cmd/mr_note.go +++ b/cmd/mr_note.go @@ -19,11 +19,12 @@ import ( ) var mrCreateNoteCmd = &cobra.Command{ - Use: "note [remote] ", - Aliases: []string{"comment"}, - Short: "Add a note or comment to an MR on GitLab", - Long: ``, - Args: cobra.MinimumNArgs(1), + Use: "note [remote] ", + Aliases: []string{"comment"}, + Short: "Add a note or comment to an MR on GitLab", + Long: ``, + Args: cobra.MinimumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, mrNum, err := parseArgs(args) if err != nil { diff --git a/cmd/mr_rebase.go b/cmd/mr_rebase.go index 58ebf5e8..cb43965c 100644 --- a/cmd/mr_rebase.go +++ b/cmd/mr_rebase.go @@ -10,10 +10,11 @@ import ( ) var mrRebaseCmd = &cobra.Command{ - Use: "rebase [remote] ", - Aliases: []string{"delete"}, - Short: "Rebase an open merge request", - Args: cobra.MinimumNArgs(1), + Use: "rebase [remote] ", + Aliases: []string{"delete"}, + Short: "Rebase an open merge request", + Args: cobra.MinimumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, id, err := parseArgs(args) if err != nil { diff --git a/cmd/mr_thumb.go b/cmd/mr_thumb.go index 2c82e352..f2cccc6a 100644 --- a/cmd/mr_thumb.go +++ b/cmd/mr_thumb.go @@ -11,17 +11,19 @@ import ( ) var mrThumbCmd = &cobra.Command{ - Use: "thumb", - Aliases: []string{}, - Short: "Thumb operations on merge requests", - Long: ``, + Use: "thumb", + Aliases: []string{}, + Short: "Thumb operations on merge requests", + PersistentPreRun: LabPersistentPreRun, + Long: ``, } var mrThumbUpCmd = &cobra.Command{ - Use: "up [remote] ", - Aliases: []string{}, - Short: "Thumb up merge request", - Long: ``, + Use: "up [remote] ", + Aliases: []string{}, + Short: "Thumb up merge request", + Long: ``, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, id, err := parseArgs(args) if err != nil { diff --git a/cmd/project.go b/cmd/project.go index 8ef06102..95268bea 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -6,10 +6,11 @@ import ( // repoCmd represents the repo command var projectCmd = &cobra.Command{ - Use: "project", - Aliases: []string{"repo"}, - Short: "Perform project level operations on GitLab", - Long: ``, + Use: "project", + Aliases: []string{"repo"}, + Short: "Perform project level operations on GitLab", + PersistentPreRun: LabPersistentPreRun, + Long: ``, //Run: func(cmd *cobra.Command, args []string) {}, } diff --git a/cmd/project_browse.go b/cmd/project_browse.go index b83f77e7..daaecdc4 100644 --- a/cmd/project_browse.go +++ b/cmd/project_browse.go @@ -8,10 +8,11 @@ import ( ) var projectBrowseCmd = &cobra.Command{ - Use: "browse [remote]", - Aliases: []string{"b"}, - Short: "View project in a browser", - Long: ``, + Use: "browse [remote]", + Aliases: []string{"b"}, + Short: "View project in a browser", + Long: ``, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, _, err := parseArgs(args) diff --git a/cmd/project_create.go b/cmd/project_create.go index 220017f5..2a7687bb 100644 --- a/cmd/project_create.go +++ b/cmd/project_create.go @@ -29,7 +29,8 @@ lab project create # user/ named lab project create myproject # user/myproject named myproject lab project create myproject -n "new proj" # user/myproject named "new proj" lab project create -n "new proj" # user/new-proj named "new proj"`, - Args: cobra.MaximumNArgs(1), + Args: cobra.MaximumNArgs(1), + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { var ( name, _ = cmd.Flags().GetString("name") diff --git a/cmd/project_list.go b/cmd/project_list.go index 2973d625..ece9f21b 100644 --- a/cmd/project_list.go +++ b/cmd/project_list.go @@ -19,9 +19,10 @@ var projectListConfig struct { } var projectListCmd = &cobra.Command{ - Use: "list [search]", - Aliases: []string{"ls", "search"}, - Short: "List your projects", + Use: "list [search]", + Aliases: []string{"ls", "search"}, + Short: "List your projects", + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { search, _, err := parseArgsStr(args) if err != nil { diff --git a/cmd/snippet.go b/cmd/snippet.go index ab4bd381..09e397ed 100644 --- a/cmd/snippet.go +++ b/cmd/snippet.go @@ -8,10 +8,11 @@ import ( // snippetCmd represents the snippet command var snippetCmd = &cobra.Command{ - Use: "snippet", - Aliases: []string{"snip"}, - Short: snippetCreateCmd.Short, - Long: snippetCreateCmd.Long, + Use: "snippet", + Aliases: []string{"snip"}, + Short: snippetCreateCmd.Short, + Long: snippetCreateCmd.Long, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { if list, _ := cmd.Flags().GetBool("list"); list { snippetListCmd.Run(cmd, args) diff --git a/cmd/snippet_browse.go b/cmd/snippet_browse.go index d261c9e3..c6029b2a 100644 --- a/cmd/snippet_browse.go +++ b/cmd/snippet_browse.go @@ -13,9 +13,10 @@ import ( ) var snippetBrowseCmd = &cobra.Command{ - Use: "browse [remote] ", - Short: "View personal or project snippet in a browser", - Long: ``, + Use: "browse [remote] ", + Short: "View personal or project snippet in a browser", + Long: ``, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { rn, id, err := parseArgs(args) if err != nil { diff --git a/cmd/snippet_create.go b/cmd/snippet_create.go index 3df519a6..8318d730 100644 --- a/cmd/snippet_create.go +++ b/cmd/snippet_create.go @@ -34,6 +34,7 @@ var snippetCreateCmd = &cobra.Command{ Long: ` Source snippets from stdin, file, or in editor from scratch Optionally add a title & description with -m`, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { msgs, err := cmd.Flags().GetStringArray("message") if err != nil { diff --git a/cmd/snippet_list.go b/cmd/snippet_list.go index b1e7244e..5a15290a 100644 --- a/cmd/snippet_list.go +++ b/cmd/snippet_list.go @@ -18,10 +18,11 @@ var snippetListConfig struct { // snippetListCmd represents the snippetList command var snippetListCmd = &cobra.Command{ - Use: "list [remote]", - Aliases: []string{"ls"}, - Short: "List personal or project snippets", - Long: ``, + Use: "list [remote]", + Aliases: []string{"ls"}, + Short: "List personal or project snippets", + Long: ``, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { snips, err := snippetList(args) if err != nil { diff --git a/cmd/version.go b/cmd/version.go index ba994d3d..5729cecc 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -12,9 +12,10 @@ var Version string // versionCmd represents the version command var versionCmd = &cobra.Command{ - Use: "version", - Short: "", - Long: ``, + Use: "version", + Short: "", + Long: ``, + PersistentPreRun: LabPersistentPreRun, Run: func(cmd *cobra.Command, args []string) { git := git.New("version") git.Stdout = nil From 010a62363d746f94927ba1a7eb54beed811302f6 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Tue, 22 Sep 2020 18:31:23 -0400 Subject: [PATCH 4/4] root_test: Add tests for new config and flag layout There isn't really a good way to test the config and flag override code. I've opted to call 'mr show' with different flag and config settings to test out the code. The tests include testing for .git/lab/lab.toml overrides of ~/.config/lab/lab.toml and tests for the override by the flag of the value in the config files. Add tests for the new config and flag layout. Signed-off-by: Prarit Bhargava --- cmd/root_test.go | 185 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) diff --git a/cmd/root_test.go b/cmd/root_test.go index d5e02939..2673e68d 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -14,6 +14,7 @@ import ( "testing" "time" + "github.com/acarl005/stripansi" "github.com/spf13/viper" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -511,3 +512,187 @@ func getAppOutput(output []byte) []string { } return lines } + +func setConfigValues(repo string, configVal string, gitVal string) { + err := os.Rename(repo+"/lab.toml", "/home/travis/.config/lab/lab.toml") + if err != nil { + log.Fatal(err) + } + + configfile, err := os.OpenFile("/home/travis/.config/lab/lab.toml", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + log.Fatal(err) + } + + if _, err := configfile.WriteString("\n[mr_show]\n comments = " + configVal + "\n"); err != nil { + log.Fatal(err) + } + configfile.Close() + + err = os.Mkdir(repo+"/.git/lab/", 0700) + if err != nil { + log.Fatal(err) + } + gitfile, err := os.OpenFile(repo+"/.git/lab/lab.toml", os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + log.Fatal(err) + } + + if _, err = gitfile.WriteString("\n[mr_show]\n comments = " + gitVal + "\n"); err != nil { + log.Fatal(err) + } + gitfile.Close() +} + +// There isn't a really good way to test the config override +// infrastruture, so just call 'mr show' and set 'mr_show.comments' +func Test_config_gitConfig_FF(t *testing.T) { + repo := copyTestRepo(t) + + setConfigValues(repo, "false", "false") + os.Remove(repo + "/lab.toml") + + cmd := exec.Command(labBinaryPath, "mr", "show", "1") + cmd.Dir = repo + + b, err := cmd.CombinedOutput() + if err != nil { + t.Log(string(b)) + t.Error(err) + } + + out := string(b) + out = stripansi.Strip(out) + + os.Remove("/home/travis/.config/lab/lab.toml") + // both configs set to false, comments should not be output + require.NotContains(t, string(b), `commented at`) +} + +func Test_config_gitConfig_FT(t *testing.T) { + repo := copyTestRepo(t) + + setConfigValues(repo, "false", "true") + os.Remove(repo + "/lab.toml") + + cmd := exec.Command(labBinaryPath, "mr", "show", "1") + cmd.Dir = repo + + b, err := cmd.CombinedOutput() + if err != nil { + t.Log(string(b)) + t.Error(err) + } + + out := string(b) + out = stripansi.Strip(out) + + os.Remove("/home/travis/.config/lab/lab.toml") + // .config set to false and .git set to true, comments should be + // output + require.Contains(t, string(b), `commented at`) +} + +func Test_config_gitConfig_TF(t *testing.T) { + repo := copyTestRepo(t) + + setConfigValues(repo, "true", "false") + os.Remove(repo + "/lab.toml") + + cmd := exec.Command(labBinaryPath, "mr", "show", "1") + cmd.Dir = repo + + b, err := cmd.CombinedOutput() + if err != nil { + t.Log(string(b)) + t.Error(err) + } + + out := string(b) + out = stripansi.Strip(out) + + os.Remove("/home/travis/.config/lab/lab.toml") + // .config set to true and .git set to false, comments should not be + // output + require.NotContains(t, string(b), `commented at`) +} + +func Test_config_gitConfig_TT(t *testing.T) { + repo := copyTestRepo(t) + + setConfigValues(repo, "true", "true") + os.Remove(repo + "/lab.toml") + + cmd := exec.Command(labBinaryPath, "mr", "show", "1") + cmd.Dir = repo + + b, err := cmd.CombinedOutput() + if err != nil { + t.Log(string(b)) + t.Error(err) + } + + out := string(b) + out = stripansi.Strip(out) + + os.Remove("/home/travis/.config/lab/lab.toml") + // both configs set to true, comments should be output + require.Contains(t, string(b), `commented at`) +} + +// Some flag and config tests do not have to be run. +// flag not set, config true == comments +// This case is handled by Test_config_gitConfig_TT +// flag not set, config false == no comments +// This case is handled by Test_config_gitConfig_FF +// flag not set, config not set == no comments +// flag set, config not set == comments +// These case are handled in cmd/mr_show_test.go + +// flag set, config true == comments +func Test_flag_config_TT(t *testing.T) { + repo := copyTestRepo(t) + + setConfigValues(repo, "true", "true") + os.Remove(repo + "/lab.toml") + + cmd := exec.Command(labBinaryPath, "mr", "show", "1", "--comments") + cmd.Dir = repo + + b, err := cmd.CombinedOutput() + if err != nil { + t.Log(string(b)) + t.Error(err) + } + + out := string(b) + out = stripansi.Strip(out) + + os.Remove("/home/travis/.config/lab/lab.toml") + // both configs set to true, comments should be output + require.Contains(t, string(b), `commented at`) +} + +// flag set, config false == comments +func Test_flag_config_TF(t *testing.T) { + repo := copyTestRepo(t) + + setConfigValues(repo, "false", "false") + os.Remove(repo + "/lab.toml") + + cmd := exec.Command(labBinaryPath, "mr", "show", "1", "--comments") + cmd.Dir = repo + + b, err := cmd.CombinedOutput() + if err != nil { + t.Log(string(b)) + t.Error(err) + } + + out := string(b) + out = stripansi.Strip(out) + + os.Remove("/home/travis/.config/lab/lab.toml") + // both configs set to true, comments should be output + require.Contains(t, string(b), `commented at`) +}