-
Notifications
You must be signed in to change notification settings - Fork 3
/
repos.go
151 lines (134 loc) · 4.12 KB
/
repos.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package main
import (
"context"
"log/slog"
"strings"
github "github.com/google/go-github/v58/github"
"github.com/spf13/viper"
)
func GetRepo(client *github.Client, repo string) (*github.Repository, error) {
ctx := context.Background()
parts := strings.Split(repo, "/")
theRepo, _, err := client.Repositories.Get(ctx, parts[0], parts[1])
return theRepo, err
}
func GetRepos(client *github.Client, owners []string) ([]*github.Repository, error) {
var allRepos []*github.Repository
if viper.GetBool("public") {
repos, err := getPublicRepos(client, owners)
if err != nil {
return nil, err
}
allRepos = append(allRepos, repos...)
}
if viper.GetBool("private") {
repos, err := getPrivateRepos(client, owners)
if err != nil {
return nil, err
}
allRepos = append(allRepos, repos...)
}
forks := viper.GetBool("forks")
archived := viper.GetBool("archived")
var filteredRepos []*github.Repository
for _, repo := range allRepos {
if !forks && *repo.Fork {
slog.Debug("skipping forked repo", "repo", *repo.FullName)
continue
}
if !archived && *repo.Archived {
slog.Debug("skipping archived repo", "repo", *repo.FullName)
continue
}
filteredRepos = append(filteredRepos, repo)
}
return filteredRepos, nil
}
func getPublicRepos(client *github.Client, owners []string) ([]*github.Repository, error) {
var allRepos []*github.Repository
for _, owner := range owners {
repos, err := getPublicReposForOwner(client, owner)
if err != nil {
return nil, err
}
allRepos = append(allRepos, repos...)
}
slog.Debug("total public repos", "count", len(allRepos))
return allRepos, nil
}
func getPublicReposForOwner(client *github.Client, owner string) ([]*github.Repository, error) {
listOptions := github.ListOptions{PerPage: 100}
opt := &github.RepositoryListByUserOptions{Type: "all", Sort: "updated", Direction: "desc", ListOptions: listOptions}
ctx := context.Background()
var allRepos []*github.Repository
for {
repos, resp, err := client.Repositories.ListByUser(ctx, owner, opt)
if err != nil {
return nil, err
}
for _, repo := range repos {
// needed since getting a user's repos will return all repos, even if under a different owner.
if !strings.EqualFold(*repo.Owner.Login, owner) {
continue
}
// needed since getting a user's repos will include private repos
if *repo.Private {
continue
}
_, skip := SkipSet[strings.ToLower(*repo.FullName)]
if skip {
slog.Debug("explicitly skipping repo", "repo", *repo.FullName)
continue
}
allRepos = append(allRepos, repo)
}
if resp.NextPage == 0 {
break
}
slog.Debug("paging for public repos", "owner", owner, "page", resp.NextPage)
opt.Page = resp.NextPage
}
slog.Debug("public repos", "owner", owner, "count", len(allRepos))
return allRepos, nil
}
func getPrivateRepos(client *github.Client, owners []string) ([]*github.Repository, error) {
listOptions := github.ListOptions{PerPage: 100}
opt := &github.RepositoryListByAuthenticatedUserOptions{Visibility: "private", Sort: "updated", Direction: "desc", ListOptions: listOptions}
ctx := context.Background()
ownerSet := make(map[string]struct{})
for _, owner := range owners {
ownerSet[strings.ToLower(owner)] = struct{}{}
}
var allRepos []*github.Repository
for {
repos, resp, err := client.Repositories.ListByAuthenticatedUser(ctx, opt)
if err != nil {
return nil, err
}
for _, repo := range repos {
_, ok := ownerSet[strings.ToLower(*repo.Owner.Login)]
if !ok {
// these are private repos you can see, but aren't in the list of owners
slog.Debug("skipping private repo", "repo", *repo.FullName)
continue
}
if !*repo.Private {
slog.Warn("repo marked as public but returned from query", "repo", *repo.FullName)
continue
}
_, skip := SkipSet[strings.ToLower(*repo.FullName)]
if skip {
slog.Debug("explicitly skipping repo", "repo", *repo.FullName)
continue
}
allRepos = append(allRepos, repo)
}
if resp.NextPage == 0 {
break
}
slog.Debug("paging through private repos...")
opt.Page = resp.NextPage
}
slog.Debug("total private repos", "count", len(allRepos))
return allRepos, nil
}