55from urllib .parse import urlparse
66
77from osv_common import extract_repo_urls , iter_vulnerability_files , load_vulnerability
8- from recidivism_config import load_config_with_source , required_value , resolve_config_path
8+ from recidivism_config import get_required_value , load_config_with_source , resolve_config_path
99
1010
1111def clone_or_update (repo_url : str , target_dir : Path , update_existing : bool ) -> None :
@@ -46,13 +46,18 @@ def main() -> None:
4646 config , config_source = load_config_with_source ("clone" )
4747
4848 parser = argparse .ArgumentParser (description = "Clone all repositories referenced by OSV vulnerabilities." )
49- parser .add_argument ("--osv-dir" , help = "Directory containing extracted OSV JSON files" )
50- parser .add_argument ("--target-dir" , help = "Directory to place local repository clones" )
51- max_repos_str = config .get ("max_repos" , fallback = "" ).strip ()
49+ parser .add_argument (
50+ "--osv-dir" ,
51+ help = "Directory containing extracted OSV JSON files (overrides clone.osv_dir in recidivism.ini)" ,
52+ )
53+ parser .add_argument (
54+ "--target-dir" ,
55+ help = "Directory to place local repository clones (overrides clone.target_dir in recidivism.ini)" ,
56+ )
5257 parser .add_argument (
5358 "--max-repos" ,
5459 type = int ,
55- default = int ( max_repos_str ) if max_repos_str else None ,
60+ default = None ,
5661 help = "Optional limit for number of repositories" ,
5762 )
5863 parser .add_argument (
@@ -64,10 +69,18 @@ def main() -> None:
6469 args = parser .parse_args ()
6570
6671 try :
67- osv_dir = resolve_config_path (args .osv_dir or required_value (config , "osv_dir" ))
68- target_dir = resolve_config_path (args .target_dir or required_value (config , "target_dir" ))
72+ osv_dir = resolve_config_path (args .osv_dir or get_required_value (config , "clone" , "osv_dir" ))
73+ target_dir = resolve_config_path (args .target_dir or get_required_value (config , "clone" , "target_dir" ))
6974 except ValueError as error :
7075 parser .error (f"{ error } (config: { config_source } )" )
76+ max_repos = args .max_repos
77+ if max_repos is None :
78+ max_repos_str = config .get ("max_repos" , fallback = "" ).strip ()
79+ if max_repos_str :
80+ try :
81+ max_repos = int (max_repos_str )
82+ except ValueError as error :
83+ parser .error (f"Invalid clone.max_repos value '{ max_repos_str } ' in { config_source } : { error } " )
7184 target_dir .mkdir (parents = True , exist_ok = True )
7285
7386 repo_urls = set ()
@@ -76,8 +89,8 @@ def main() -> None:
7689 repo_urls .update (extract_repo_urls (vulnerability ))
7790
7891 ordered_repos = sorted (repo_urls )
79- if args . max_repos is not None :
80- ordered_repos = ordered_repos [: args . max_repos ]
92+ if max_repos is not None :
93+ ordered_repos = ordered_repos [:max_repos ]
8194
8295 for repo_url in ordered_repos :
8396 clone_or_update (repo_url , target_dir , args .update_existing )
0 commit comments