3030 'OSS Version' , 'License' , 'Download Location' ,
3131 'Homepage' , 'Copyright Text' , 'Exclude' ,
3232 'Comment' , 'Depends On' ]}
33- _exclude_dir = ['node_moduels ' , 'venv' ]
33+ _exclude_dir = ['node_modules ' , 'venv' , 'Pods' , 'Carthage ' ]
3434
3535
3636def get_terminal_size ():
@@ -50,7 +50,7 @@ def paginate_file(file_path):
5050 input ("Press Enter to see the next page..." )
5151
5252
53- def find_package_manager (input_dir , abs_path_to_exclude = [], manifest_file_name = []):
53+ def find_package_manager (input_dir , abs_path_to_exclude = [], manifest_file_name = [], recursive = False ):
5454 ret = True
5555 if not manifest_file_name :
5656 for value in const .SUPPORT_PACKAE .values ():
@@ -62,9 +62,8 @@ def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[
6262 found_manifest_file = []
6363 suggested_files = []
6464 for parent , dirs , files in os .walk (input_dir ):
65- if len (files ) < 1 :
66- continue
67- if os .path .basename (parent ) in _exclude_dir :
65+ parent_parts = parent .split (os .sep )
66+ if any (ex_dir in parent_parts for ex_dir in _exclude_dir ):
6867 continue
6968 if os .path .abspath (parent ) in abs_path_to_exclude :
7069 continue
@@ -75,7 +74,8 @@ def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[
7574 for exclude_path in abs_path_to_exclude ):
7675 continue
7776 if file in manifest_file_name :
78- found_manifest_file .append (file )
77+ path_with_filename = os .path .join (parent , file )
78+ found_manifest_file .append (path_with_filename )
7979 if file in const .SUGGESTED_PACKAGE .keys ():
8080 suggested_files .append (os .path .join (parent , file ))
8181 for dir in dirs :
@@ -84,42 +84,53 @@ def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[
8484 if len (manifest_l ) > 1 :
8585 if manifest_l [0 ] == dir :
8686 if os .path .exists (os .path .join (parent , manifest_f )):
87- found_manifest_file .append (manifest_f )
88- if len (found_manifest_file ) > 0 :
89- input_dir = parent
90- break
91- found_package_manager = defaultdict (list )
92- for f_idx in found_manifest_file :
87+ found_manifest_file .append (os .path .join (parent , manifest_f ))
88+ if not recursive :
89+ if len (found_manifest_file ) > 0 :
90+ input_dir = parent
91+ break
92+
93+ found_package_manager = defaultdict (lambda : defaultdict (list ))
94+ for f_with_path in found_manifest_file :
95+ f_name = os .path .basename (f_with_path )
96+ dir_path = os .path .dirname (f_with_path )
9397 for key , value in const .SUPPORT_PACKAE .items ():
9498 if isinstance (value , list ):
95- for v in value :
96- if f_idx == v :
97- if key in found_package_manager .keys ():
98- found_package_manager [key ].append (f_idx )
99- else :
100- found_package_manager [key ] = [f_idx ]
99+ if f_name in value :
100+ found_package_manager [key ][dir_path ].append (f_name )
101101 else :
102- if value == f_idx :
103- found_package_manager [key ] = [f_idx ]
102+ if f_name == value :
103+ found_package_manager [key ][dir_path ].append (f_name )
104+ found_package_manager = {k : dict (v ) for k , v in found_package_manager .items ()}
104105
105106 # both npm and pnpm are detected, remove npm.
106- if 'npm' in found_package_manager and 'pnpm' in found_package_manager :
107+ if 'npm' in found_package_manager . keys () and 'pnpm' in found_package_manager . keys () :
107108 del found_package_manager ['npm' ]
108109 if len (found_package_manager ) >= 1 :
109- manifest_file_w_path = [os . path . join ( input_dir , file ) for pkg , files in found_package_manager . items () for file in files ]
110- logger . info ( f"Found the manifest file( { ',' . join ( manifest_file_w_path ) } ) automatically." )
111- logger .warning ( f"### Set Package Manager = { ', ' .join (found_package_manager . keys ()) } " )
110+ log_lines = [" \n Detected Manifest Files automatically" ]
111+ log_lines = print_package_info ( found_package_manager , log_lines )
112+ logger .info ( ' \n ' .join (log_lines ) )
112113 else :
113114 ret = False
114115 logger .info ("Cannot find the manifest file." )
115116
116117 return ret , found_package_manager , input_dir , suggested_files
117118
118119
120+ def print_package_info (success_pm , log_lines ):
121+ if success_pm :
122+ for pm , dir_dict in success_pm .items ():
123+ log_lines .append (f"- { pm } :" )
124+ for path , files in dir_dict .items ():
125+ file_list = ', ' .join (files )
126+ log_lines .append (f" { path } : { file_list } " )
127+ return log_lines
128+
129+
119130def run_dependency_scanner (package_manager = '' , input_dir = '' , output_dir_file = '' , pip_activate_cmd = '' ,
120131 pip_deactivate_cmd = '' , output_custom_dir = '' , app_name = const .default_app_name ,
121132 github_token = '' , formats = [], direct = True , path_to_exclude = [], graph_path = '' ,
122- graph_size = (600 , 600 )):
133+ graph_size = (600 , 600 ), recursive = False ):
123134 global logger
124135
125136 ret = True
@@ -217,9 +228,8 @@ def run_dependency_scanner(package_manager='', input_dir='', output_dir_file='',
217228 try :
218229 ret , found_package_manager , input_dir , suggested_files = find_package_manager (input_dir ,
219230 abs_path_to_exclude ,
220- manifest_file_name )
221- if ret :
222- os .chdir (input_dir )
231+ manifest_file_name ,
232+ recursive )
223233 except Exception as e :
224234 if autodetect :
225235 logger .error (f'Fail to find package manager: { e } ' )
@@ -228,7 +238,7 @@ def run_dependency_scanner(package_manager='', input_dir='', output_dir_file='',
228238 if not ret :
229239 if not autodetect :
230240 logger .info ('Try to analyze dependency without manifest file. (Manual mode)' )
231- found_package_manager [package_manager ] = []
241+ found_package_manager [package_manager ] = {}
232242 else :
233243 ret = False
234244 if suggested_files :
@@ -243,40 +253,47 @@ def run_dependency_scanner(package_manager='', input_dir='', output_dir_file='',
243253 else :
244254 scan_item .set_cover_comment ("No Package manager detected." )
245255
246- pass_key = 'PASS'
247- success_pm = []
248- fail_pm = []
256+ pass_key = [ 'PASS' ]
257+ success_pm = defaultdict ( lambda : defaultdict ( list ))
258+ fail_pm = defaultdict ( lambda : defaultdict ( list ))
249259 cover_comment = ''
250- for pm , manifest_file_name in found_package_manager .items ():
251- if manifest_file_name == pass_key :
252- continue
253- ret , package_dep_item_list , cover_comment = analyze_dependency (pm , input_dir , output_path ,
254- pip_activate_cmd , pip_deactivate_cmd ,
255- output_custom_dir , app_name , github_token ,
256- manifest_file_name , direct )
257- if ret :
258- success_pm .append (f"{ pm } ({ ', ' .join (manifest_file_name )} )" )
259- scan_item .append_file_items (package_dep_item_list )
260- if pm == const .GRADLE :
261- if const .ANDROID in found_package_manager .keys ():
262- found_package_manager [const .ANDROID ] = pass_key
263- if f"{ const .ANDROID } ({ ', ' .join (manifest_file_name )} )" in fail_pm :
264- fail_pm .remove (f"{ const .ANDROID } ({ ', ' .join (manifest_file_name )} )" )
265- elif pm == const .ANDROID :
266- if const .GRADLE in found_package_manager .keys ():
267- found_package_manager [const .GRADLE ] = pass_key
268- if f"{ const .GRADLE } ({ ', ' .join (manifest_file_name )} )" in fail_pm :
269- fail_pm .remove (f"{ const .GRADLE } ({ ', ' .join (manifest_file_name )} )" )
270- else :
271- fail_pm .append (f"{ pm } ({ ', ' .join (manifest_file_name )} )" )
260+ for pm , manifest_file_name_list in found_package_manager .items ():
261+ for manifest_dir , manifest_file_name in manifest_file_name_list .items ():
262+ input_dir = manifest_dir
263+ if manifest_file_name == pass_key :
264+ continue
265+ os .chdir (input_dir )
266+ ret , package_dep_item_list , cover_comment = analyze_dependency (pm , input_dir , output_path ,
267+ pip_activate_cmd , pip_deactivate_cmd ,
268+ output_custom_dir , app_name , github_token ,
269+ manifest_file_name , direct )
270+ if ret :
271+ success_pm [pm ][input_dir ].extend (manifest_file_name )
272+ scan_item .append_file_items (package_dep_item_list )
273+ if pm == const .GRADLE and const .ANDROID in found_package_manager :
274+ found_package_manager [const .ANDROID ][manifest_dir ] = pass_key
275+ if const .ANDROID in fail_pm and input_dir in fail_pm [const .ANDROID ]:
276+ del fail_pm [const .ANDROID ][input_dir ]
277+ elif pm == const .ANDROID and const .GRADLE in found_package_manager :
278+ found_package_manager [const .GRADLE ][manifest_dir ] = pass_key
279+ if const .GRADLE in fail_pm and input_dir in fail_pm [const .GRADLE ]:
280+ del fail_pm [const .GRADLE ][input_dir ]
281+ else :
282+ fail_pm [pm ][input_dir ].extend (manifest_file_name )
272283
284+ success_pm = {k : dict (v ) for k , v in success_pm .items ()}
285+ fail_pm = {k : dict (v ) for k , v in fail_pm .items ()}
273286 if len (found_package_manager .keys ()) > 0 :
274287 if len (success_pm ) > 0 :
275- scan_item .set_cover_comment (f"Analyzed Package manager: { ', ' .join (success_pm )} " )
288+ log_lines = ["Success to analyze:" ]
289+ log_lines = print_package_info (success_pm , log_lines )
290+ scan_item .set_cover_comment ('\n ' .join (log_lines ))
276291 if len (fail_pm ) > 0 :
277- info_msg = 'Check log file(fosslight_log*.txt) ' \
278- 'and https://fosslight.org/fosslight-guide-en/scanner/3_dependency.html#-prerequisite.'
279- scan_item .set_cover_comment (f"Analysis failed Package manager: { ', ' .join (fail_pm )} ({ info_msg } )" )
292+ log_lines = ["Fail to analyze:" ]
293+ log_lines = print_package_info (fail_pm , log_lines )
294+ scan_item .set_cover_comment ('\n ' .join (log_lines ))
295+ scan_item .set_cover_comment ('Check log file(fosslight_log*.txt) '
296+ 'and https://fosslight.org/fosslight-guide-en/scanner/3_dependency.html#-prerequisite.' )
280297
281298 if ret and graph_path :
282299 graph_path = os .path .abspath (graph_path )
@@ -335,6 +352,7 @@ def main():
335352 graph_path = ''
336353 graph_size = (600 , 600 )
337354 direct = True
355+ recursive = False
338356
339357 parser = argparse .ArgumentParser (add_help = False )
340358 parser .add_argument ('-h' , '--help' , action = 'store_true' , required = False )
@@ -353,6 +371,7 @@ def main():
353371 parser .add_argument ('--graph-size' , nargs = 2 , type = int , metavar = ("WIDTH" , "HEIGHT" ), required = False )
354372 parser .add_argument ('--direct' , choices = ('true' , 'false' ), default = 'True' , required = False )
355373 parser .add_argument ('--notice' , action = 'store_true' , required = False )
374+ parser .add_argument ('-r' , '--recursive' , action = 'store_true' , required = False )
356375
357376 args = parser .parse_args ()
358377
@@ -405,10 +424,12 @@ def main():
405424 paginate_file (source_file )
406425 shutil .copyfile (source_file , destination_file )
407426 sys .exit (0 )
427+ if args .recursive : # -r option
428+ recursive = True
408429
409430 run_dependency_scanner (package_manager , input_dir , output_dir , pip_activate_cmd , pip_deactivate_cmd ,
410431 output_custom_dir , app_name , github_token , format , direct , path_to_exclude ,
411- graph_path , graph_size )
432+ graph_path , graph_size , recursive )
412433
413434
414435if __name__ == '__main__' :
0 commit comments