You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
4.0KB

  1. import multiprocessing
  2. import shutil
  3. from pathlib import Path
  4. from typing import Optional
  5. from . import paths, proc, toolchain as tc_mod
  6. from dds_ci.util import Pathish
  7. class DDSWrapper:
  8. """
  9. Wraps a 'dds' executable with some convenience APIs that invoke various
  10. 'dds' subcommands.
  11. """
  12. def __init__(self,
  13. path: Path,
  14. *,
  15. repo_dir: Optional[Pathish] = None,
  16. catalog_path: Optional[Pathish] = None,
  17. default_cwd: Optional[Pathish] = None) -> None:
  18. self.path = path
  19. self.repo_dir = Path(repo_dir or (paths.PREBUILT_DIR / 'ci-repo'))
  20. self.catalog_path = Path(catalog_path or (self.repo_dir.parent / 'ci-catalog.db'))
  21. self.default_cwd = default_cwd or Path.cwd()
  22. def clone(self) -> 'DDSWrapper':
  23. return DDSWrapper(self.path,
  24. repo_dir=self.repo_dir,
  25. catalog_path=self.catalog_path,
  26. default_cwd=self.default_cwd)
  27. @property
  28. def catalog_path_arg(self) -> str:
  29. """The arguments for --catalog"""
  30. return f'--catalog={self.catalog_path}'
  31. @property
  32. def repo_dir_arg(self) -> str:
  33. """The arguments for --repo-dir"""
  34. return f'--repo-dir={self.repo_dir}'
  35. def set_repo_scratch(self, path: Pathish) -> None:
  36. self.repo_dir = Path(path) / 'data'
  37. self.catalog_path = Path(path) / 'catalog.db'
  38. def clean(self, *, build_dir: Optional[Path] = None, repo: bool = True, catalog: bool = True) -> None:
  39. """
  40. Clean out prior executable output, including repos, catalog, and
  41. the build results at 'build_dir', if given.
  42. """
  43. if build_dir and build_dir.exists():
  44. shutil.rmtree(build_dir)
  45. if repo and self.repo_dir.exists():
  46. shutil.rmtree(self.repo_dir)
  47. if catalog and self.catalog_path.exists():
  48. self.catalog_path.unlink()
  49. def run(self, args: proc.CommandLine, *, cwd: Optional[Pathish] = None) -> None:
  50. """Execute the 'dds' executable with the given arguments"""
  51. proc.check_run([self.path, args], cwd=cwd or self.default_cwd)
  52. def catalog_json_import(self, path: Path) -> None:
  53. """Run 'catalog import' to import the given JSON. Only applicable to older 'dds'"""
  54. self.run(['catalog', 'import', self.catalog_path_arg, f'--json={path}'])
  55. def catalog_get(self, what: str) -> None:
  56. self.run(['catalog', 'get', self.catalog_path_arg, what])
  57. def repo_add(self, url: str) -> None:
  58. self.run(['repo', 'add', self.catalog_path_arg, url, '--update'])
  59. def repo_import(self, sdist: Path) -> None:
  60. self.run(['repo', self.repo_dir_arg, 'import', sdist])
  61. def build(self,
  62. *,
  63. root: Path,
  64. toolchain: Optional[Path] = None,
  65. build_root: Optional[Path] = None,
  66. jobs: Optional[int] = None) -> None:
  67. """
  68. Run 'dds build' with the given arguments.
  69. :param toolchain: The toolchain to use for the build.
  70. :param root: The root project directory.
  71. :param build_root: The root directory where the output will be written.
  72. :param jobs: The number of jobs to use. Default is CPU-count + 2
  73. """
  74. toolchain = toolchain or tc_mod.get_default_audit_toolchain()
  75. jobs = jobs or multiprocessing.cpu_count() + 2
  76. self.run([
  77. 'build',
  78. f'--toolchain={toolchain}',
  79. self.repo_dir_arg,
  80. self.catalog_path_arg,
  81. f'--jobs={jobs}',
  82. f'--project-dir={root}',
  83. f'--out={build_root}',
  84. ])
  85. def build_deps(self, args: proc.CommandLine, *, toolchain: Optional[Path] = None) -> None:
  86. toolchain = toolchain or tc_mod.get_default_audit_toolchain()
  87. self.run([
  88. 'build-deps',
  89. f'--toolchain={toolchain}',
  90. self.catalog_path_arg,
  91. self.repo_dir_arg,
  92. args,
  93. ])