Avoid having to first query for username in repo list
Dynamically construct the GraphQL query by using the `viewer` connection if the owner isn't set and the `repositoryOwner(login:"...")` connection if the owner was set.
This commit is contained in:
parent
4da02614ed
commit
1fa763f514
4 changed files with 42 additions and 48 deletions
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"data": {
|
||||
"repositoryOwner": {
|
||||
"login": "octocat",
|
||||
"repositories": {
|
||||
"totalCount": 3,
|
||||
"nodes": [
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package list
|
|||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
|
@ -39,31 +40,18 @@ func (r Repository) Info() string {
|
|||
}
|
||||
|
||||
type RepositoryList struct {
|
||||
Owner string
|
||||
Repositories []Repository
|
||||
TotalCount int
|
||||
}
|
||||
|
||||
func listRepos(client *http.Client, hostname string, limit int, owner string, filter FilterOptions) (*RepositoryList, error) {
|
||||
type query struct {
|
||||
RepositoryOwner struct {
|
||||
Repositories struct {
|
||||
Nodes []Repository
|
||||
TotalCount int
|
||||
PageInfo struct {
|
||||
HasNextPage bool
|
||||
EndCursor string
|
||||
}
|
||||
} `graphql:"repositories(first: $perPage, after: $endCursor, privacy: $privacy, isFork: $fork, ownerAffiliations: OWNER, orderBy: { field: PUSHED_AT, direction: DESC })"`
|
||||
} `graphql:"repositoryOwner(login: $owner)"`
|
||||
}
|
||||
|
||||
perPage := limit
|
||||
if perPage > 100 {
|
||||
perPage = 100
|
||||
}
|
||||
|
||||
variables := map[string]interface{}{
|
||||
"owner": githubv4.String(owner),
|
||||
"perPage": githubv4.Int(perPage),
|
||||
"endCursor": (*githubv4.String)(nil),
|
||||
}
|
||||
|
|
@ -82,28 +70,58 @@ func listRepos(client *http.Client, hostname string, limit int, owner string, fi
|
|||
variables["fork"] = (*githubv4.Boolean)(nil)
|
||||
}
|
||||
|
||||
var ownerConnection string
|
||||
if owner == "" {
|
||||
ownerConnection = `graphql:"repositoryOwner: viewer"`
|
||||
} else {
|
||||
ownerConnection = `graphql:"repositoryOwner(login: $owner)"`
|
||||
variables["owner"] = githubv4.String(owner)
|
||||
}
|
||||
|
||||
type repositoryOwner struct {
|
||||
Login string
|
||||
Repositories struct {
|
||||
Nodes []Repository
|
||||
TotalCount int
|
||||
PageInfo struct {
|
||||
HasNextPage bool
|
||||
EndCursor string
|
||||
}
|
||||
} `graphql:"repositories(first: $perPage, after: $endCursor, privacy: $privacy, isFork: $fork, ownerAffiliations: OWNER, orderBy: { field: PUSHED_AT, direction: DESC })"`
|
||||
}
|
||||
query := reflect.StructOf([]reflect.StructField{
|
||||
{
|
||||
Name: "RepositoryOwner",
|
||||
Type: reflect.TypeOf(repositoryOwner{}),
|
||||
Tag: reflect.StructTag(ownerConnection),
|
||||
},
|
||||
})
|
||||
|
||||
listResult := RepositoryList{}
|
||||
pagination:
|
||||
for {
|
||||
var result query
|
||||
result := reflect.New(query)
|
||||
gql := graphql.NewClient(ghinstance.GraphQLEndpoint(hostname), client)
|
||||
err := gql.QueryNamed(context.Background(), "RepositoryList", &result, variables)
|
||||
err := gql.QueryNamed(context.Background(), "RepositoryList", result.Interface(), variables)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listResult.TotalCount = result.RepositoryOwner.Repositories.TotalCount
|
||||
for _, repo := range result.RepositoryOwner.Repositories.Nodes {
|
||||
owner := result.Elem().FieldByName("RepositoryOwner").Interface().(repositoryOwner)
|
||||
listResult.TotalCount = owner.Repositories.TotalCount
|
||||
listResult.Owner = owner.Login
|
||||
|
||||
for _, repo := range owner.Repositories.Nodes {
|
||||
listResult.Repositories = append(listResult.Repositories, repo)
|
||||
if len(listResult.Repositories) >= limit {
|
||||
break pagination
|
||||
}
|
||||
}
|
||||
|
||||
if !result.RepositoryOwner.Repositories.PageInfo.HasNextPage {
|
||||
if !owner.Repositories.PageInfo.HasNextPage {
|
||||
break
|
||||
}
|
||||
variables["endCursor"] = githubv4.String(result.RepositoryOwner.Repositories.PageInfo.EndCursor)
|
||||
variables["endCursor"] = githubv4.String(owner.Repositories.PageInfo.EndCursor)
|
||||
}
|
||||
|
||||
return &listResult, nil
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/cli/cli/api"
|
||||
"github.com/cli/cli/internal/ghinstance"
|
||||
"github.com/cli/cli/pkg/cmdutil"
|
||||
"github.com/cli/cli/pkg/iostreams"
|
||||
|
|
@ -94,25 +93,13 @@ func listRun(opts *ListOptions) error {
|
|||
return err
|
||||
}
|
||||
|
||||
apiClient := api.NewClientFromHTTP(httpClient)
|
||||
|
||||
isTerminal := opts.IO.IsStdoutTTY()
|
||||
|
||||
owner := opts.Owner
|
||||
if owner == "" {
|
||||
owner, err = api.CurrentLoginName(apiClient, ghinstance.OverridableDefault())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
filter := FilterOptions{
|
||||
Visibility: opts.Visibility,
|
||||
Fork: opts.Fork,
|
||||
Source: opts.Source,
|
||||
}
|
||||
|
||||
listResult, err := listRepos(httpClient, ghinstance.OverridableDefault(), opts.Limit, owner, filter)
|
||||
listResult, err := listRepos(httpClient, ghinstance.OverridableDefault(), opts.Limit, opts.Owner, filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -139,9 +126,9 @@ func listRun(opts *ListOptions) error {
|
|||
tp.EndRow()
|
||||
}
|
||||
|
||||
if isTerminal {
|
||||
if opts.IO.IsStdoutTTY() {
|
||||
hasFilters := filter.Visibility != "" || filter.Fork || filter.Source
|
||||
title := listHeader(owner, len(listResult.Repositories), listResult.TotalCount, hasFilters)
|
||||
title := listHeader(listResult.Owner, len(listResult.Repositories), listResult.TotalCount, hasFilters)
|
||||
fmt.Fprintf(opts.IO.Out, "\n%s\n\n", title)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,10 +57,6 @@ func TestRepoList_nontty(t *testing.T) {
|
|||
httpReg := &httpmock.Registry{}
|
||||
defer httpReg.Verify(t)
|
||||
|
||||
httpReg.Register(
|
||||
httpmock.GraphQL(`query UserCurrent\b`),
|
||||
httpmock.StringResponse(`{"data":{"viewer":{"login":"octocat"}}}`),
|
||||
)
|
||||
httpReg.Register(
|
||||
httpmock.GraphQL(`query RepositoryList\b`),
|
||||
httpmock.FileResponse("./fixtures/repoList.json"),
|
||||
|
|
@ -99,10 +95,6 @@ func TestRepoList_tty(t *testing.T) {
|
|||
httpReg := &httpmock.Registry{}
|
||||
defer httpReg.Verify(t)
|
||||
|
||||
httpReg.Register(
|
||||
httpmock.GraphQL(`query UserCurrent\b`),
|
||||
httpmock.StringResponse(`{"data":{"viewer":{"login":"octocat"}}}`),
|
||||
)
|
||||
httpReg.Register(
|
||||
httpmock.GraphQL(`query RepositoryList\b`),
|
||||
httpmock.FileResponse("./fixtures/repoList.json"),
|
||||
|
|
@ -139,10 +131,6 @@ func TestRepoList_filtering(t *testing.T) {
|
|||
http := &httpmock.Registry{}
|
||||
defer http.Verify(t)
|
||||
|
||||
http.Register(
|
||||
httpmock.GraphQL(`query UserCurrent\b`),
|
||||
httpmock.StringResponse(`{"data":{"viewer":{"login":"octocat"}}}`),
|
||||
)
|
||||
http.Register(
|
||||
httpmock.GraphQL(`query RepositoryList\b`),
|
||||
httpmock.GraphQLQuery(`{}`, func(_ string, params map[string]interface{}) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue