aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/project/boost/download.py
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2020-03-28 23:01:09 +0000
committerEgor Tensin <Egor.Tensin@gmail.com>2020-03-28 23:54:46 +0000
commitc58a3787eca9c0c4a7f376ba841cd7e39ab95ece (patch)
tree709b5ab8385bbb952912206ae561fbe5e1e752d8 /project/boost/download.py
parentproject.boost: factor out BoostVersion (diff)
downloadcmake-common-c58a3787eca9c0c4a7f376ba841cd7e39ab95ece.tar.gz
cmake-common-c58a3787eca9c0c4a7f376ba841cd7e39ab95ece.zip
project.boost: factor out everything else
I finally snapped. This starts to resemble sensible structure though.
Diffstat (limited to 'project/boost/download.py')
-rw-r--r--project/boost/download.py112
1 files changed, 112 insertions, 0 deletions
diff --git a/project/boost/download.py b/project/boost/download.py
new file mode 100644
index 0000000..954ec1f
--- /dev/null
+++ b/project/boost/download.py
@@ -0,0 +1,112 @@
+# Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com>
+# This file is part of the "cmake-common" project.
+# For details, see https://github.com/egor-tensin/cmake-common.
+# Distributed under the MIT License.
+
+R'''Download & bootstrap Boost.
+
+This script downloads and bootstraps a Boost distribution. It's main utility
+is that it's supposed to be cross-platform.
+
+Usage examples:
+
+ $ %(prog)s 1.71.0
+ ...
+
+ $ %(prog)s --unpack ~/workspace/third-party/ 1.65.0
+ ...
+'''
+
+import argparse
+from contextlib import contextmanager
+import logging
+import sys
+import urllib.request
+
+from project.boost.archive import Archive, PermanentStorage, TemporaryStorage
+from project.boost.version import Version
+import project.utils
+
+
+def _download_try_url(url):
+ logging.info('Trying URL: %s', url)
+ try:
+ with urllib.request.urlopen(url, timeout=20) as request:
+ return request.read()
+ except urllib.request.URLError as e:
+ logging.error("Couldn't download from this mirror, an error occured:")
+ logging.exception(e)
+
+
+@contextmanager
+def _download_try_all_urls(version, storage):
+ urls = version.get_download_urls()
+ for url in urls:
+ reply = _download_try_url(url)
+ if reply is None:
+ continue
+ with storage.write_archive(version, reply) as path:
+ yield path
+ return
+ raise RuntimeError("Couldn't download Boost from any of the mirrors")
+
+
+@contextmanager
+def _download_if_necessary(version, storage):
+ path = storage.get_archive(version)
+ if path is not None:
+ logging.info('Using existing Boost archive: %s', path)
+ yield path
+ return
+ with _download_try_all_urls(version, storage) as path:
+ yield path
+
+
+class DownloadParameters:
+ def __init__(self, version, unpack_dir='.', cache_dir=None):
+ self.version = version
+ self.unpack_dir = project.utils.normalize_path(unpack_dir)
+ self.storage = TemporaryStorage(unpack_dir)
+ if cache_dir is not None:
+ cache_dir = project.utils.normalize_path(cache_dir)
+ self.storage = PermanentStorage(cache_dir)
+
+ @staticmethod
+ def from_args(args):
+ return DownloadParameters(**vars(args))
+
+
+def download(params):
+ with _download_if_necessary(params.version, params.storage) as path:
+ archive = Archive(params.version, path)
+ boost_dir = archive.unpack(params.unpack_dir)
+ boost_dir.bootstrap()
+
+
+def _parse_args(argv=None):
+ if argv is None:
+ argv = sys.argv[1:]
+ logging.info('Command line arguments: %s', argv)
+
+ parser = argparse.ArgumentParser(
+ description=__doc__,
+ formatter_class=argparse.RawDescriptionHelpFormatter)
+
+ parser.add_argument('--unpack', metavar='DIR', dest='unpack_dir',
+ type=project.utils.normalize_path, default='.',
+ help='directory to unpack the archive to')
+ parser.add_argument('--cache', metavar='DIR', dest='cache_dir',
+ type=project.utils.normalize_path,
+ help='download directory (temporary file unless specified)')
+ parser.add_argument('version', metavar='VERSION', type=Version.from_string,
+ help='Boost version (in the MAJOR.MINOR.PATCH format)')
+ return parser.parse_args(argv)
+
+
+def _main(argv=None):
+ with project.utils.setup_logging():
+ download(DownloadParameters.from_args(_parse_args(argv)))
+
+
+if __name__ == '__main__':
+ _main()