diff --git a/scripts/get_clang_format.py b/scripts/get_clang_format.py new file mode 100755 index 00000000000..8e96a3e6598 --- /dev/null +++ b/scripts/get_clang_format.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python + +"""Downloads the clang-format binary appropriate for the host platform.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import argparse +import os +import platform +import sys +import urllib.request +import urllib.error + + +def report_download_progress(chunk_number, chunk_size, file_size): + """Pretty printer for file download progress.""" + if file_size != -1: + percent = min(1, (chunk_number * chunk_size) / file_size) + bar = "#" * int(64 * percent) + sys.stdout.write("\r0% |{:<64}| {}%".format(bar, int(percent * 100))) + + +def download_clang_format(path): + """Downloads a clang-format binary appropriate for the host platform and stores it at the given location.""" + # This dictionary maps each platform to the S3 object URL for its clang-format binary. + PLATFORM_TO_URL = { + "Darwin": "https://oss-clang-format.s3.us-east-2.amazonaws.com/mac/clang-format-mojave", + "Linux": "https://oss-clang-format.s3.us-east-2.amazonaws.com/linux64/clang-format-linux64", + } + + plat = platform.system() + + if plat not in PLATFORM_TO_URL: + print("Unsupported platform: {}".format(plat)) + return False + + cf_url = PLATFORM_TO_URL[plat] + filename = "{}{}clang-format".format(path, os.sep) + + # Try to download clang-format. + try: + urllib.request.urlretrieve( + cf_url, filename, reporthook=report_download_progress + ) + except urllib.error.URLError as e: + print("Error downloading {}: {}".format(filename, str(e))) + return False + finally: + print() + + return True + + +def parse_args(args): + """Parse and return command-line arguments.""" + parser = argparse.ArgumentParser( + description="Install a platform-appropriate clang-format binary for use during PyTorch development." + ) + parser.add_argument( + "--path", required=True, help="Path where clang-format should be stored" + ) + + return parser.parse_args(args) + + +def sanitize_path(path): + """Sanitize a given path by expanding ~ and converting a relative path to an absolute path.""" + expand_user = os.path.expanduser(path) + abs_path = os.path.abspath(expand_user) + + return abs_path + + +def main(args): + # Parse arguments. + options = parse_args(args) + # Make sure the path is absolute. + path = sanitize_path(options.path) + # Try downloading clang-format. + ok = download_clang_format(path) + + if ok: + print("Successfully downloaded clang-format to {}".format(path)) + print("Remember to add {} to your PATH".format(path)) + + return not ok + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:]))