#!/usr/bin/python3 # Download the latest KaoriYa Vim 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 = 'koron/vim-kaoriya' gh_releases_url = 'https://api.github.com/repos/' + repo_name + '/releases' # Asset name checker def does_skip_asset(asset): return asset['name'].find('pdb') >= 0 # Arguments properties arg_desc = 'Download the latest KaoriYa Vim from the GitHub releases' arg_archs = ['all', 'win32', 'win64'] arg_default_arch = 'all' arg_allow_prerelease = False # 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()