@@ -36,16 +36,19 @@ use regex_lite::{Regex, RegexBuilder};
36
36
use std:: { ffi:: OsString , sync:: LazyLock } ;
37
37
use xshell:: Shell ;
38
38
39
- use crate :: util:: git_version_at_least;
39
+ use crate :: util:: { git_version_at_least, looks_like_git_sha } ;
40
40
41
41
/// Path within the repository where the CTS will be checked out.
42
42
const CTS_CHECKOUT_PATH : & str = "cts" ;
43
43
44
+ /// Path to git's `shallow` file.
45
+ const GIT_SHALLOW_PATH : & str = ".git/shallow" ;
46
+
44
47
/// Path within the repository to a file containing the git revision of the CTS to check out.
45
48
const CTS_REVISION_PATH : & str = "cts_runner/revision.txt" ;
46
49
47
50
/// URL of the CTS git repository.
48
- const CTS_GIT_URL : & str = "https://github.com/ gpuweb/cts.git " ;
51
+ const CTS_GITHUB_PATH : & str = "gpuweb/cts" ;
49
52
50
53
/// Path to default CTS test list.
51
54
const CTS_DEFAULT_TEST_LIST : & str = "cts_runner/test.lst" ;
@@ -56,6 +59,100 @@ struct TestLine {
56
59
pub fails_if : Vec < String > ,
57
60
}
58
61
62
+ fn have_git_sha ( shell : & Shell , sha : & str ) -> bool {
63
+ shell
64
+ . cmd ( "git" )
65
+ . args ( [ "cat-file" , "commit" , sha] )
66
+ . quiet ( )
67
+ . ignore_stdout ( )
68
+ . ignore_stderr ( )
69
+ . run ( )
70
+ . is_ok ( )
71
+ }
72
+
73
+ fn maybe_deepen_git_repo ( shell : & Shell , desired : & str ) -> anyhow:: Result < ( ) > {
74
+ if shell
75
+ . cmd ( "curl" )
76
+ . args ( [
77
+ "-f" ,
78
+ "-L" ,
79
+ "-I" ,
80
+ "-H" ,
81
+ "Accept: application/vnd.github+json" ,
82
+ "-H" ,
83
+ "X-GitHub-Api-Version: 2022-11-28" ,
84
+ ] )
85
+ . arg ( format ! (
86
+ "https://api.github.com/repos/{CTS_GITHUB_PATH}/commits/{desired}"
87
+ ) )
88
+ . quiet ( )
89
+ . ignore_stdout ( )
90
+ . ignore_stderr ( )
91
+ . run ( )
92
+ . is_err ( )
93
+ {
94
+ log:: warn!( "Not deepening repo because the desired CTS SHA was not found on GitHub." ) ;
95
+ return Ok ( ( ) ) ;
96
+ }
97
+
98
+ if !shell. path_exists ( GIT_SHALLOW_PATH ) {
99
+ log:: warn!( "Not deepening repo because it is not a shallow clone." ) ;
100
+ return Ok ( ( ) ) ;
101
+ }
102
+
103
+ let shallow = shell
104
+ . read_file ( GIT_SHALLOW_PATH )
105
+ . context ( format ! (
106
+ "Failed to read git shallow SHA from {GIT_SHALLOW_PATH}"
107
+ ) ) ?
108
+ . trim ( )
109
+ . to_string ( ) ;
110
+
111
+ if !looks_like_git_sha ( & shallow) {
112
+ log:: warn!(
113
+ "Automatic deepening of git repo requires a shallow clone with a single graft point"
114
+ ) ;
115
+ return Ok ( ( ) ) ;
116
+ }
117
+
118
+ let output = shell
119
+ . cmd ( "curl" )
120
+ . args ( [
121
+ "-f" ,
122
+ "-L" ,
123
+ "-H" ,
124
+ "Accept: application/vnd.github+json" ,
125
+ "-H" ,
126
+ "X-GitHub-Api-Version: 2022-11-28" ,
127
+ ] )
128
+ . arg ( format ! (
129
+ "https://api.github.com/repos/{CTS_GITHUB_PATH}/compare/{desired}...{shallow}"
130
+ ) )
131
+ . output ( )
132
+ . context ( "Error calling GitHub API" ) ?;
133
+
134
+ let gh_json: serde_json:: Map < String , serde_json:: Value > =
135
+ serde_json:: from_slice ( & output. stdout ) . context ( "Failed parsing GitHub API JSON" ) ?;
136
+
137
+ let Some ( deepen_count) = gh_json
138
+ . get ( "total_commits" )
139
+ . and_then ( serde_json:: Value :: as_u64)
140
+ else {
141
+ bail ! ( "missing or invalid total_commits" ) ;
142
+ } ;
143
+
144
+ log:: info!( "Fetching CTS with --deepen {deepen_count}" ) ;
145
+
146
+ shell
147
+ . cmd ( "git" )
148
+ . args ( [ "fetch" , "--deepen" , & deepen_count. to_string ( ) ] )
149
+ . quiet ( )
150
+ . run ( )
151
+ . context ( "Failed to deepen git repo" ) ?;
152
+
153
+ Ok ( ( ) )
154
+ }
155
+
59
156
pub fn run_cts (
60
157
shell : Shell ,
61
158
mut args : Arguments ,
@@ -142,7 +239,11 @@ pub fn run_cts(
142
239
}
143
240
let mut cmd = shell
144
241
. cmd ( "git" )
145
- . args ( [ "clone" , CTS_GIT_URL , CTS_CHECKOUT_PATH ] )
242
+ . args ( [
243
+ "clone" ,
244
+ & format ! ( "https://github.com/{CTS_GITHUB_PATH}.git" ) ,
245
+ CTS_CHECKOUT_PATH ,
246
+ ] )
146
247
. quiet ( ) ;
147
248
148
249
if git_version_at_least ( & shell, [ 2 , 49 , 0 ] ) ? {
@@ -187,23 +288,25 @@ pub fn run_cts(
187
288
}
188
289
189
290
// If we don't have the CTS commit we want, try to fetch it.
190
- if shell
191
- . cmd ( "git" )
192
- . args ( [ "cat-file" , "commit" , & cts_revision] )
193
- . quiet ( )
194
- . ignore_stdout ( )
195
- . ignore_stderr ( )
196
- . run ( )
197
- . is_err ( )
198
- {
199
- log:: info!( "Fetching CTS" ) ;
291
+ if !have_git_sha ( & shell, & cts_revision) {
292
+ log:: info!( "Desired SHA not found, fetching CTS" ) ;
200
293
shell
201
294
. cmd ( "git" )
202
295
. args ( [ "fetch" , "--quiet" ] )
203
296
. quiet ( )
204
297
. run ( )
205
298
. context ( "Failed to fetch CTS" ) ?;
206
299
}
300
+
301
+ // If we still don't have the commit we want, maybe we need more history.
302
+ if !have_git_sha ( & shell, & cts_revision) {
303
+ log:: info!( "Desired SHA still not found, checking if missing from shallow clone" ) ;
304
+ maybe_deepen_git_repo ( & shell, & cts_revision) ?;
305
+ }
306
+
307
+ if !have_git_sha ( & shell, & cts_revision) {
308
+ bail ! ( "Unable to obtain the desired CTS revision {cts_revision}" ) ;
309
+ }
207
310
} else {
208
311
shell. change_dir ( CTS_CHECKOUT_PATH ) ;
209
312
}
0 commit comments