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?
49
84
}
50
85
51
86
52
- def run (title , command , check = True ):
87
+ def run (title , command , cwd ):
53
88
print ("::group::" + title , flush = True )
54
- print (command , flush = True )
89
+ print (f" { command } (in { cwd } )" , flush = True )
55
90
start = time .monotonic ()
56
91
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 )
58
93
finally :
59
94
print ("::endgroup::" , flush = True )
60
95
print ("Duration:" , time .monotonic () - start , flush = True )
61
96
62
97
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
+
63
125
def set_output (name , value ):
64
126
if "GITHUB_OUTPUT" in os .environ :
65
127
with open (os .environ ["GITHUB_OUTPUT" ], "at" ) as f :
66
128
print (f"{ name } ={ value } " , file = f )
67
129
else :
68
- print (f"Would set GitHub actions output { name } to ' { value } ' " )
130
+ print (f"{ name } : { value !r } " )
69
131
70
132
71
- def main ():
133
+ SUBMODULES_BY_TARGET = {}
134
+
135
+
136
+ def main (target ):
72
137
submodules = []
73
- submodules_tags = []
74
138
75
- print ("Target:" , TARGET )
139
+ print ("Target:" , target )
76
140
77
- if TARGET == "scheduler" :
78
- # submodules = ["tools/"]
141
+ if target == "all" :
142
+ submodules = ["." , "frozen" ] # explicitly list frozen to get tags
143
+ elif target == "scheduler" :
79
144
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/" ,
83
150
"frozen/Adafruit_CircuitPython_asyncio" ,
84
151
"frozen/Adafruit_CircuitPython_Ticks" ,
85
152
]
86
- elif TARGET == "docs" :
153
+ elif target == "docs" :
87
154
# 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" :
91
157
submodules = ["tools/" ] # for huffman
92
- elif TARGET == "windows" :
158
+ elif target == "windows" :
93
159
# This builds one board from a number of ports so fill out a bunch of submodules
94
160
for port in ("atmel-samd" , "nrf" , "raspberrypi" , "stm" ):
95
161
submodules .append (f"ports/{ port } " )
96
162
submodules .extend (PORT_DEPS [port ])
97
163
unique_submodules = set (submodules )
98
164
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" :
103
168
submodules = ["extmod/ulab" ]
169
+ elif target in PORT_DEPS :
170
+ submodules = ["data" , "extmod" , "lib" , "tools" , "frozen" , f"ports/{ target } " ] + PORT_DEPS [
171
+ target
172
+ ]
104
173
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" ))
106
175
if not p :
107
- raise RuntimeError (f"Unsupported target: { TARGET } " )
176
+ raise RuntimeError (f"Unsupported target: { target } " )
108
177
109
178
config = p [0 ]
110
179
# Add the ports folder to init submodules
111
180
port_folder = config .parents [2 ]
112
181
port = port_folder .name
113
- submodules .append (str ( port_folder ) )
182
+ submodules .append (f"ports/ { port } " )
114
183
submodules .append ("tools/" ) # for huffman
115
184
submodules .extend (PORT_DEPS [port ])
116
185
with config .open () as f :
@@ -123,24 +192,14 @@ def main():
123
192
if lib_folder .count ("/" ) > 1 :
124
193
lib_folder = lib_folder .split ("/" , maxsplit = 2 )
125
194
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 )
130
196
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 ))
136
198
137
199
if submodules :
138
- run (
139
- "Init the submodules without tags" ,
140
- f"git submodule update --init --depth=1 { ' ' .join (submodules )} " ,
141
- )
200
+ fetch (submodules )
142
201
143
- for submodule in submodules_tags :
202
+ for submodule in submodules :
144
203
if submodule .startswith ("frozen" ):
145
204
set_output ("frozen_tags" , True )
146
205
break
@@ -149,4 +208,11 @@ def main():
149
208
150
209
151
210
if __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