|
|
|
|
|
|
|
|
import argparse |
|
|
import argparse |
|
|
import itertools |
|
|
import itertools |
|
|
import json |
|
|
import json |
|
|
import tarfile |
|
|
|
|
|
|
|
|
import os |
|
|
import re |
|
|
import re |
|
|
import shutil |
|
|
import shutil |
|
|
import sys |
|
|
import sys |
|
|
|
|
|
import tarfile |
|
|
import tempfile |
|
|
import tempfile |
|
|
from concurrent.futures import ThreadPoolExecutor |
|
|
from concurrent.futures import ThreadPoolExecutor |
|
|
from contextlib import contextmanager |
|
|
from contextlib import contextmanager |
|
|
from pathlib import Path |
|
|
from pathlib import Path |
|
|
from subprocess import check_call |
|
|
from subprocess import check_call |
|
|
from threading import Lock |
|
|
from threading import Lock |
|
|
from urllib import request |
|
|
|
|
|
from typing import (Any, Dict, Iterable, Iterator, NamedTuple, NoReturn, Optional, Sequence, Tuple, TypeVar, Type, |
|
|
|
|
|
|
|
|
from typing import (Any, Dict, Iterable, Iterator, NamedTuple, NoReturn, Optional, Sequence, Tuple, Type, TypeVar, |
|
|
Union) |
|
|
Union) |
|
|
|
|
|
from urllib import request |
|
|
|
|
|
|
|
|
from semver import VersionInfo |
|
|
from semver import VersionInfo |
|
|
from typing_extensions import Protocol |
|
|
from typing_extensions import Protocol |
|
|
|
|
|
|
|
|
I32_MAX = 0xffff_ffff - 1 |
|
|
I32_MAX = 0xffff_ffff - 1 |
|
|
MAX_VERSION = VersionInfo(I32_MAX, I32_MAX, I32_MAX) |
|
|
MAX_VERSION = VersionInfo(I32_MAX, I32_MAX, I32_MAX) |
|
|
|
|
|
|
|
|
|
|
|
REPO_ROOT = Path(__file__).resolve().absolute().parent.parent |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def dds_exe() -> Path: |
|
|
|
|
|
suffix = '.exe' if os.name == 'nt' else '' |
|
|
|
|
|
dirs = [REPO_ROOT / '_build', REPO_ROOT / '_prebuilt'] |
|
|
|
|
|
for d in dirs: |
|
|
|
|
|
exe = d / ('dds' + suffix) |
|
|
|
|
|
if exe.is_file(): |
|
|
|
|
|
return exe |
|
|
|
|
|
raise RuntimeError('Unable to find a dds.exe to use') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Dependency(NamedTuple): |
|
|
class Dependency(NamedTuple): |
|
|
name: str |
|
|
name: str |
|
|
|
|
|
|
|
|
def spec_as_local_tgz(spec: SpecPackage) -> Iterator[Path]: |
|
|
def spec_as_local_tgz(spec: SpecPackage) -> Iterator[Path]: |
|
|
with spec.remote.make_local_dir(spec.name, spec.version) as clone_dir: |
|
|
with spec.remote.make_local_dir(spec.name, spec.version) as clone_dir: |
|
|
out_tgz = clone_dir / 'sdist.tgz' |
|
|
out_tgz = clone_dir / 'sdist.tgz' |
|
|
check_call(['dds', 'sdist', 'create', f'--project-dir={clone_dir}', f'--out={out_tgz}']) |
|
|
|
|
|
|
|
|
check_call([str(dds_exe()), 'sdist', 'create', f'--project-dir={clone_dir}', f'--out={out_tgz}']) |
|
|
yield out_tgz |
|
|
yield out_tgz |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
@classmethod |
|
|
def create(cls, dirpath: Path, name: str) -> 'Repository': |
|
|
def create(cls, dirpath: Path, name: str) -> 'Repository': |
|
|
check_call(['dds', 'repoman', 'init', str(dirpath), f'--name={name}']) |
|
|
|
|
|
|
|
|
check_call([str(dds_exe()), 'repoman', 'init', str(dirpath), f'--name={name}']) |
|
|
return Repository(dirpath) |
|
|
return Repository(dirpath) |
|
|
|
|
|
|
|
|
@classmethod |
|
|
@classmethod |
|
|
|
|
|
|
|
|
return Repository(dirpath) |
|
|
return Repository(dirpath) |
|
|
|
|
|
|
|
|
def import_tgz(self, path: Path) -> None: |
|
|
def import_tgz(self, path: Path) -> None: |
|
|
check_call(['dds', 'repoman', 'import', str(self._path), str(path)]) |
|
|
|
|
|
|
|
|
check_call([str(dds_exe()), 'repoman', 'import', str(self._path), str(path)]) |
|
|
|
|
|
|
|
|
def remove(self, name: str) -> None: |
|
|
def remove(self, name: str) -> None: |
|
|
check_call(['dds', 'repoman', 'remove', str(self._path), name]) |
|
|
|
|
|
|
|
|
check_call([str(dds_exe()), 'repoman', 'remove', str(self._path), name]) |
|
|
|
|
|
|
|
|
def spec_import(self, spec: Path) -> None: |
|
|
def spec_import(self, spec: Path) -> None: |
|
|
all_specs = iter_spec(spec) |
|
|
all_specs = iter_spec(spec) |