99import os
1010import sys
1111from importlib import metadata as importlib_metadata
12+ from typing import Any
1213
1314from jinja2 import Environment , FileSystemLoader , select_autoescape
1415from packageurl import PackageURL
@@ -96,6 +97,12 @@ def analyze_slsa_levels_single(analyzer_single_args: argparse.Namespace) -> None
9697
9798 global_config .local_maven_repo = user_provided_local_maven_repo
9899
100+ # Set local artifact path.
101+ if analyzer_single_args .local_artifact_path is not None and os .path .isfile (
102+ analyzer_single_args .local_artifact_path
103+ ):
104+ global_config .local_artifact_path = analyzer_single_args .local_artifact_path
105+
99106 analyzer = Analyzer (global_config .output_path , global_config .build_log_path )
100107
101108 # Initiate reporters.
@@ -118,7 +125,6 @@ def analyze_slsa_levels_single(analyzer_single_args: argparse.Namespace) -> None
118125 analyzer .reporters .append (HTMLReporter ())
119126 analyzer .reporters .append (JSONReporter ())
120127
121- run_config = {}
122128 repo_path = analyzer_single_args .repo_path
123129 purl = analyzer_single_args .package_url
124130 branch = analyzer_single_args .branch
@@ -370,8 +376,25 @@ def main(argv: list[str] | None = None) -> None:
370376 # Add sub parsers for each action.
371377 sub_parser = main_parser .add_subparsers (dest = "action" , help = "Run macaron <action> --help for help" )
372378
379+ # Dump the default values.
380+ sub_parser .add_parser (name = "dump-defaults" , description = "Dumps the defaults.ini file to the output directory." )
381+
382+ # Add the sub parser commands.
383+ _add_analyzer_parser (sub_parser )
384+ _add_verify_policy_parser (sub_parser )
385+ _add_find_source_parser (sub_parser )
386+
387+ # Perform parsing.
388+ args = parse_arguments (main_parser , argv )
389+
390+ # Perform actions.
391+ perform_action (args )
392+
393+
394+ def _add_analyzer_parser (parser : Any ) -> None :
395+ """Add the analyzer commands to the parser."""
373396 # Use Macaron to analyze one single repository.
374- single_analyze_parser = sub_parser .add_parser (name = "analyze" )
397+ single_analyze_parser = parser .add_parser (name = "analyze" )
375398
376399 single_analyze_parser .add_argument (
377400 "-sbom" ,
@@ -390,7 +413,7 @@ def main(argv: list[str] | None = None) -> None:
390413 "--repo-path" ,
391414 required = False ,
392415 type = str ,
393- help = ( "The path to the repository, can be local or remote" ) ,
416+ help = "The path to the repository, can be local or remote" ,
394417 )
395418
396419 single_analyze_parser .add_argument (
@@ -411,7 +434,7 @@ def main(argv: list[str] | None = None) -> None:
411434 required = False ,
412435 type = str ,
413436 default = "" ,
414- help = ( "The branch of the repository that we want to checkout. If not set, Macaron will use the default branch" ) ,
437+ help = "The branch of the repository that we want to checkout. If not set, Macaron will use the default branch" ,
415438 )
416439
417440 single_analyze_parser .add_argument (
@@ -430,14 +453,14 @@ def main(argv: list[str] | None = None) -> None:
430453 "-pe" ,
431454 "--provenance-expectation" ,
432455 required = False ,
433- help = ( "The path to provenance expectation file or directory." ) ,
456+ help = "The path to provenance expectation file or directory." ,
434457 )
435458
436459 single_analyze_parser .add_argument (
437460 "-pf" ,
438461 "--provenance-file" ,
439462 required = False ,
440- help = ( "The path to the provenance file in in-toto format." ) ,
463+ help = "The path to the provenance file in in-toto format." ,
441464 )
442465
443466 single_analyze_parser .add_argument (
@@ -456,7 +479,7 @@ def main(argv: list[str] | None = None) -> None:
456479 required = False ,
457480 type = str ,
458481 default = "" ,
459- help = ( "The path to the Jinja2 html template (please make sure to use .html or .j2 extensions)." ) ,
482+ help = "The path to the Jinja2 html template (please make sure to use .html or .j2 extensions)." ,
460483 )
461484
462485 single_analyze_parser .add_argument (
@@ -472,44 +495,56 @@ def main(argv: list[str] | None = None) -> None:
472495 "--local-maven-repo" ,
473496 required = False ,
474497 help = (
475- "The path to the local .m2 directory. If this option is not used, Macaron will use the default location at $HOME/.m2"
498+ "The path to the local .m2 directory. "
499+ "If this option is not used, Macaron will use the default location at $HOME/.m2"
476500 ),
477501 )
478502
479503 single_analyze_parser .add_argument (
480504 "--force-analyze-source" ,
481505 required = False ,
482506 action = "store_true" ,
483- help = ( "Forces PyPI sourcecode analysis to run regardless of other heuristic results." ) ,
507+ help = "Forces PyPI sourcecode analysis to run regardless of other heuristic results." ,
484508 )
485509
486510 single_analyze_parser .add_argument (
487511 "--verify-provenance" ,
488512 required = False ,
489513 action = "store_true" ,
490- help = ( "Allow the analysis to attempt to verify provenance files as part of its normal operations." ) ,
514+ help = "Allow the analysis to attempt to verify provenance files as part of its normal operations." ,
491515 )
492516
493- # Dump the default values.
494- sub_parser .add_parser (name = "dump-defaults" , description = "Dumps the defaults.ini file to the output directory." )
517+ single_analyze_parser .add_argument (
518+ "-ap" ,
519+ "--local-artifact-path" ,
520+ required = False ,
521+ type = str ,
522+ help = "The path to the local artifact file that should match the target software component being analyzed." ,
523+ )
495524
525+
526+ def _add_verify_policy_parser (parser : Any ) -> None :
527+ """Add the verify policy commands parser."""
496528 # Verify the Datalog policy.
497- vp_parser = sub_parser .add_parser (name = "verify-policy" )
529+ vp_parser = parser .add_parser (name = "verify-policy" )
498530 vp_group = vp_parser .add_mutually_exclusive_group (required = True )
499531
500532 vp_parser .add_argument ("-d" , "--database" , required = True , type = str , help = "Path to the database." )
501533 vp_group .add_argument ("-f" , "--file" , type = str , help = "Path to the Datalog policy." )
502534 vp_group .add_argument ("-s" , "--show-prelude" , action = "store_true" , help = "Show policy prelude." )
503535
536+
537+ def _add_find_source_parser (parser : Any ) -> None :
538+ """Add the find source commands parser."""
504539 # Find the repo and commit of a passed PURL, or the commit of a passed PURL and repo.
505- find_parser = sub_parser .add_parser (name = "find-source" )
540+ find_parser = parser .add_parser (name = "find-source" )
506541
507542 find_parser .add_argument (
508543 "-purl" ,
509544 "--package-url" ,
510545 required = True ,
511546 type = str ,
512- help = ( "The PURL string to perform repository and commit finding for." ) ,
547+ help = "The PURL string to perform repository and commit finding for." ,
513548 )
514549
515550 find_parser .add_argument (
@@ -523,10 +558,26 @@ def main(argv: list[str] | None = None) -> None:
523558 ),
524559 )
525560
526- args = main_parser .parse_args (argv )
561+
562+ def parse_arguments (parser : argparse .ArgumentParser , argv : list [str ] | None ) -> argparse .Namespace :
563+ """Parse the arguments of the argument parser.
564+
565+ Parameters
566+ ----------
567+ parser: argparse.ArgumentParser
568+ The parser to use.
569+ argv: list[str]
570+ The list of arguments for the parser to parse.
571+
572+ Returns
573+ -------
574+ argparse.Namespace
575+ The results of the argument parsing.
576+ """
577+ args = parser .parse_args (argv )
527578
528579 if not args .action :
529- main_parser .print_help ()
580+ parser .print_help ()
530581 sys .exit (os .EX_USAGE )
531582
532583 if args .verbose :
@@ -587,7 +638,7 @@ def main(argv: list[str] | None = None) -> None:
587638 logger .error ("Exiting because the defaults configuration could not be loaded." )
588639 sys .exit (os .EX_NOINPUT )
589640
590- perform_action ( args )
641+ return args
591642
592643
593644def _get_token_from_dict_or_env (token : str , token_dict : dict [str , str ]) -> str :
0 commit comments