3434import traceback
3535import urllib
3636import ssl
37+ import ctypes
3738
3839ssl ._create_default_https_context = ssl ._create_unverified_context
3940
6970
7071BOOTSTRAP_VERSION = "1.0.7 (2025)"
7172
73+ class Colors :
74+ GREEN = '\033 [92m'
75+ WARNING = '\033 [91m'
76+ NORMAL = '\033 [0m'
77+
7278SRC_DIR_BASE = "src"
7379ARCHIVE_DIR_BASE = "archives"
7480SNAPSHOT_DIR_BASE = "snapshots"
9399TOOL_COMMAND_TAR = "tar"
94100TOOL_COMMAND_UNZIP = "unzip"
95101
102+ ansi_console = True
103+
96104if platform .system () == "Windows" :
97105 os .environ ['CYGWIN' ] = "nodosfilewarning"
106+ ansi_console = False
107+ if sys .getwindowsversion ().major >= 10 :
108+ ansi_console = True
109+ kernel32 = ctypes .windll .kernel32
110+ handle = kernel32 .GetStdHandle (- 11 )
111+ mode = ctypes .c_uint32 ()
112+ kernel32 .GetConsoleMode (handle , ctypes .byref (mode ))
113+ kernel32 .SetConsoleMode (handle , mode .value | 0x0004 )
98114
99115if not sys .version_info [0 ] >= 3 :
100116 raise ValueError ("I require Python 3.0 or a later version" )
101117
102118def log (string ):
103119 print ("--- " + string )
104120
121+ def warning (string ):
122+ if ansi_console :
123+ print (Colors .WARNING , "--- " + string , Colors .NORMAL )
124+ else :
125+ print ("--- " + string )
105126
106127def dlog (string ):
107128 if DEBUG_OUTPUT :
@@ -232,13 +253,13 @@ def extractFile(filename, target_dir):
232253 try :
233254 zfile = zipfile .ZipFile (filename )
234255 except zipfile .BadZipFile :
235- print ("WARNING: Invalid ZIP file '" + filename + "'" )
256+ warning ("WARNING: Invalid ZIP file '" + filename + "'" )
236257 if os .path .exists (filename ) and os .path .getsize (filename ) == 0 :
237- print ("WARNING: Zero-sized file was deleted. Run the script again." )
258+ warning ("WARNING: Zero-sized file was deleted. Run the script again." )
238259 os .remove (filename )
239260 else :
240- print ("WARNING: Try deleting the cached file and run the script again." )
241- raise RuntimeError ("Updating to revision not implemented for SVN. " ) from None
261+ warning ("WARNING: Try deleting the cached file and run the script again." )
262+ raise RuntimeError ("Invalid ZIP file '" + filename + "' " ) from None
242263 extract_dir = os .path .commonprefix (zfile .namelist ())
243264 hasFolder = False
244265 for fname in zfile .namelist ():
@@ -331,7 +352,7 @@ def createArchiveFromDirectory(src_dir_name, archive_name, delete_existing_archi
331352
332353def downloadSCP (hostname , username , path , target_dir ):
333354 if not scp_available :
334- log ("ERROR: missing Python packages [paramiko, scp]; cannot continue." )
355+ warning ("ERROR: missing Python packages [paramiko, scp]; cannot continue." )
335356 raise RuntimeError ("Missing Python packages [paramiko, scp]; cannot continue." )
336357 ssh = paramiko .SSHClient ()
337358 ssh .load_system_host_keys ()
@@ -436,7 +457,7 @@ def applyPatchFile(patch_name, dir_name, pnum):
436457 arguments = argumentsBinary
437458 res = executeCommand (TOOL_COMMAND_PATCH + " --dry-run " + arguments , quiet = True )
438459 if res != 0 :
439- log ("ERROR: patch application failure; has this patch already been applied?" )
460+ warning ("ERROR: patch application failure; has this patch already been applied?" )
440461 executeCommand (TOOL_COMMAND_PATCH + " --dry-run " + arguments , printCommand = True )
441462 exit (255 )
442463 else :
@@ -462,7 +483,7 @@ def findToolCommand(command, paths_to_search, required = False):
462483 break ;
463484
464485 if required and not found :
465- log ("WARNING: command " + command + " not found, but required by script" )
486+ warning ("WARNING: command " + command + " not found, but required by script" )
466487
467488 dlog ("Found '" + command + "' as " + command_res )
468489 return command_res
@@ -472,16 +493,16 @@ def readJSONData(filename):
472493 try :
473494 json_data = open (filename ).read ()
474495 except :
475- log ("ERROR: Could not read JSON file: " + filename )
496+ warning ("ERROR: Could not read JSON file: " + filename )
476497 return None
477498
478499 try :
479500 data = json .loads (json_data )
480501 except json .JSONDecodeError as e :
481- log ("ERROR: Could not parse JSON document: {}\n {} (line {}:{})\n " .format (filename , e .msg , e .lineno , e .colno ))
502+ warning ("ERROR: Could not parse JSON document: {}\n {} (line {}:{})\n " .format (filename , e .msg , e .lineno , e .colno ))
482503 return None
483504 except :
484- log ("ERROR: Could not parse JSON document: " + filename )
505+ warning ("ERROR: Could not parse JSON document: " + filename )
485506 return None
486507
487508 return data
@@ -651,11 +672,11 @@ def main(argv):
651672 opt_names += opt_names_local
652673 dlog ("Name file contains: " + ", " .join (opt_names_local ))
653674 except :
654- log ("ERROR: cannot parse name file '" + name_file + "'" )
675+ warning ("ERROR: cannot parse name file '" + name_file + "'" )
655676 return - 1
656677
657678 if force_fallback and not FALLBACK_URL :
658- log ("Error: cannot force usage of the fallback location without specifying a fallback URL" )
679+ warning ("Error: cannot force usage of the fallback location without specifying a fallback URL" )
659680 return - 1 ;
660681
661682 state_filename = os .path .join (os .path .dirname (os .path .splitext (bootstrap_filename )[0 ]), \
@@ -673,7 +694,7 @@ def main(argv):
673694 # some sanity checking
674695 for library in data :
675696 if library .get ('name' , None ) is None :
676- log ("ERROR: Invalid schema: library object does not have a 'name'" )
697+ warning ("ERROR: Invalid schema: library object does not have a 'name'" )
677698 return - 1
678699
679700 # read local libraries data, if available
@@ -687,7 +708,7 @@ def main(argv):
687708 # some sanity checking
688709 for local_library in local_data :
689710 if local_library .get ('name' , None ) is None :
690- log ("ERROR: Invalid schema: local library object does not have a 'name'" )
711+ warning ("ERROR: Invalid schema: local library object does not have a 'name'" )
691712 return - 1
692713
693714 # merge canonical and local library data, if applicable; local libraries take precedence
@@ -775,10 +796,10 @@ def main(argv):
775796 # download source
776797 if source is not None :
777798 if 'type' not in source :
778- log ("ERROR: Invalid schema for '" + name + "': 'source' object must have a 'type'" )
799+ warning ("ERROR: Invalid schema for '" + name + "': 'source' object must have a 'type'" )
779800 return - 1
780801 if 'url' not in source :
781- log ("ERROR: Invalid schema for '" + name + "': 'source' object must have a 'url'" )
802+ warning ("ERROR: Invalid schema for '" + name + "': 'source' object must have a 'url'" )
782803 return - 1
783804 src_type = source ['type' ]
784805 src_url = source ['url' ]
@@ -872,10 +893,10 @@ def main(argv):
872893 # post-processing
873894 if post is not None :
874895 if 'type' not in post :
875- log ("ERROR: Invalid schema for '" + name + "': 'postprocess' object must have a 'type'" )
896+ warning ("ERROR: Invalid schema for '" + name + "': 'postprocess' object must have a 'type'" )
876897 return - 1
877898 if 'file' not in post :
878- log ("ERROR: Invalid schema for '" + name + "': 'postprocess' object must have a 'file'" )
899+ warning ("ERROR: Invalid schema for '" + name + "': 'postprocess' object must have a 'file'" )
879900 return - 1
880901 post_type = post ['type' ]
881902 post_file = post ['file' ]
@@ -885,7 +906,7 @@ def main(argv):
885906 elif post_type == "script" :
886907 runPythonScript (post_file )
887908 else :
888- log ("ERROR: Unknown post-processing type '" + post_type + "' for " + name )
909+ warning ("ERROR: Unknown post-processing type '" + post_type + "' for " + name )
889910 return - 1
890911
891912 # add to cached state
@@ -894,23 +915,23 @@ def main(argv):
894915 # write out cached state
895916 writeJSONData (sdata , state_filename )
896917 except urllib .error .URLError as e :
897- log ("ERROR: Failure to bootstrap library '" + name + "' (urllib.error.URLError: reason " + str (e .reason ) + ")" )
918+ warning ("ERROR: Failure to bootstrap library '" + name + "' (urllib.error.URLError: reason " + str (e .reason ) + ")" )
898919 if break_on_first_error :
899920 exit (- 1 )
900921 traceback .print_exc ()
901922 failed_libraries .append (name )
902923 except :
903- log ("ERROR: Failure to bootstrap library '" + name + "' (reason: " + str (sys .exc_info ()[0 ]) + ")" )
924+ warning ("ERROR: Failure to bootstrap library '" + name + "' (reason: " + str (sys .exc_info ()[0 ]) + ")" )
904925 if break_on_first_error :
905926 exit (- 1 )
906927 traceback .print_exc ()
907928 failed_libraries .append (name )
908929
909930 if failed_libraries :
910- log ("***************************************" )
911- log ("FAILURE to bootstrap the following libraries:" )
912- log (', ' .join (failed_libraries ))
913- log ("***************************************" )
931+ warning ("***************************************" )
932+ warning ("FAILURE to bootstrap the following libraries:" )
933+ warning (', ' .join (failed_libraries ))
934+ warning ("***************************************" )
914935 return - 1
915936
916937 log ("Finished" )
0 commit comments