|
14 | 14 | from packageurl import PackageURL |
15 | 15 |
|
16 | 16 | import macaron |
| 17 | +from macaron.build_spec_generator.build_spec_generator import ( |
| 18 | + BuildSpecFormat, |
| 19 | + gen_build_spec_str, |
| 20 | +) |
17 | 21 | from macaron.config.defaults import create_defaults, load_defaults |
18 | 22 | from macaron.config.global_config import global_config |
19 | 23 | from macaron.errors import ConfigurationError |
@@ -236,6 +240,63 @@ def verify_policy(verify_policy_args: argparse.Namespace) -> int: |
236 | 240 | return os.EX_USAGE |
237 | 241 |
|
238 | 242 |
|
| 243 | +def gen_build_spec(gen_build_spec_args: argparse.Namespace) -> int: |
| 244 | + """Generate a build spec containing the build information discovered by Macaron. |
| 245 | +
|
| 246 | + Returns |
| 247 | + ------- |
| 248 | + int |
| 249 | + Returns os.EX_OK if successful or the corresponding error code on failure. |
| 250 | + """ |
| 251 | + if not os.path.isfile(gen_build_spec_args.database): |
| 252 | + logger.critical("The database file does not exist.") |
| 253 | + return os.EX_OSFILE |
| 254 | + |
| 255 | + output_format = gen_build_spec_args.output_format |
| 256 | + |
| 257 | + try: |
| 258 | + build_spec_format = BuildSpecFormat(output_format) |
| 259 | + except ValueError: |
| 260 | + logger.error("The output format %s is not supported.", output_format) |
| 261 | + return os.EX_USAGE |
| 262 | + |
| 263 | + try: |
| 264 | + purl = PackageURL.from_string(gen_build_spec_args.package_url) |
| 265 | + except ValueError as error: |
| 266 | + logger.error("Cannot parse purl %s. Error %s", gen_build_spec_args.package_url, error) |
| 267 | + return os.EX_USAGE |
| 268 | + |
| 269 | + build_spec_content = gen_build_spec_str( |
| 270 | + purl=purl, |
| 271 | + database_path=gen_build_spec_args.database, |
| 272 | + build_spec_format=build_spec_format, |
| 273 | + ) |
| 274 | + |
| 275 | + if not build_spec_content: |
| 276 | + logger.error("Error while generate reproducible central build spec.") |
| 277 | + return os.EX_DATAERR |
| 278 | + |
| 279 | + logger.debug("Build spec content: \n%s", build_spec_content) |
| 280 | + build_spec_filepath = os.path.join(global_config.output_path, "macaron.buildspec") |
| 281 | + try: |
| 282 | + with open(build_spec_filepath, mode="w", encoding="utf-8") as file: |
| 283 | + logger.info( |
| 284 | + "Generating the %s format build spec to %s.", |
| 285 | + build_spec_format.value, |
| 286 | + os.path.relpath(build_spec_filepath, os.getcwd()), |
| 287 | + ) |
| 288 | + file.write(build_spec_content) |
| 289 | + except OSError as error: |
| 290 | + logger.error( |
| 291 | + "Could not generate the Buildspec to %s. Error: %s", |
| 292 | + os.path.relpath(build_spec_filepath, os.getcwd()), |
| 293 | + error, |
| 294 | + ) |
| 295 | + return os.EX_DATAERR |
| 296 | + |
| 297 | + return os.EX_OK |
| 298 | + |
| 299 | + |
239 | 300 | def find_source(find_args: argparse.Namespace) -> int: |
240 | 301 | """Perform repo and commit finding for a passed PURL, or commit finding for a passed PURL and repo.""" |
241 | 302 | if repo_finder.find_source(find_args.package_url, find_args.repo_path or None): |
@@ -284,6 +345,9 @@ def perform_action(action_args: argparse.Namespace) -> None: |
284 | 345 |
|
285 | 346 | find_source(action_args) |
286 | 347 |
|
| 348 | + case "gen-build-spec": |
| 349 | + sys.exit(gen_build_spec(action_args)) |
| 350 | + |
287 | 351 | case _: |
288 | 352 | logger.error("Macaron does not support command option %s.", action_args.action) |
289 | 353 | sys.exit(os.EX_USAGE) |
@@ -523,6 +587,30 @@ def main(argv: list[str] | None = None) -> None: |
523 | 587 | ), |
524 | 588 | ) |
525 | 589 |
|
| 590 | + # Generate a build spec containing rebuild information for a software component. |
| 591 | + gen_build_spec_parser = sub_parser.add_parser(name="gen-build-spec") |
| 592 | + |
| 593 | + gen_build_spec_parser.add_argument( |
| 594 | + "-purl", |
| 595 | + "--package-url", |
| 596 | + required=True, |
| 597 | + type=str, |
| 598 | + help=("The PURL string of the software component to generate build spec for."), |
| 599 | + ) |
| 600 | + |
| 601 | + gen_build_spec_parser.add_argument( |
| 602 | + "--database", |
| 603 | + help="Path to the database.", |
| 604 | + required=True, |
| 605 | + ) |
| 606 | + |
| 607 | + gen_build_spec_parser.add_argument( |
| 608 | + "--output-format", |
| 609 | + type=str, |
| 610 | + help=('The output format. Can be rc-buildspec (Reproducible-central build spec) (default "rc-buildspec")'), |
| 611 | + default="rc-buildspec", |
| 612 | + ) |
| 613 | + |
526 | 614 | args = main_parser.parse_args(argv) |
527 | 615 |
|
528 | 616 | if not args.action: |
|
0 commit comments