Skip to content

Commit

Permalink
feat: 修改获取repo列表为请求为graphql
Browse files Browse the repository at this point in the history
  • Loading branch information
TBXark committed Dec 7, 2024
1 parent 2ef71ca commit 693c3a1
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 78 deletions.
4 changes: 2 additions & 2 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (f *FileBackup) MigrateRepo(owner, repoOwner string, isOwnerOrg, isRepoOwne
DefaultBranch string `json:"default_branch"`
UpdateAt string `json:"updated_at"`
}
err := GithubRequestJson("GET", url, githubToken, &info)
err := GithubRequestJson("GET", url, githubToken, nil, &info)
if err != nil {
return "", err
}
Expand Down Expand Up @@ -93,7 +93,7 @@ func (f *FileBackup) MigrateRepo(owner, repoOwner string, isOwnerOrg, isRepoOwne
return "", wErr
}
} else {
dErr := GithubRequest("GET", url, githubToken, func(resp *http.Response) error {
dErr := GithubRequest("GET", url, githubToken, nil, func(resp *http.Response) error {
tarFile, wErr := os.Create(filePath)
if wErr != nil {
return wErr
Expand Down
144 changes: 68 additions & 76 deletions github.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
package main

import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
)

type Repo struct {
Name string `json:"name"`
Description string `json:"description"`
Private bool `json:"private"`
Fork bool `json:"fork"`
Archived bool `json:"archived"`
Private bool `json:"isPrivate"`
Fork bool `json:"isFork"`
Archived bool `json:"isArchived"`
Owner struct {
Login string `json:"login"`
}
Expand All @@ -26,99 +27,90 @@ func NewGithub(token string) *Github {
return &Github{Token: token}
}

func filterRepos(owner string, res []Repo) map[string]Repo {
matchedRepos := make(map[string]Repo)
ownerLower := strings.ToLower(owner)
for _, repo := range res {
if strings.ToLower(repo.Owner.Login) != ownerLower {
continue
}
matchedRepos[repo.Name] = repo
}
return matchedRepos
func (g *Github) LoadAllRepos(owner string, isOrg bool) ([]Repo, error) {
tmpl := `
query {
%s {
repositories(
first: 100,
after: %s
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
name
description
isPrivate
isFork
isArchived
owner {
login
}
}
}
}
}

func (g *Github) loadReposPageBySearch(owner string, perPage, page int, isOrg bool) (map[string]Repo, error) {
url := "search/repositories"
`
next := "null"
queryType := ""
dataKey := ""
var repos []Repo
if isOrg {
url = fmt.Sprintf("%s?q=org%s&page=%d&per_page=%d", url, "%3A"+owner, page, perPage)
dataKey = "organization"
queryType = fmt.Sprintf("organization(login: \"%s\")", owner)
} else {
url = fmt.Sprintf("%s?q=user%s&page=%d&per_page=%d", url, "%3A"+owner, page, perPage)
}
var res struct {
Items []Repo `json:"items"`
}
err := GithubRequestJson("GET", url, g.Token, &res)
if err != nil {
return nil, err
}
return filterRepos(owner, res.Items), nil

}

func (g *Github) loadReposPage(owner string, perPage, page int, isOrg bool) (map[string]Repo, error) {
url := fmt.Sprintf("users/%s/repos", owner)
if isOrg {
url = fmt.Sprintf("orgs/%s/repos", owner)
}
url = fmt.Sprintf("%s?per_page=%d&page=%d&type=all", url, perPage, page)
var res []Repo
err := GithubRequestJson("GET", url, g.Token, &res)
if err != nil {
return nil, err
dataKey = "repositoryOwner"
queryType = fmt.Sprintf("repositoryOwner(login: \"%s\")", owner)
}
return filterRepos(owner, res), nil
}

func (g *Github) LoadAllRepos(owner string, isOrg bool) ([]Repo, error) {
page := 1
perPage := 100
res := make(map[string]Repo)
for {
repos, err := g.loadReposPageBySearch(owner, perPage, page, isOrg)
var data struct {
Data map[string]struct {
Repositories struct {
PageInfo struct {
HasNextPage bool `json:"hasNextPage"`
EndCursor string `json:"endCursor"`
} `json:"pageInfo"`
Nodes []Repo `json:"nodes"`
} `json:"repositories"`
} `json:"data"`
}
query := fmt.Sprintf(tmpl, queryType, next)
rawBody, err := json.Marshal(map[string]any{"query": query})
if err != nil {
return nil, err
}
if len(repos) == 0 {
break
}
for k, v := range repos {
res[k] = v
}
page++
}
page = 1
for {
repos, err := g.loadReposPage(owner, perPage, page, isOrg)
err = GithubRequestJson("POST", "graphql", g.Token, bytes.NewReader(rawBody), &data)
if err != nil {
return nil, err
}
if len(repos) == 0 {
break
info, ok := data.Data[dataKey]
if !ok {
return nil, fmt.Errorf("no data key %s", dataKey)
}
for k, v := range repos {
res[k] = v
for _, repo := range info.Repositories.Nodes {
if repo.Owner.Login == owner {
repos = append(repos, repo)
}
}
page++
}
var resSlice []Repo
for _, v := range res {
resSlice = append(resSlice, v)
if !info.Repositories.PageInfo.HasNextPage {
break
}
next = fmt.Sprintf(`"%s"`, info.Repositories.PageInfo.EndCursor)
}
return resSlice, nil
return repos, nil
}

func GithubRequest(method, path, token string, handler func(*http.Response) error) error {
func GithubRequest(method, path, token string, body io.Reader, handler func(*http.Response) error) error {
url := fmt.Sprintf("https://api.github.com/%s", path)
req, err := http.NewRequest(method, url, nil)
req, err := http.NewRequest(method, url, body)
if err != nil {
return err
}
if token != "" {
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
}
req.Header.Add("Accept", "application/vnd.github.v3+json")
req.Header.Add("X-GitHub-Api-Version", "2022-11-28")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
Expand All @@ -130,8 +122,8 @@ func GithubRequest(method, path, token string, handler func(*http.Response) erro
return handler(resp)
}

func GithubRequestJson[T any](method, path, token string, res *T) error {
return GithubRequest(method, path, token, func(resp *http.Response) error {
func GithubRequestJson[T any](method, path, token string, body io.Reader, res *T) error {
return GithubRequest(method, path, token, body, func(resp *http.Response) error {
return json.NewDecoder(resp.Body).Decode(res)
})
}
27 changes: 27 additions & 0 deletions github_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package main

import (
"os"
"testing"
)

func TestGithub_LoadAllRepos(t *testing.T) {
github := NewGithub(os.Getenv("GITHUB_TOKEN"))
repos, err := github.LoadAllRepos("TBXark", false)
if err != nil {
t.Fatal(err)
}
t.Logf("repos count: %d", len(repos))
for _, repo := range repos {
t.Log(repo.Name)
}

repos, err = github.LoadAllRepos("tbxark-arc", true)
if err != nil {
t.Fatal(err)
}
t.Logf("repos count: %d", len(repos))
for _, repo := range repos {
t.Log(repo.Name)
}
}

0 comments on commit 693c3a1

Please sign in to comment.