33import time
44import shlex
55import pathlib
6+ import re
67import subprocess
78
8- # Target will be a board, "test", "docs", "mpy-cross-mac", or "windows"
9- TARGET = sys .argv [1 ]
9+ TOP = pathlib .Path (__file__ ).parent .parent
10+
11+
12+ def _git_version ():
13+ version_str = subprocess .check_output (["git" , "--version" ], encoding = "ascii" , errors = "replace" )
14+ version_str = re .search ("([0-9]\.*)*[0-9]" , version_str ).group (0 )
15+ return tuple (int (part ) for part in version_str .split ("." ))
16+
17+
18+ clone_supports_filter = (
19+ False if "NO_USE_CLONE_FILTER" in os .environ else _git_version () >= (2 , 27 , 0 )
20+ )
21+
22+ if clone_supports_filter :
23+ filter_maybe = "--filter=blob:none"
24+ else :
25+ filter_maybe = ""
26+
27+
28+ def _all_submodules ():
29+ submodule_str = subprocess .check_output (
30+ ["git" , "submodule" , "status" ], encoding = "ascii" , errors = "replace" , cwd = TOP
31+ )
32+ return [row .split ()[1 ] for row in submodule_str .strip ().split ("\n " )]
33+
34+
35+ all_submodules = _all_submodules ()
36+
37+
38+ def matching_submodules (s ):
39+ if s .endswith ("/" ):
40+ return [m for m in all_submodules if m .startswith (s )]
41+ elif s not in all_submodules :
42+ raise ValueError (f"{ s !r} is not a submodule" )
43+ return [s ]
44+
1045
1146# Submodules needed by port builds outside of their ports directory.
1247# Should we try and detect these?
4984}
5085
5186
52- def run (title , command , check = True ):
87+ def run (title , command , cwd ):
5388 print ("::group::" + title , flush = True )
54- print (command , flush = True )
89+ print (f" { command } (in { cwd } )" , flush = True )
5590 start = time .monotonic ()
5691 try :
57- subprocess .run (shlex .split (command ), stderr = subprocess .STDOUT , check = check )
92+ subprocess .run (shlex .split (command ), stderr = subprocess .STDOUT , check = True , cwd = cwd )
5893 finally :
5994 print ("::endgroup::" , flush = True )
6095 print ("Duration:" , time .monotonic () - start , flush = True )
6196
6297
98+ def matching_submodules (where ):
99+ for m in all_submodules :
100+ if m in where :
101+ yield m
102+ for w in where :
103+ if m .startswith (f"{ w } /" ):
104+ yield m
105+ break
106+
107+
108+ def fetch (where ):
109+ if clone_supports_filter :
110+ run (
111+ "Init submodules (using filter)" ,
112+ f"git submodule update --init { filter_maybe } { ' ' .join (where )} " ,
113+ cwd = TOP ,
114+ )
115+ else :
116+ run (
117+ "Init submodules (using depth)" ,
118+ f"git submodule update --init --depth 1 { ' ' .join (where )} " ,
119+ cwd = TOP ,
120+ )
121+ for s in matching_submodules ([w for w in where if w .startswith ("frozen" )]):
122+ run (f"Ensure tags exist in { s } " , "git fetch --tags --depth 1" , cwd = TOP / s )
123+
124+
63125def set_output (name , value ):
64126 if "GITHUB_OUTPUT" in os .environ :
65127 with open (os .environ ["GITHUB_OUTPUT" ], "at" ) as f :
66128 print (f"{ name } ={ value } " , file = f )
67129 else :
68- print (f"Would set GitHub actions output { name } to ' { value } ' " )
130+ print (f"{ name } : { value !r } " )
69131
70132
71- def main ():
133+ SUBMODULES_BY_TARGET = {}
134+
135+
136+ def main (target ):
72137 submodules = []
73- submodules_tags = []
74138
75- print ("Target:" , TARGET )
139+ print ("Target:" , target )
76140
77- if TARGET == "scheduler" :
78- # submodules = ["tools/"]
141+ if target == "all" :
142+ submodules = ["." , "frozen" ] # explicitly list frozen to get tags
143+ elif target == "scheduler" :
79144 submodules = ["extmod/ulab" , "lib/" , "tools/" ]
80- elif TARGET == "tests" :
81- submodules = ["extmod/ulab" , "lib/" , "tools/" ]
82- submodules_tags = [
145+ elif target == "tests" :
146+ submodules = [
147+ "extmod/ulab" ,
148+ "lib/" ,
149+ "tools/" ,
83150 "frozen/Adafruit_CircuitPython_asyncio" ,
84151 "frozen/Adafruit_CircuitPython_Ticks" ,
85152 ]
86- elif TARGET == "docs" :
153+ elif target == "docs" :
87154 # used in .readthedocs.yml to generate RTD
88- submodules = ["extmod/ulab" ]
89- submodules_tags = ["frozen/" ]
90- elif TARGET == "mpy-cross" or TARGET == "mpy-cross-mac" :
155+ submodules = ["extmod/ulab" , "frozen" ]
156+ elif target == "mpy-cross" or target == "mpy-cross-mac" :
91157 submodules = ["tools/" ] # for huffman
92- elif TARGET == "windows" :
158+ elif target == "windows" :
93159 # This builds one board from a number of ports so fill out a bunch of submodules
94160 for port in ("atmel-samd" , "nrf" , "raspberrypi" , "stm" ):
95161 submodules .append (f"ports/{ port } " )
96162 submodules .extend (PORT_DEPS [port ])
97163 unique_submodules = set (submodules )
98164 submodules = list (unique_submodules )
99- elif TARGET == "website" :
100- submodules = ["tools/adabot/" ]
101- submodules_tags = ["frozen/" ]
102- elif TARGET == "pre-commit" :
165+ elif target == "website" :
166+ submodules = ["tools/adabot" , "frozen" ]
167+ elif target == "pre-commit" :
103168 submodules = ["extmod/ulab" ]
169+ elif target in PORT_DEPS :
170+ submodules = ["data" , "extmod" , "lib" , "tools" , "frozen" , f"ports/{ target } " ] + PORT_DEPS [
171+ target
172+ ]
104173 else :
105- p = list (pathlib .Path ("." ).glob (f"ports/*/boards/{ TARGET } /mpconfigboard.mk" ))
174+ p = list (pathlib .Path (TOP ).glob (f"ports/*/boards/{ target } /mpconfigboard.mk" ))
106175 if not p :
107- raise RuntimeError (f"Unsupported target: { TARGET } " )
176+ raise RuntimeError (f"Unsupported target: { target } " )
108177
109178 config = p [0 ]
110179 # Add the ports folder to init submodules
111180 port_folder = config .parents [2 ]
112181 port = port_folder .name
113- submodules .append (str ( port_folder ) )
182+ submodules .append (f"ports/ { port } " )
114183 submodules .append ("tools/" ) # for huffman
115184 submodules .extend (PORT_DEPS [port ])
116185 with config .open () as f :
@@ -123,24 +192,14 @@ def main():
123192 if lib_folder .count ("/" ) > 1 :
124193 lib_folder = lib_folder .split ("/" , maxsplit = 2 )
125194 lib_folder = "/" .join (lib_folder [:2 ])
126- submodules_tags .append (lib_folder )
127-
128- print ("Submodule tags[Y]:" , submodules_tags )
129- print ("Submodule tags[N]:" , submodules )
195+ submodules .append (lib_folder )
130196
131- if submodules_tags :
132- run (
133- "Init the submodules with tags" ,
134- f"git submodule update --init { ' ' .join (submodules_tags )} " ,
135- )
197+ print ("Submodules:" , " " .join (submodules ))
136198
137199 if submodules :
138- run (
139- "Init the submodules without tags" ,
140- f"git submodule update --init --depth=1 { ' ' .join (submodules )} " ,
141- )
200+ fetch (submodules )
142201
143- for submodule in submodules_tags :
202+ for submodule in submodules :
144203 if submodule .startswith ("frozen" ):
145204 set_output ("frozen_tags" , True )
146205 break
@@ -149,4 +208,11 @@ def main():
149208
150209
151210if __name__ == "__main__" :
152- main ()
211+ if len (sys .argv ) < 2 :
212+ raise SystemExit ("Usage: ci_fetch_deps dep..." )
213+
214+ run ("Sync submodule URLs" , "git submodule sync --quiet" , cwd = TOP )
215+
216+ # Target will be a board, "test", "docs", "mpy-cross-mac", or "windows"
217+ for target in sys .argv [1 :]:
218+ main (target )
0 commit comments