Skip to content

Commit

Permalink
Issue list search (#242)
Browse files Browse the repository at this point in the history
* add --search flag to lab issue list

* refactor parseArgs, parseArgsStr; add parseArgsStringInt, parseArgsRemoteInt, parseArgsRemoteString

* remove --search, use positional arg for search terms instead (close 208)

* issue search: add examples and fix godoc comment
  • Loading branch information
claytonrcarter authored and zaquestion committed Nov 15, 2018
1 parent 64ce4cf commit 9ba0548
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 5 deletions.
23 changes: 18 additions & 5 deletions cmd/issue_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,22 @@ import (
var (
issueLabels []string
issueState string
issueSearch string
issueNumRet int
issueAll bool
)

var issueListCmd = &cobra.Command{
Use: "list [remote]",
Aliases: []string{"ls"},
Use: "list [remote] [search]",
Aliases: []string{"ls", "search"},
Short: "List issues",
Long: ``,
Example: `lab issue list # list all open issues
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"`,
Run: func(cmd *cobra.Command, args []string) {
rn, _, err := parseArgs(args)
rn, issueSearch, err := parseArgsRemoteString(args)
if err != nil {
log.Fatal(err)
}
Expand All @@ -35,6 +40,11 @@ var issueListCmd = &cobra.Command{
State: &issueState,
OrderBy: gitlab.String("updated_at"),
}

if issueSearch != "" {
opts.Search = &issueSearch
}

num := issueNumRet
if issueAll {
num = -1
Expand All @@ -51,13 +61,16 @@ var issueListCmd = &cobra.Command{

func init() {
issueListCmd.Flags().StringSliceVarP(
&issueLabels, "label", "l", []string{}, "Filter issues by label")
&issueLabels, "label", "l", []string{},
"Filter issues by label")
issueListCmd.Flags().StringVarP(
&issueState, "state", "s", "opened",
"Filter issues by state (opened/closed)")
issueListCmd.Flags().IntVarP(
&issueNumRet, "number", "n", 10,
"Number of issues to return")
issueListCmd.Flags().BoolVarP(&issueAll, "all", "a", false, "List all issues on the project")
issueListCmd.Flags().BoolVarP(
&issueAll, "all", "a", false,
"List all issues on the project")
issueCmd.AddCommand(issueListCmd)
}
17 changes: 17 additions & 0 deletions cmd/issue_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,20 @@ func Test_issueListStateClosed(t *testing.T) {
t.Log(issues)
require.Contains(t, issues, "#4 test closed issue")
}

func Test_issueListSearch(t *testing.T) {
t.Parallel()
repo := copyTestRepo(t)
cmd := exec.Command("../lab_bin", "issue", "list", "filter labels")
cmd.Dir = repo

b, err := cmd.CombinedOutput()
if err != nil {
t.Fatal(err)
}

issues := strings.Split(string(b), "\n")
t.Log(issues)
require.Contains(t, issues, "#3 test filter labels 1")
require.NotContains(t, issues, "#1 test issue for lab list")
}
53 changes: 53 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ func init() {
// parseArgsStr returns a string and a number if parsed. Many commands accept a
// string to operate on (remote or search) and number such as a page id
func parseArgsStr(args []string) (string, int64, error) {
return parseArgsStringInt(args)
}

// parseArgsStringInt returns a string and a number if parsed.
func parseArgsStringInt(args []string) (string, int64, error) {
if len(args) == 2 {
n, err := strconv.ParseInt(args[1], 0, 64)
if err != nil {
Expand All @@ -127,7 +132,14 @@ func parseArgsStr(args []string) (string, int64, error) {
return "", 0, nil
}

// parseArgs returns a remote name and a number if parsed
func parseArgs(args []string) (string, int64, error) {
return parseArgsRemoteInt(args)
}

// parseArgsRemoteInt is similar to parseArgsStringInt except that it uses the
// string argument as a remote and returns the project name for that remote
func parseArgsRemoteInt(args []string) (string, int64, error) {
if !git.InsideGitRepo() {
return "", 0, nil
}
Expand Down Expand Up @@ -156,6 +168,47 @@ func parseArgs(args []string) (string, int64, error) {
return rn, num, nil
}

// parseArgsRemoteString returns a remote name and a string if parsed.
// If there is an error, it returns two empty strings.
// If no remote is given, it returns the project name of the default remote
// (ie 'origin').
// If no second argument is given, it returns "" as second return value.
func parseArgsRemoteString(args []string) (string, string, error) {
if !git.InsideGitRepo() {
return "", "", nil
}

remote, str := forkedFromRemote, ""

if len(args) == 1 {
ok, err := git.IsRemote(args[0])
if err != nil {
return "", "", err
}
if ok {
remote = args[0]
} else {
str = args[0]
}
} else if len(args) > 1 {
remote, str = args[0], args[1]
}

ok, err := git.IsRemote(remote)
if err != nil {
return "", "", err
}
if !ok {
return "", "", errors.Errorf("%s is not a valid remote", remote)
}

remote, err = git.PathWithNameSpace(remote)
if err != nil {
return "", "", err
}
return remote, str, nil
}

var (
// Will be updated to upstream in Execute() if "upstream" remote exists
forkedFromRemote = "origin"
Expand Down
65 changes: 65 additions & 0 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,68 @@ func Test_parseArgs(t *testing.T) {
})
}
}

func Test_parseArgsRemoteString(t *testing.T) {
tests := []struct {
Name string
Args []string
ExpectedRemote string
ExpectedString string
ExpectedErr string
}{
{
Name: "No Args",
Args: nil,
ExpectedRemote: "zaquestion/test",
ExpectedString: "",
ExpectedErr: "",
},
{
Name: "1 arg remote",
Args: []string{"lab-testing"},
ExpectedRemote: "lab-testing/test",
ExpectedString: "",
ExpectedErr: "",
},
{
Name: "1 arg non remote",
Args: []string{"foo123"},
ExpectedRemote: "zaquestion/test",
ExpectedString: "foo123",
ExpectedErr: "",
},
{
Name: "1 arg page",
Args: []string{"100"},
ExpectedRemote: "zaquestion/test",
ExpectedString: "100",
ExpectedErr: "",
},
{
Name: "2 arg remote and string",
Args: []string{"origin", "foo123"},
ExpectedRemote: "zaquestion/test",
ExpectedString: "foo123",
ExpectedErr: "",
},
{
Name: "2 arg invalid remote and string",
Args: []string{"foo", "string123"},
ExpectedRemote: "",
ExpectedString: "",
ExpectedErr: "foo is not a valid remote",
},
}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
test := test
t.Parallel()
r, s, err := parseArgsRemoteString(test.Args)
if err != nil {
assert.EqualError(t, err, test.ExpectedErr)
}
assert.Equal(t, test.ExpectedRemote, r)
assert.Equal(t, test.ExpectedString, s)
})
}
}

0 comments on commit 9ba0548

Please sign in to comment.