|
- import enum
- from pathlib import Path
- from contextlib import contextmanager
- from typing import Iterator
- import sys
- import urllib.request
- import shutil
-
- from . import paths
- from .dds import DDSWrapper
- from .paths import new_tempdir
-
-
- class BootstrapMode(enum.Enum):
- """How should be bootstrap our prior DDS executable?"""
- #: Downlaod one from GitHub
- Download = 'download'
- #: Build one from source
- Build = 'build'
- #: Skip bootstrapping. Assume it already exists.
- Skip = 'skip'
- #: If the prior executable exists, skip, otherwise download
- Lazy = 'lazy'
-
-
- def _do_bootstrap_download() -> Path:
- filename = {
- 'win32': 'dds-win-x64.exe',
- 'linux': 'dds-linux-x64',
- 'darwin': 'dds-macos-x64',
- 'freebsd11': 'dds-freebsd-x64',
- 'freebsd12': 'dds-freebsd-x64',
- }.get(sys.platform)
- if filename is None:
- raise RuntimeError(f'We do not have a prebuilt DDS binary for the "{sys.platform}" platform')
- url = f'https://github.com/vector-of-bool/dds/releases/download/0.1.0-alpha.4/{filename}'
-
- print(f'Downloading prebuilt DDS executable: {url}')
- stream = urllib.request.urlopen(url)
- paths.PREBUILT_DDS.parent.mkdir(exist_ok=True, parents=True)
- with paths.PREBUILT_DDS.open('wb') as fd:
- while True:
- buf = stream.read(1024 * 4)
- if not buf:
- break
- fd.write(buf)
-
- if sys.platform != 'win32':
- # Mark the binary executable. By default it won't be
- mode = paths.PREBUILT_DDS.stat().st_mode
- mode |= 0b001_001_001
- paths.PREBUILT_DDS.chmod(mode)
-
- return paths.PREBUILT_DDS
-
-
- @contextmanager
- def pin_exe(fpath: Path) -> Iterator[Path]:
- """
- Create a copy of 'fpath' at an unspecified location, and yield that path.
-
- This is needed if the executable would overwrite itself.
- """
- with new_tempdir() as tdir:
- tfile = tdir / 'previous-dds.exe'
- shutil.copy2(fpath, tfile)
- yield tfile
-
-
- @contextmanager
- def get_bootstrap_exe(mode: BootstrapMode) -> Iterator[DDSWrapper]:
- """Context manager that yields a DDSWrapper around a prior 'dds' executable"""
- if mode is BootstrapMode.Lazy:
- f = paths.PREBUILT_DDS
- if not f.exists():
- _do_bootstrap_download()
- elif mode is BootstrapMode.Download:
- f = _do_bootstrap_download()
- elif mode is BootstrapMode.Build:
- f = _do_bootstrap_build() # type: ignore # TODO
- elif mode is BootstrapMode.Skip:
- f = paths.PREBUILT_DDS
-
- with pin_exe(f) as dds:
- yield DDSWrapper(dds)
|