3
3
import time
4
4
import shlex
5
5
import pathlib
6
+ import re
6
7
import subprocess
7
8
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
+
10
45
11
46
# Submodules needed by port builds outside of their ports directory.
12
47
# Should we try and detect these?
66
101
}
67
102
68
103
69
- def run (title , command , check = True ):
104
+ def run (title , command , cwd ):
70
105
print ("::group::" + title , flush = True )
71
- print (command , flush = True )
106
+ print (f" { command } (in { cwd } )" , flush = True )
72
107
start = time .monotonic ()
73
108
try :
74
- subprocess .run (shlex .split (command ), stderr = subprocess .STDOUT , check = check )
109
+ subprocess .run (shlex .split (command ), stderr = subprocess .STDOUT , check = True , cwd = cwd )
75
110
finally :
76
111
print ("::endgroup::" , flush = True )
77
112
print ("Duration:" , time .monotonic () - start , flush = True )
78
113
79
114
115
+ def matching_submodules (where ):
116
+ for m in all_submodules :
117
+ if m in where :
118
+ yield m
119
+ for w in where :
120
+ if m .startswith (f"{ w } /" ):
121
+ yield m
122
+ break
123
+
124
+
125
+ def fetch (where ):
126
+ if clone_supports_filter :
127
+ run (
128
+ "Init submodules (using filter)" ,
129
+ f"git submodule update --init { filter_maybe } { ' ' .join (where )} " ,
130
+ cwd = TOP ,
131
+ )
132
+ else :
133
+ run (
134
+ "Init submodules (using depth)" ,
135
+ f"git submodule update --init --depth 1 { ' ' .join (where )} " ,
136
+ cwd = TOP ,
137
+ )
138
+ for s in matching_submodules ([w for w in where if w .startswith ("frozen" )]):
139
+ run (f"Ensure tags exist in { s } " , "git fetch --tags --depth 1" , cwd = TOP / s )
140
+
141
+
80
142
def set_output (name , value ):
81
143
if "GITHUB_OUTPUT" in os .environ :
82
144
with open (os .environ ["GITHUB_OUTPUT" ], "at" ) as f :
83
145
print (f"{ name } ={ value } " , file = f )
84
146
else :
85
- print (f"Would set GitHub actions output { name } to ' { value } ' " )
147
+ print (f"{ name } : { value !r } " )
86
148
87
149
88
- def main ():
150
+ SUBMODULES_BY_TARGET = {}
151
+
152
+
153
+ def main (target ):
89
154
submodules = []
90
- submodules_tags = []
91
155
92
- print ("Target:" , TARGET )
156
+ print ("Target:" , target )
93
157
94
- if TARGET == "scheduler" :
95
- # submodules = ["tools/"]
158
+ if target == "all" :
159
+ submodules = ["." , "frozen" ] # explicitly list frozen to get tags
160
+ elif target == "scheduler" :
96
161
submodules = ["extmod/ulab" , "lib/" , "tools/" ]
97
- elif TARGET == "tests" :
98
- submodules = ["extmod/ulab" , "lib/" , "tools/" ]
99
- submodules_tags = [
162
+ elif target == "tests" :
163
+ submodules = [
164
+ "extmod/ulab" ,
165
+ "lib/" ,
166
+ "tools/" ,
100
167
"frozen/Adafruit_CircuitPython_asyncio" ,
101
168
"frozen/Adafruit_CircuitPython_Ticks" ,
102
169
]
103
- elif TARGET == "docs" :
170
+ elif target == "docs" :
104
171
# used in .readthedocs.yml to generate RTD
105
- submodules = ["extmod/ulab" ]
106
- submodules_tags = ["frozen/" ]
107
- elif TARGET == "mpy-cross" or TARGET == "mpy-cross-mac" :
172
+ submodules = ["extmod/ulab" , "frozen" ]
173
+ elif target == "mpy-cross" or target == "mpy-cross-mac" :
108
174
submodules = ["tools/" ] # for huffman
109
- elif TARGET == "windows" :
175
+ elif target == "windows" :
110
176
# This builds one board from a number of ports so fill out a bunch of submodules
111
177
for port in ("atmel-samd" , "nrf" , "raspberrypi" , "stm" ):
112
178
submodules .append (f"ports/{ port } " )
113
179
submodules .extend (PORT_DEPS [port ])
114
180
unique_submodules = set (submodules )
115
181
submodules = list (unique_submodules )
116
- elif TARGET == "website" :
117
- submodules = ["tools/adabot/" ]
118
- submodules_tags = ["frozen/" ]
119
- elif TARGET == "pre-commit" :
182
+ elif target == "website" :
183
+ submodules = ["tools/adabot" , "frozen" ]
184
+ elif target == "pre-commit" :
120
185
submodules = ["extmod/ulab" ]
186
+ elif target in PORT_DEPS :
187
+ submodules = ["data" , "extmod" , "lib" , "tools" , "frozen" , f"ports/{ target } " ] + PORT_DEPS [
188
+ target
189
+ ]
121
190
else :
122
- p = list (pathlib .Path ("." ).glob (f"ports/*/boards/{ TARGET } /mpconfigboard.mk" ))
191
+ p = list (pathlib .Path (TOP ).glob (f"ports/*/boards/{ target } /mpconfigboard.mk" ))
123
192
if not p :
124
- raise RuntimeError (f"Unsupported target: { TARGET } " )
193
+ raise RuntimeError (f"Unsupported target: { target } " )
125
194
126
195
config = p [0 ]
127
196
# Add the ports folder to init submodules
128
197
port_folder = config .parents [2 ]
129
198
port = port_folder .name
130
- submodules .append (str ( port_folder ) )
199
+ submodules .append (f"ports/ { port } " )
131
200
submodules .append ("tools/" ) # for huffman
132
201
submodules .extend (PORT_DEPS [port ])
133
202
with config .open () as f :
@@ -140,24 +209,14 @@ def main():
140
209
if lib_folder .count ("/" ) > 1 :
141
210
lib_folder = lib_folder .split ("/" , maxsplit = 2 )
142
211
lib_folder = "/" .join (lib_folder [:2 ])
143
- submodules_tags .append (lib_folder )
144
-
145
- print ("Submodule tags[Y]:" , submodules_tags )
146
- print ("Submodule tags[N]:" , submodules )
212
+ submodules .append (lib_folder )
147
213
148
- if submodules_tags :
149
- run (
150
- "Init the submodules with tags" ,
151
- f"git submodule update --init { ' ' .join (submodules_tags )} " ,
152
- )
214
+ print ("Submodules:" , " " .join (submodules ))
153
215
154
216
if submodules :
155
- run (
156
- "Init the submodules without tags" ,
157
- f"git submodule update --init --depth=1 { ' ' .join (submodules )} " ,
158
- )
217
+ fetch (submodules )
159
218
160
- for submodule in submodules_tags :
219
+ for submodule in submodules :
161
220
if submodule .startswith ("frozen" ):
162
221
set_output ("frozen_tags" , True )
163
222
break
@@ -166,4 +225,11 @@ def main():
166
225
167
226
168
227
if __name__ == "__main__" :
169
- main ()
228
+ if len (sys .argv ) < 2 :
229
+ raise SystemExit ("Usage: ci_fetch_deps dep..." )
230
+
231
+ run ("Sync submodule URLs" , "git submodule sync --quiet" , cwd = TOP )
232
+
233
+ # Target will be a board, "test", "docs", "mpy-cross-mac", or "windows"
234
+ for target in sys .argv [1 :]:
235
+ main (target )
0 commit comments