Created
February 27, 2020 02:51
-
-
Save k-takata/6c90f977abfe0dc6ee0970ea3379c1f1 to your computer and use it in GitHub Desktop.
Download the latest silver searcher Win32 from the GitHub releases
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# Download the latest silver searcher Win32 from the GitHub releases | |
import argparse | |
import calendar | |
import io | |
import json | |
import os | |
import sys | |
import time | |
import urllib.request, urllib.error | |
# Repository Name | |
repo_name = 'k-takata/the_silver_searcher-win32' | |
gh_releases_url = 'https://api.github.com/repos/' + repo_name + '/releases' | |
# Asset name checker | |
def does_skip_asset(asset): | |
return asset['name'].find('debug') >= 0 | |
# Arguments properties | |
arg_desc = 'Download the latest silver searcher Win32 from the GitHub releases' | |
arg_archs = ['all', 'x86', 'x64'] | |
arg_default_arch = 'all' | |
arg_allow_prerelease = True | |
# Parse arguments | |
def parse_args(): | |
global parser | |
parser = argparse.ArgumentParser(description=arg_desc) | |
parser.add_argument('-c', '--check', action='store_true', | |
help='only check the information of the latest release') | |
parser.add_argument('--noprogress', action='store_true', | |
help="Don't show the progress") | |
parser.add_argument('-f', '--force', action='store_true', | |
help='overwrite the download file') | |
parser.add_argument('-n', '--filename', type=str, action='store', | |
help='filename to save') | |
parser.add_argument('-p', '--prerelease', action='store_true', | |
default=arg_allow_prerelease, | |
help='Allow downloading prerelease') | |
parser.add_argument('-a', '--arch', type=str, action='store', | |
choices=arg_archs, default=arg_default_arch, | |
help='architecture to download') | |
parser.add_argument('--auth', type=str, action='store', | |
default=os.getenv('AUTH_TOKEN'), | |
metavar="TOKEN", help='GitHub API token (Environment variable AUTH_TOKEN can be also used.)') | |
return parser.parse_args() | |
# Get information of GitHub release | |
# see: https://developer.github.com/v3/repos/releases/ | |
def get_rel_info(url, auth): | |
if auth: | |
# Unauthenticated requests are limited up to 60 requests per hour. | |
# Authenticated requests are allowed up to 5,000 requests per hour. | |
# See: https://developer.github.com/v3/#rate-limiting | |
request = urllib.request.Request(url) | |
request.add_header("Authorization", "token " + auth) | |
else: | |
request = url | |
try: | |
response = urllib.request.urlopen(request) | |
except urllib.error.HTTPError as err: | |
print('GitHub release not found. (%s)' % err.reason, file=sys.stderr) | |
exit(1) | |
return json.load(io.StringIO(str(response.read(), 'utf-8'))) | |
# Show progress | |
def reporthook(count, blocksize, totalsize): | |
size = count * blocksize | |
if totalsize <= 0: | |
print("\r{:,}".format(size)) | |
else: | |
size = min(size, totalsize) | |
print("\r{:,} / {:,} ({:.1%})".format(size, totalsize, size / totalsize), end='') | |
# Download the files | |
def download(args, rel_info): | |
for asset in rel_info['assets']: | |
if args.filename: | |
name = args.filename | |
else: | |
name = asset['name'] | |
if does_skip_asset(asset): | |
continue | |
if args.arch != 'all' and asset['name'].find(args.arch) < 0: | |
continue | |
if os.path.isfile(name) and not args.force: | |
print('File exists:', name) | |
continue | |
print('Downloading from:', asset['browser_download_url']) | |
print('Downloading to:', name) | |
if args.noprogress: | |
hook = None | |
else: | |
hook = reporthook | |
urllib.request.urlretrieve(asset['browser_download_url'], name, hook) | |
# Set timestamp | |
asset_time = time.strptime(asset['updated_at'], '%Y-%m-%dT%H:%M:%SZ') | |
os.utime(name, times=(time.time(), calendar.timegm(asset_time))) | |
if not args.noprogress: | |
print() | |
def main(): | |
args = parse_args() | |
if args.filename and args.arch == 'all': | |
parser.error('-a must be specified when you specify -n.') | |
if args.prerelease: | |
rels_info = get_rel_info(gh_releases_url, args.auth) | |
for rel in rels_info: | |
if rel['draft']: | |
continue | |
gh_release_url = rel['url'] | |
break | |
else: | |
print('GitHub release not found.', file=sys.stderr) | |
exit(1) | |
else: | |
gh_release_url = gh_releases_url + '/latest' | |
rel_info = get_rel_info(gh_release_url, args.auth) | |
print('Last release:', rel_info['name']) | |
print('Created at:', rel_info['created_at']) | |
if args.check: | |
exit(0) | |
download(args, rel_info) | |
exit(0) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment