77
88import os
99import shutil
10- import logging
11- import textwrap
1210import asyncio
11+ import logging
12+ from configparser import NoOptionError
1313from git_fleximod import utils
1414from git_fleximod import cli
1515from git_fleximod .gitinterface import GitInterface
1616from git_fleximod .gitmodules import GitModules
1717from git_fleximod .submodule import Submodule
1818
19- # logger variable is global
20- logger = None
19+ logger = logging .getLogger (__name__ )
2120
2221
2322def fxrequired_allowed_values ():
24- return ["ToplevelRequired" , "ToplevelOptional" , "AlwaysRequired" , "AlwaysOptional" , "TopLevelRequired" , "TopLevelOptional" ]
23+ return [
24+ "ToplevelRequired" ,
25+ "ToplevelOptional" ,
26+ "AlwaysRequired" ,
27+ "AlwaysOptional" ,
28+ "TopLevelRequired" ,
29+ "TopLevelOptional" ,
30+ ]
2531
2632
2733def commandline_arguments (args = None ):
@@ -69,6 +75,7 @@ def commandline_arguments(args=None):
6975 options .components ,
7076 options .exclude ,
7177 options .force ,
78+ options .no_mods_details ,
7279 action ,
7380 )
7481
@@ -151,8 +158,8 @@ def submodule_sparse_checkout(root_dir, name, url, path, sparsefile, tag="master
151158
152159 if os .path .isdir (os .path .join (root_dir , path , ".git" )):
153160 with utils .pushd (sprep_repo ):
154- if os .path .isdir (os .path .join (topgit ,".git" )):
155- shutil .rmtree (os .path .join (topgit ,".git" ))
161+ if os .path .isdir (os .path .join (topgit , ".git" )):
162+ shutil .rmtree (os .path .join (topgit , ".git" ))
156163 shutil .move (".git" , topgit )
157164 with open (".git" , "w" ) as f :
158165 f .write ("gitdir: " + os .path .relpath (topgit ))
@@ -167,7 +174,6 @@ def submodule_sparse_checkout(root_dir, name, url, path, sparsefile, tag="master
167174 with utils .pushd (sprep_repo ):
168175 if os .path .isfile (sparsefile ):
169176 shutil .copy (sparsefile , gitsparse )
170-
171177
172178 # Finally checkout the repo
173179 sprepo_git .git_operation ("fetch" , "origin" , "--tags" )
@@ -177,7 +183,8 @@ def submodule_sparse_checkout(root_dir, name, url, path, sparsefile, tag="master
177183 rgit .config_set_value (f'submodule "{ name } "' , "active" , "true" )
178184 rgit .config_set_value (f'submodule "{ name } "' , "url" , url )
179185
180- def init_submodule_from_gitmodules (gitmodules , name , root_dir , logger ):
186+
187+ def init_submodule_from_gitmodules (gitmodules , name , root_dir , llogger ):
181188 path = gitmodules .get (name , "path" )
182189 url = gitmodules .get (name , "url" )
183190 assert path and url , f"Malformed .gitmodules file { path } { url } "
@@ -187,60 +194,73 @@ def init_submodule_from_gitmodules(gitmodules, name, root_dir, logger):
187194 fxurl = gitmodules .get (name , "fxDONOTUSEurl" )
188195 fxsparse = gitmodules .get (name , "fxsparse" )
189196 fxrequired = gitmodules .get (name , "fxrequired" )
190- return Submodule (root_dir , name , path , url , fxtag = tag , fxurl = fxurl , fxsparse = fxsparse , fxrequired = fxrequired , logger = logger )
197+ return Submodule (
198+ root_dir ,
199+ name ,
200+ path ,
201+ url ,
202+ fxtag = tag ,
203+ fxurl = fxurl ,
204+ fxsparse = fxsparse ,
205+ fxrequired = fxrequired ,
206+ logger = llogger ,
207+ )
191208
192- def submodules_status (gitmodules , root_dir , toplevel = False , depth = 0 ):
209+
210+ def submodules_status (
211+ gitmodules , root_dir , toplevel = False , depth = 0 , no_mods_details = False
212+ ):
193213 testfails = 0
194214 localmods = 0
195215 needsupdate = 0
196- wrapper = textwrap .TextWrapper (initial_indent = ' ' * (depth * 10 ), width = 120 ,subsequent_indent = ' ' * (depth * 20 ))
197216 for name in gitmodules .sections ():
198217 submod = init_submodule_from_gitmodules (gitmodules , name , root_dir , logger )
199-
200- result ,n , l , t = submod .status ()
218+
219+ result , n , l , t = submod .status (depth = depth , no_mods_details = no_mods_details )
201220 if toplevel or not submod .toplevel ():
202- print (wrapper . fill ( result ) )
221+ print (result )
203222 testfails += t
204223 localmods += l
205224 needsupdate += n
206225 subdir = os .path .join (root_dir , submod .path )
207226 if os .path .exists (os .path .join (subdir , ".gitmodules" )):
208227 gsubmod = GitModules (logger , confpath = subdir )
209- t ,l ,n = submodules_status (gsubmod , subdir , depth = depth + 1 )
228+ t , l , n = submodules_status (
229+ gsubmod , subdir , depth = depth + 1 , no_mods_details = no_mods_details
230+ )
210231 if toplevel or not submod .toplevel ():
211232 testfails += t
212233 localmods += l
213234 needsupdate += n
214-
235+
215236 return testfails , localmods , needsupdate
216237
217- def git_toplevelroot (root_dir , logger ):
218- rgit = GitInterface (root_dir , logger )
238+
239+ def git_toplevelroot (root_dir , llogger ):
240+ rgit = GitInterface (root_dir , llogger )
219241 _ , superroot = rgit .git_operation ("rev-parse" , "--show-superproject-working-tree" )
220242 return superroot
221243
244+
222245async def submodules_update (gitmodules , root_dir , requiredlist , force ):
223246 async def update_submodule (name , requiredlist , force ):
224247 submod = init_submodule_from_gitmodules (gitmodules , name , root_dir , logger )
225248
226- _ , needsupdate , localmods , testfails = submod .status ()
227249 if not submod .fxrequired :
228250 submod .fxrequired = "AlwaysRequired"
229- fxrequired = submod .fxrequired
251+ fxrequired = submod .fxrequired
230252 allowedvalues = fxrequired_allowed_values ()
231253 assert fxrequired in allowedvalues
232254
233255 superroot = git_toplevelroot (root_dir , logger )
234-
235- if (
236- fxrequired
237- and ((superroot and "Toplevel" in fxrequired )
238- or fxrequired not in requiredlist )
256+
257+ if fxrequired and (
258+ (superroot and "Toplevel" in fxrequired ) or fxrequired not in requiredlist
239259 ):
240260 if "Optional" in fxrequired and "Optional" not in requiredlist :
241261 if fxrequired .startswith ("Always" ):
242262 print (f"Skipping optional component { name :>20} " )
243- return # continue to next submodule
263+ return # continue to next submodule
244264 optional = "AlwaysOptional" in requiredlist
245265
246266 if fxrequired in requiredlist :
@@ -253,11 +273,16 @@ async def update_submodule(name, requiredlist, force):
253273 newrequiredlist = ["AlwaysRequired" ]
254274 if optional :
255275 newrequiredlist .append ("AlwaysOptional" )
256- await submodules_update (gitsubmodules , repodir , newrequiredlist , force = force )
276+ await submodules_update (
277+ gitsubmodules , repodir , newrequiredlist , force = force
278+ )
257279
258- tasks = [update_submodule (name , requiredlist , force ) for name in gitmodules .sections ()]
280+ tasks = [
281+ update_submodule (name , requiredlist , force ) for name in gitmodules .sections ()
282+ ]
259283 await asyncio .gather (* tasks )
260284
285+
261286def local_mods_output ():
262287 text = """\
263288 The submodules labeled with 'M' above are not in a clean state.
@@ -271,7 +296,8 @@ def local_mods_output():
271296"""
272297 print (text )
273298
274- def submodules_test (gitmodules , root_dir ):
299+
300+ def submodules_test (gitmodules , root_dir , no_mods_details = False ):
275301 """
276302 This function tests the git submodules based on the provided parameters.
277303
@@ -282,12 +308,15 @@ def submodules_test(gitmodules, root_dir):
282308 Parameters:
283309 gitmodules (ConfigParser): The gitmodules configuration.
284310 root_dir (str): The root directory for the git operation.
311+ no_mods_details (bool, optional): If True, suppress details on local mods in status output
285312
286313 Returns:
287314 int: The number of test failures.
288315 """
289316 # First check that fxtags are present and in sync with submodule hashes
290- testfails , localmods , needsupdate = submodules_status (gitmodules , root_dir )
317+ testfails , localmods , needsupdate = submodules_status (
318+ gitmodules , root_dir , no_mods_details = no_mods_details
319+ )
291320 print ("" )
292321 # Then make sure that urls are consistant with fxurls (not forks and not ssh)
293322 # and that sparse checkout files exist
@@ -315,14 +344,17 @@ def main():
315344 includelist ,
316345 excludelist ,
317346 force ,
347+ no_mods_details ,
318348 action ,
319349 ) = commandline_arguments ()
320350 # Get a logger for the package
321351 global logger
322352 logger = logging .getLogger (__name__ )
323353
324- logger .info ("action is {} root_dir={} file_name={}" .format (action , root_dir , file_name ))
325-
354+ logger .info (
355+ "action is {} root_dir={} file_name={}" .format (action , root_dir , file_name )
356+ )
357+
326358 if not root_dir or not os .path .isfile (os .path .join (root_dir , file_name )):
327359 if root_dir :
328360 file_path = utils .find_upwards (root_dir , file_name )
@@ -352,15 +384,17 @@ def main():
352384 if action == "update" :
353385 asyncio .run (submodules_update (gitmodules , root_dir , fxrequired , force ))
354386 elif action == "status" :
355- tfails , lmods , updates = submodules_status (gitmodules , root_dir , toplevel = True )
387+ tfails , lmods , updates = submodules_status (
388+ gitmodules , root_dir , toplevel = True , no_mods_details = no_mods_details
389+ )
356390 if tfails + lmods + updates > 0 :
357391 print (
358392 f" testfails = { tfails } , local mods = { lmods } , needs updates { updates } \n "
359393 )
360394 if lmods > 0 :
361395 local_mods_output ()
362396 elif action == "test" :
363- retval = submodules_test (gitmodules , root_dir )
397+ retval = submodules_test (gitmodules , root_dir , no_mods_details = no_mods_details )
364398 else :
365399 utils .fatal_error (f"unrecognized action request { action } " )
366400 return retval
0 commit comments