|
30 | 30 |
|
31 | 31 | import pypac |
32 | 32 |
|
| 33 | +from scanoss.scanners.folder_hasher import ( |
| 34 | + FolderHasher, |
| 35 | + create_folder_hasher_config_from_args, |
| 36 | +) |
33 | 37 | from scanoss.scanossgrpc import ( |
34 | 38 | ScanossGrpc, |
35 | 39 | ScanossGrpcError, |
@@ -316,6 +320,7 @@ def setup_args() -> None: # noqa: PLR0915 |
316 | 320 | for p in [c_crypto, c_vulns, c_semgrep]: |
317 | 321 | p.add_argument('--purl', '-p', type=str, nargs='*', help='Package URL - PURL to process.') |
318 | 322 | p.add_argument('--input', '-i', type=str, help='Input file name') |
| 323 | + |
319 | 324 | # Common Component sub-command options |
320 | 325 | for p in [c_crypto, c_vulns, c_search, c_versions, c_semgrep, c_provenance]: |
321 | 326 | p.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).') |
@@ -474,35 +479,68 @@ def setup_args() -> None: # noqa: PLR0915 |
474 | 479 | ) |
475 | 480 | p_undeclared.set_defaults(func=inspect_undeclared) |
476 | 481 |
|
| 482 | + # Sub-command: folder-scan |
477 | 483 | p_folder_scan = subparsers.add_parser( |
478 | 484 | 'folder-scan', |
| 485 | + aliases=['fs'], |
479 | 486 | description=f'Scan the given directory using folder hashing: {__version__}', |
480 | 487 | help='Scan the given directory using folder hashing', |
481 | 488 | ) |
482 | 489 | p_folder_scan.add_argument('scan_dir', metavar='FILE/DIR', type=str, nargs='?', help='The root directory to scan') |
483 | 490 | p_folder_scan.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).') |
| 491 | + p_folder_scan.add_argument( |
| 492 | + '--timeout', |
| 493 | + '-M', |
| 494 | + type=int, |
| 495 | + default=600, |
| 496 | + help='Timeout (in seconds) for API communication (optional - default 600)', |
| 497 | + ) |
484 | 498 | p_folder_scan.add_argument( |
485 | 499 | '--format', |
486 | 500 | '-f', |
487 | 501 | type=str, |
488 | | - choices=['plain', 'json'], |
489 | | - help='Result output format (optional - default: plain)', |
| 502 | + choices=['json'], |
| 503 | + default='json', |
| 504 | + help='Result output format (optional - default: json)', |
490 | 505 | ) |
491 | 506 | p_folder_scan.add_argument( |
492 | 507 | '--best-match', |
493 | 508 | '-bm', |
494 | 509 | action='store_true', |
| 510 | + default=False, |
495 | 511 | help='Enable best match mode (optional - default: False)', |
496 | 512 | ) |
497 | 513 | p_folder_scan.add_argument( |
498 | 514 | '--threshold', |
499 | 515 | type=int, |
| 516 | + choices=range(1, 101), |
| 517 | + metavar='1-100', |
| 518 | + default=100, |
500 | 519 | help='Threshold for result matching (optional - default: 100)', |
501 | 520 | ) |
502 | 521 | p_folder_scan.set_defaults(func=folder_hashing_scan) |
503 | 522 |
|
| 523 | + # Sub-command: folder-hash |
| 524 | + p_folder_hash = subparsers.add_parser( |
| 525 | + 'folder-hash', |
| 526 | + aliases=['fh'], |
| 527 | + description=f'Produce a folder hash for the given directory: {__version__}', |
| 528 | + help='Produce a folder hash for the given directory', |
| 529 | + ) |
| 530 | + p_folder_hash.add_argument('scan_dir', metavar='FILE/DIR', type=str, nargs='?', help='A file or folder to scan') |
| 531 | + p_folder_hash.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).') |
| 532 | + p_folder_hash.add_argument( |
| 533 | + '--format', |
| 534 | + '-f', |
| 535 | + type=str, |
| 536 | + choices=['json'], |
| 537 | + default='json', |
| 538 | + help='Result output format (optional - default: json)', |
| 539 | + ) |
| 540 | + p_folder_hash.set_defaults(func=folder_hash) |
| 541 | + |
504 | 542 | # Scanoss settings options |
505 | | - for p in [p_folder_scan, p_scan, p_wfp]: |
| 543 | + for p in [p_folder_scan, p_scan, p_wfp, p_folder_hash]: |
506 | 544 | p.add_argument( |
507 | 545 | '--settings', |
508 | 546 | '-st', |
@@ -530,7 +568,7 @@ def setup_args() -> None: # noqa: PLR0915 |
530 | 568 | p.add_argument('-s', '--status', type=str, help='Save summary data into Markdown file') |
531 | 569 |
|
532 | 570 | # Global Scan command options |
533 | | - for p in [p_scan, p_folder_scan]: |
| 571 | + for p in [p_scan]: |
534 | 572 | p.add_argument( |
535 | 573 | '--apiurl', type=str, help='SCANOSS API URL (optional - default: https://api.osskb.org/scan/direct)' |
536 | 574 | ) |
@@ -614,6 +652,7 @@ def setup_args() -> None: # noqa: PLR0915 |
614 | 652 | p_undeclared, |
615 | 653 | p_copyleft, |
616 | 654 | p_folder_scan, |
| 655 | + p_folder_hash, |
617 | 656 | ]: |
618 | 657 | p.add_argument('--debug', '-d', action='store_true', help='Enable debug messages') |
619 | 658 | p.add_argument('--trace', '-t', action='store_true', help='Enable trace messages, including API posts') |
@@ -1499,6 +1538,39 @@ def folder_hashing_scan(parser, args): |
1499 | 1538 | sys.exit(1) |
1500 | 1539 |
|
1501 | 1540 |
|
| 1541 | +def folder_hash(parser, args): |
| 1542 | + """Run the "folder-hash" sub-command |
| 1543 | +
|
| 1544 | + Args: |
| 1545 | + parser (ArgumentParser): command line parser object |
| 1546 | + args (Namespace): Parsed arguments |
| 1547 | + """ |
| 1548 | + try: |
| 1549 | + if not args.scan_dir: |
| 1550 | + print_stderr('ERROR: Please specify a directory to scan') |
| 1551 | + parser.parse_args([args.subparser, '-h']) |
| 1552 | + sys.exit(1) |
| 1553 | + |
| 1554 | + if not os.path.exists(args.scan_dir) or not os.path.isdir(args.scan_dir): |
| 1555 | + print_stderr(f'ERROR: The specified directory {args.scan_dir} does not exist') |
| 1556 | + sys.exit(1) |
| 1557 | + |
| 1558 | + folder_hasher_config = create_folder_hasher_config_from_args(args) |
| 1559 | + scanoss_settings = get_scanoss_settings_from_args(args) |
| 1560 | + |
| 1561 | + folder_hasher = FolderHasher( |
| 1562 | + scan_dir=args.scan_dir, |
| 1563 | + config=folder_hasher_config, |
| 1564 | + scanoss_settings=scanoss_settings, |
| 1565 | + ) |
| 1566 | + |
| 1567 | + folder_hasher.hash_directory(args.scan_dir) |
| 1568 | + folder_hasher.present(output_file=args.output, output_format=args.format) |
| 1569 | + except Exception as e: |
| 1570 | + print_stderr(f'ERROR: {e}') |
| 1571 | + sys.exit(1) |
| 1572 | + |
| 1573 | + |
1502 | 1574 | def get_scanoss_settings_from_args(args): |
1503 | 1575 | scanoss_settings = None |
1504 | 1576 | if not args.skip_settings_file: |
|
0 commit comments