Skip to content

Commit ee4320b

Browse files
authored
Merge pull request #499 from cesanta/cat
Check in the tool to list repos in an org
2 parents 8a111af + 9d55059 commit ee4320b

File tree

2 files changed

+149
-0
lines changed

2 files changed

+149
-0
lines changed

tools/github_api.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright (c) 2014-2018 Cesanta Software Limited
4+
# All rights reserved
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the ""License"");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an ""AS IS"" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
18+
import json
19+
20+
import requests # apt-get install python3-requests || pip3 install requests
21+
22+
# call_api: Calls github API with the provided args. {{{
23+
#
24+
# url is an url like "https://api.github.com/repos/foo/bar/releases".
25+
#
26+
# params is a dictionary with query string params.
27+
# json_data, if not None, will be encoded as JSON body.
28+
# data, if not None, will be send as a body literally.
29+
# subdomain is "api" by default, but should be set to "uploads" for file uploads.
30+
# headers is a dictionary with headers to send. Independently of that argument,
31+
# authentication header is always sent (with the token we've read above)
32+
# if response is not expected to be a JSON, set decode_json to False; in this
33+
# case, the first returned value is the response returned right from
34+
# requests.request().
35+
def call_api(
36+
token, url,
37+
params = {}, method = "GET", json_data = None,
38+
data = None, headers = {}, decode_json = True
39+
):
40+
41+
if token:
42+
if token.startswith("file:"):
43+
with open(token[5:], "r") as f:
44+
token = f.read().strip()
45+
46+
headers.update({
47+
"Authorization": "token %s" % token,
48+
})
49+
50+
resp = requests.request(
51+
method, url=url, params=params, json=json_data, headers=headers, data=data
52+
)
53+
54+
if decode_json:
55+
resp_data = json.loads(resp.text)
56+
return (resp_data, resp.ok)
57+
else:
58+
return (resp, resp.ok)
59+
# }}}
60+
61+
62+
def CallRefsAPI(
63+
repo_name, token, uri,
64+
subdomain="api",
65+
params={}, method="GET", json_data=None,
66+
data=None, headers={}, decode_json=True):
67+
url = 'https://%s.github.com/repos/%s/git/refs%s' % (subdomain, repo_name, uri)
68+
return call_api(token, url, params=params, method=method, json_data=json_data, data=data, headers=headers, decode_json=decode_json)
69+
70+
# CallReleasesAPI: a wrapper for call_api which constructs the
71+
# releases-related url.
72+
#
73+
# releases_url is an url part after "/repos/<repo_name>/releases".
74+
# Where repo_name consists of two parts: "org/repo".
75+
# releases_url should be either be empty or start with a slash.
76+
# The rest of the arguments are the same as call_api has.
77+
def CallReleasesAPI(
78+
repo_name, token, releases_url,
79+
subdomain = "api",
80+
params = {}, method = "GET", json_data = None,
81+
data = None, headers = {}, decode_json = True
82+
):
83+
url = 'https://%s.github.com/repos/%s/releases%s' % (subdomain, repo_name, releases_url)
84+
return call_api(token, url, params=params, method=method, json_data=json_data, data=data, headers=headers, decode_json=decode_json)
85+
86+
87+
def CallUsersAPI(
88+
org, token, users_url, params = {}, method = "GET", json_data = None, subdomain = "api",
89+
data = None, headers = {}, decode_json = True
90+
):
91+
url = 'https://%s.github.com/users/%s%s' % (subdomain, org, users_url)
92+
return call_api(token, url, params=params, method=method, json_data=json_data, data=data, headers=headers, decode_json=decode_json)
93+
94+
95+
def GetRepos(org, token):
96+
repos = []
97+
page = 1
98+
while True:
99+
# Get repos on the current "page"
100+
r, ok = CallUsersAPI(org, token, "/repos", params={"page": page})
101+
102+
if len(r) == 0:
103+
# No more repos, we're done
104+
break
105+
106+
repos += r
107+
page += 1
108+
109+
return repos
110+
111+

tools/list_repos.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright (c) 2014-2019 Cesanta Software Limited
4+
# All rights reserved
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the ""License"");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an ""AS IS"" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
18+
import argparse
19+
20+
import github_api
21+
22+
parser = argparse.ArgumentParser(description="")
23+
parser.add_argument("--org", required=True)
24+
25+
args = parser.parse_args()
26+
27+
repos = github_api.GetRepos(args.org, None)
28+
29+
for r in sorted(repos, key=lambda e: e["name"]):
30+
dp, l = [], 0
31+
for p in (r["description"] or "").split():
32+
if l + len(p) >= 90:
33+
dp.append("...")
34+
break
35+
l += len(p)
36+
dp.append(p)
37+
descr = " ".join(dp)
38+
print("| [%s](%s) | %s |" % (r["name"], r["html_url"], descr))

0 commit comments

Comments
 (0)