|
16 | 16 | from pprint import pprint |
17 | 17 |
|
18 | 18 | import click |
| 19 | +import link_header |
19 | 20 | import requests |
20 | 21 | from requests import request |
21 | 22 |
|
@@ -145,6 +146,22 @@ def formatPos(_self): |
145 | 146 | return bar |
146 | 147 |
|
147 | 148 |
|
| 149 | +def _recursive_gh_get(href, items): |
| 150 | + """Recursively get list of GitHub objects. |
| 151 | +
|
| 152 | + See https://developer.github.com/v3/guides/traversing-with-pagination/ |
| 153 | + """ |
| 154 | + response = _request('GET', href) |
| 155 | + response.raise_for_status() |
| 156 | + items.extend(response.json()) |
| 157 | + if "link" not in response.headers: |
| 158 | + return |
| 159 | + links = link_header.parse(response.headers["link"]) |
| 160 | + rels = {link.rel: link.href for link in links.links} |
| 161 | + if "next" in rels: |
| 162 | + _recursive_gh_get(rels["next"], items) |
| 163 | + |
| 164 | + |
148 | 165 | @click.group() |
149 | 166 | @click.option("--github-token", envvar='GITHUB_TOKEN', default=None, |
150 | 167 | help="[default: GITHUB_TOKEN env. variable]") |
@@ -227,10 +244,11 @@ def print_release_info(release, title=None, indent=""): |
227 | 244 |
|
228 | 245 |
|
229 | 246 | def get_releases(repo_name, verbose=False): |
230 | | - response = _request( |
231 | | - 'GET', GITHUB_API + '/repos/{0}/releases'.format(repo_name)) |
232 | | - response.raise_for_status() |
233 | | - releases = response.json() |
| 247 | + |
| 248 | + releases = [] |
| 249 | + _recursive_gh_get( |
| 250 | + GITHUB_API + '/repos/{0}/releases'.format(repo_name), releases) |
| 251 | + |
234 | 252 | if verbose: |
235 | 253 | list(map(print_release_info, |
236 | 254 | sorted(releases, key=lambda r: r['tag_name']))) |
@@ -348,14 +366,15 @@ def get_assets(repo_name, tag_name, verbose=False): |
348 | 366 | release = get_release(repo_name, tag_name) |
349 | 367 | if not release: |
350 | 368 | raise Exception('Release with tag_name {0} not found'.format(tag_name)) |
351 | | - response = _request( |
352 | | - 'GET', GITHUB_API + '/repos/{0}/releases/{1}/assets'.format( |
353 | | - repo_name, release["id"])) |
354 | | - response.raise_for_status() |
355 | | - assets = response.json() |
| 369 | + |
| 370 | + assets = [] |
| 371 | + _recursive_gh_get(GITHUB_API + '/repos/{0}/releases/{1}/assets'.format( |
| 372 | + repo_name, release["id"]), assets) |
| 373 | + |
356 | 374 | if verbose: |
357 | 375 | for i, asset in enumerate(sorted(assets, key=lambda r: r['name'])): |
358 | 376 | print_asset_info(i, asset) |
| 377 | + |
359 | 378 | return assets |
360 | 379 |
|
361 | 380 |
|
@@ -870,26 +889,26 @@ def print_ref_info(ref, indent=""): |
870 | 889 |
|
871 | 890 |
|
872 | 891 | def get_refs(repo_name, tags=None, pattern=None): |
873 | | - response = _request( |
874 | | - 'GET', GITHUB_API + '/repos/{0}/git/refs'.format(repo_name)) |
875 | | - response.raise_for_status() |
| 892 | + |
| 893 | + refs = [] |
| 894 | + _recursive_gh_get( |
| 895 | + GITHUB_API + '/repos/{0}/git/refs'.format(repo_name), refs) |
876 | 896 |
|
877 | 897 | # If "tags" is True, keep only "refs/tags/*" |
878 | | - data = response.json() |
| 898 | + data = refs |
879 | 899 | if tags: |
880 | 900 | tag_names = [] |
881 | 901 | data = [] |
882 | | - for ref in response.json(): |
| 902 | + for ref in refs: |
883 | 903 | if ref['ref'].startswith("refs/tags"): |
884 | 904 | data.append(ref) |
885 | 905 | tag_names.append(ref["ref"]) |
886 | 906 |
|
887 | 907 | try: |
888 | | - response = _request( |
889 | | - 'GET', |
890 | | - GITHUB_API + '/repos/{0}/git/refs/tags'.format(repo_name)) |
891 | | - response.raise_for_status() |
892 | | - for ref in response.json(): |
| 908 | + tags = [] |
| 909 | + _recursive_gh_get( |
| 910 | + GITHUB_API + '/repos/{0}/git/refs/tags'.format(repo_name), tags) |
| 911 | + for ref in tags: |
893 | 912 | if ref["ref"] not in tag_names: |
894 | 913 | data.append(ref) |
895 | 914 | except requests.exceptions.HTTPError as exc_info: |
|
0 commit comments