From e27a77fc99fd7e76c93fc45bdf9ad0901a372dec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sat, 27 Feb 2021 17:20:06 +0100 Subject: [PATCH] Add ability to filter by archived in `repo list` Like `--language`, archived filters also use the Search API. --- pkg/cmd/repo/list/http.go | 21 +++-- pkg/cmd/repo/list/http_test.go | 21 +++++ pkg/cmd/repo/list/list.go | 34 +++++--- pkg/cmd/repo/list/list_test.go | 152 ++++++++++++++++++++++----------- 4 files changed, 164 insertions(+), 64 deletions(-) diff --git a/pkg/cmd/repo/list/http.go b/pkg/cmd/repo/list/http.go index 7aefeaf9d..7e2ccecd2 100644 --- a/pkg/cmd/repo/list/http.go +++ b/pkg/cmd/repo/list/http.go @@ -44,17 +44,20 @@ type RepositoryList struct { Owner string Repositories []Repository TotalCount int + FromSearch bool } type FilterOptions struct { - Visibility string // private, public - Fork bool - Source bool - Language string + Visibility string // private, public + Fork bool + Source bool + Language string + Archived bool + NonArchived bool } func listRepos(client *http.Client, hostname string, limit int, owner string, filter FilterOptions) (*RepositoryList, error) { - if filter.Language != "" { + if filter.Language != "" || filter.Archived || filter.NonArchived { return searchRepos(client, hostname, limit, owner, filter) } @@ -165,7 +168,7 @@ func searchRepos(client *http.Client, hostname string, limit int, owner string, } gql := graphql.NewClient(ghinstance.GraphQLEndpoint(hostname), client) - listResult := RepositoryList{} + listResult := RepositoryList{FromSearch: true} pagination: for { var result query @@ -222,5 +225,11 @@ func searchQuery(owner string, filter FilterOptions) string { queryParts = append(queryParts, "is:private") } + if filter.Archived { + queryParts = append(queryParts, "archived:true") + } else if filter.NonArchived { + queryParts = append(queryParts, "archived:false") + } + return strings.Join(queryParts, " ") } diff --git a/pkg/cmd/repo/list/http_test.go b/pkg/cmd/repo/list/http_test.go index 8c6b8d5f4..0544a750b 100644 --- a/pkg/cmd/repo/list/http_test.go +++ b/pkg/cmd/repo/list/http_test.go @@ -52,6 +52,7 @@ func Test_listReposWithLanguage(t *testing.T) { require.NoError(t, err) assert.Equal(t, 3, res.TotalCount) + assert.Equal(t, true, res.FromSearch) assert.Equal(t, "octocat", res.Owner) assert.Equal(t, "octocat/hello-world", res.Repositories[0].NameWithOwner) @@ -130,6 +131,26 @@ func Test_searchQuery(t *testing.T) { }, want: "sort:updated-desc user:@me fork:true language:\"ruby\"", }, + { + name: "only archived", + args: args{ + owner: "", + filter: FilterOptions{ + Archived: true, + }, + }, + want: "sort:updated-desc user:@me fork:true archived:true", + }, + { + name: "only non-archived", + args: args{ + owner: "", + filter: FilterOptions{ + NonArchived: true, + }, + }, + want: "sort:updated-desc user:@me fork:true archived:false", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/cmd/repo/list/list.go b/pkg/cmd/repo/list/list.go index 39b330a04..0b0b5fd5e 100644 --- a/pkg/cmd/repo/list/list.go +++ b/pkg/cmd/repo/list/list.go @@ -20,10 +20,12 @@ type ListOptions struct { Limit int Owner string - Visibility string - Fork bool - Source bool - Language string + Visibility string + Fork bool + Source bool + Language string + Archived bool + NonArchived bool Now func() time.Time } @@ -55,6 +57,9 @@ func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Comman if opts.Source && opts.Fork { return &cmdutil.FlagError{Err: fmt.Errorf("specify only one of `--source` or `--fork`")} } + if opts.Archived && opts.NonArchived { + return &cmdutil.FlagError{Err: fmt.Errorf("specify only one of `--archived` or `--no-archived`")} + } if flagPrivate { opts.Visibility = "private" @@ -79,6 +84,8 @@ func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Comman cmd.Flags().BoolVar(&opts.Source, "source", false, "Show only non-forks") cmd.Flags().BoolVar(&opts.Fork, "fork", false, "Show only forks") cmd.Flags().StringVarP(&opts.Language, "language", "l", "", "Filter by primary coding language") + cmd.Flags().BoolVar(&opts.Archived, "archived", false, "Show only archived repositories") + cmd.Flags().BoolVar(&opts.NonArchived, "no-archived", false, "Omit archived repositories") return cmd } @@ -90,10 +97,12 @@ func listRun(opts *ListOptions) error { } filter := FilterOptions{ - Visibility: opts.Visibility, - Fork: opts.Fork, - Source: opts.Source, - Language: opts.Language, + Visibility: opts.Visibility, + Fork: opts.Fork, + Source: opts.Source, + Language: opts.Language, + Archived: opts.Archived, + NonArchived: opts.NonArchived, } listResult, err := listRepos(httpClient, ghinstance.OverridableDefault(), opts.Limit, opts.Owner, filter) @@ -117,13 +126,18 @@ func listRun(opts *ListOptions) error { infoColor = cs.Yellow } + t := repo.PushedAt + // if listResult.FromSearch { + // t = repo.UpdatedAt + // } + tp.AddField(repo.NameWithOwner, nil, cs.Bold) tp.AddField(text.ReplaceExcessiveWhitespace(repo.Description), nil, nil) tp.AddField(info, nil, infoColor) if tp.IsTTY() { - tp.AddField(utils.FuzzyAgoAbbr(now, repo.PushedAt), nil, cs.Gray) + tp.AddField(utils.FuzzyAgoAbbr(now, t), nil, cs.Gray) } else { - tp.AddField(repo.PushedAt.Format(time.RFC3339), nil, nil) + tp.AddField(t.Format(time.RFC3339), nil, nil) } tp.EndRow() } diff --git a/pkg/cmd/repo/list/list_test.go b/pkg/cmd/repo/list/list_test.go index 86ccdf420..59552beda 100644 --- a/pkg/cmd/repo/list/list_test.go +++ b/pkg/cmd/repo/list/list_test.go @@ -28,96 +28,140 @@ func TestNewCmdList(t *testing.T) { name: "no arguments", cli: "", wants: ListOptions{ - Limit: 30, - Owner: "", - Visibility: "", - Fork: false, - Source: false, - Language: "", + Limit: 30, + Owner: "", + Visibility: "", + Fork: false, + Source: false, + Language: "", + Archived: false, + NonArchived: false, }, }, { name: "with owner", cli: "monalisa", wants: ListOptions{ - Limit: 30, - Owner: "monalisa", - Visibility: "", - Fork: false, - Source: false, - Language: "", + Limit: 30, + Owner: "monalisa", + Visibility: "", + Fork: false, + Source: false, + Language: "", + Archived: false, + NonArchived: false, }, }, { name: "with limit", cli: "-L 101", wants: ListOptions{ - Limit: 101, - Owner: "", - Visibility: "", - Fork: false, - Source: false, - Language: "", + Limit: 101, + Owner: "", + Visibility: "", + Fork: false, + Source: false, + Language: "", + Archived: false, + NonArchived: false, }, }, { name: "only public", cli: "--public", wants: ListOptions{ - Limit: 30, - Owner: "", - Visibility: "public", - Fork: false, - Source: false, - Language: "", + Limit: 30, + Owner: "", + Visibility: "public", + Fork: false, + Source: false, + Language: "", + Archived: false, + NonArchived: false, }, }, { name: "only private", cli: "--private", wants: ListOptions{ - Limit: 30, - Owner: "", - Visibility: "private", - Fork: false, - Source: false, - Language: "", + Limit: 30, + Owner: "", + Visibility: "private", + Fork: false, + Source: false, + Language: "", + Archived: false, + NonArchived: false, }, }, { name: "only forks", cli: "--fork", wants: ListOptions{ - Limit: 30, - Owner: "", - Visibility: "", - Fork: true, - Source: false, - Language: "", + Limit: 30, + Owner: "", + Visibility: "", + Fork: true, + Source: false, + Language: "", + Archived: false, + NonArchived: false, }, }, { name: "only sources", cli: "--source", wants: ListOptions{ - Limit: 30, - Owner: "", - Visibility: "", - Fork: false, - Source: true, - Language: "", + Limit: 30, + Owner: "", + Visibility: "", + Fork: false, + Source: true, + Language: "", + Archived: false, + NonArchived: false, }, }, { name: "with language", cli: "-l go", wants: ListOptions{ - Limit: 30, - Owner: "", - Visibility: "", - Fork: false, - Source: false, - Language: "go", + Limit: 30, + Owner: "", + Visibility: "", + Fork: false, + Source: false, + Language: "go", + Archived: false, + NonArchived: false, + }, + }, + { + name: "only archived", + cli: "--archived", + wants: ListOptions{ + Limit: 30, + Owner: "", + Visibility: "", + Fork: false, + Source: false, + Language: "", + Archived: true, + NonArchived: false, + }, + }, + { + name: "only non-archived", + cli: "--no-archived", + wants: ListOptions{ + Limit: 30, + Owner: "", + Visibility: "", + Fork: false, + Source: false, + Language: "", + Archived: false, + NonArchived: true, }, }, { @@ -130,11 +174,21 @@ func TestNewCmdList(t *testing.T) { cli: "--fork --source", wantsErr: "specify only one of `--source` or `--fork`", }, + { + name: "conflicting archived", + cli: "--archived --no-archived", + wantsErr: "specify only one of `--archived` or `--no-archived`", + }, { name: "too many arguments", cli: "monalisa hubot", wantsErr: "accepts at most 1 arg(s), received 2", }, + { + name: "invalid limit", + cli: "-L 0", + wantsErr: "invalid limit: 0", + }, } for _, tt := range tests { @@ -166,6 +220,8 @@ func TestNewCmdList(t *testing.T) { assert.Equal(t, tt.wants.Visibility, gotOpts.Visibility) assert.Equal(t, tt.wants.Fork, gotOpts.Fork) assert.Equal(t, tt.wants.Source, gotOpts.Source) + assert.Equal(t, tt.wants.Archived, gotOpts.Archived) + assert.Equal(t, tt.wants.NonArchived, gotOpts.NonArchived) }) } }