@@ -24,7 +24,7 @@ pub enum SpirvSource {
24
24
/// then the source of `rust-gpu` is `Git`.
25
25
///
26
26
/// `(String, String)` is the repo source and revision hash or tag.
27
- Git ( ( String , String ) ) ,
27
+ Git { url : String , rev : String } ,
28
28
/// If the shader specifies a version like:
29
29
/// `spirv-std = { path = "/path/to/rust-gpu" ... }`
30
30
/// then the source of `rust-gpu` is `Path`.
@@ -39,7 +39,11 @@ impl core::fmt::Display for SpirvSource {
39
39
reason = "It's a core library trait implementation"
40
40
) ]
41
41
fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
42
- format ! ( "{}+{}" , self . to_repo( ) , self . to_version( ) ) . fmt ( f)
42
+ match self {
43
+ SpirvSource :: CratesIO ( version) => f. write_str ( version) ,
44
+ SpirvSource :: Git { url, rev } => f. write_str ( & format ! ( "{url}+{rev}" ) ) ,
45
+ SpirvSource :: Path ( ( a, b) ) => f. write_str ( & format ! ( "{a}+{b}" ) ) ,
46
+ }
43
47
}
44
48
}
45
49
@@ -65,15 +69,15 @@ impl SpirvSource {
65
69
pub fn to_version ( & self ) -> String {
66
70
match self {
67
71
Self :: CratesIO ( version) | Self :: Path ( ( _, version) ) => version. to_string ( ) ,
68
- Self :: Git ( ( _ , revision ) ) => revision . to_string ( ) ,
72
+ Self :: Git { rev , .. } => rev . to_string ( ) ,
69
73
}
70
74
}
71
75
72
76
/// Convert the source to just its repo or path.
73
77
fn to_repo ( & self ) -> String {
74
78
match self {
75
79
Self :: CratesIO ( _) => RUST_GPU_REPO . to_owned ( ) ,
76
- Self :: Git ( ( repo , _ ) ) => repo . to_owned ( ) ,
80
+ Self :: Git { url , .. } => url . to_owned ( ) ,
77
81
Self :: Path ( ( path, _) ) => path. to_owned ( ) ,
78
82
}
79
83
}
@@ -162,7 +166,7 @@ impl SpirvSource {
162
166
}
163
167
164
168
/// Get the shader crate's `spirv_std = ...` definition in its `Cargo.toml`
165
- fn get_spirv_std_dep_definition ( shader_crate_path : & std:: path:: PathBuf ) -> Self {
169
+ pub fn get_spirv_std_dep_definition ( shader_crate_path : & std:: path:: PathBuf ) -> Self {
166
170
log:: debug!( "Running `cargo tree` on {}" , shader_crate_path. display( ) ) ;
167
171
let output_cargo_tree = std:: process:: Command :: new ( "cargo" )
168
172
. current_dir ( shader_crate_path)
@@ -178,6 +182,7 @@ impl SpirvSource {
178
182
let maybe_spirv_std_def = cargo_tree_string
179
183
. lines ( )
180
184
. find ( |line| line. contains ( "spirv-std" ) ) ;
185
+ log:: trace!( " found {maybe_spirv_std_def:?}" ) ;
181
186
182
187
let Some ( spirv_std_def) = maybe_spirv_std_def else {
183
188
panic ! ( "`spirv-std` not found in shader's `Cargo.toml` at {shader_crate_path:?}:\n {cargo_tree_string}" ) ;
@@ -191,6 +196,7 @@ impl SpirvSource {
191
196
/// Which would return:
192
197
/// `SpirvSource::Git("https://github.com/Rust-GPU/rust-gpu", "54f6978c")`
193
198
fn parse_spirv_std_source_and_version ( spirv_std_def : & str ) -> Self {
199
+ log:: trace!( "parsing spirv-std source and version from def: '{spirv_std_def}'" ) ;
194
200
let parts: Vec < String > = spirv_std_def. split_whitespace ( ) . map ( String :: from) . collect ( ) ;
195
201
let version = parts
196
202
. get ( 1 )
@@ -202,9 +208,21 @@ impl SpirvSource {
202
208
let mut source_string = parts. get ( 2 ) . unwrap ( ) . to_owned ( ) ;
203
209
source_string = source_string. replace ( [ '(' , ')' ] , "" ) ;
204
210
211
+ // Unfortunately Uri ignores the fragment/hash portion of the Uri.
212
+ //
213
+ // There's been a ticket open for years:
214
+ // <https://github.com/hyperium/http/issues/127>
215
+ //
216
+ // So here we'll parse the fragment out of the source string by hand
205
217
let uri = source_string. parse :: < http:: Uri > ( ) . unwrap ( ) ;
218
+ let maybe_hash = if source_string. contains ( '#' ) {
219
+ let splits = source_string. split ( '#' ) ;
220
+ splits. last ( ) . map ( std:: borrow:: ToOwned :: to_owned)
221
+ } else {
222
+ None
223
+ } ;
206
224
if uri. scheme ( ) . is_some ( ) {
207
- source = Self :: parse_git_source ( version, & uri) ;
225
+ source = Self :: parse_git_source ( version, & uri, maybe_hash ) ;
208
226
} else {
209
227
source = Self :: Path ( ( source_string, version) ) ;
210
228
}
@@ -216,24 +234,29 @@ impl SpirvSource {
216
234
}
217
235
218
236
/// Parse a Git source like: `https://github.com/Rust-GPU/rust-gpu?rev=54f6978c#54f6978c`
219
- fn parse_git_source ( version : String , uri : & http:: Uri ) -> Self {
220
- let mut revision = version;
221
-
237
+ fn parse_git_source ( version : String , uri : & http:: Uri , fragment : Option < String > ) -> Self {
238
+ log:: trace!(
239
+ "parsing git source from version: '{version}' and uri: '{uri}' and fragment: {}" ,
240
+ fragment. as_deref( ) . unwrap_or( "?" )
241
+ ) ;
222
242
let repo = format ! (
223
243
"{}://{}{}" ,
224
244
uri. scheme( ) . unwrap( ) ,
225
245
uri. host( ) . unwrap( ) ,
226
246
uri. path( )
227
247
) ;
228
248
229
- if let Some ( query) = uri. query ( ) {
230
- let marker = "rev=" ;
231
- let sanity_check = query. contains ( marker) && query. split ( '=' ) . count ( ) == 2 ;
232
- assert ! ( sanity_check, "revision not found in Git URI: {query}" ) ;
233
- revision = query. replace ( marker, "" ) ;
234
- }
249
+ let rev = uri. query ( ) . map_or_else (
250
+ || fragment. unwrap_or ( version) ,
251
+ |query| {
252
+ let marker = "rev=" ;
253
+ let sanity_check = query. contains ( marker) && query. split ( '=' ) . count ( ) == 2 ;
254
+ assert ! ( sanity_check, "revision not found in Git URI: {query}" ) ;
255
+ query. replace ( marker, "" )
256
+ } ,
257
+ ) ;
235
258
236
- Self :: Git ( ( repo, revision ) )
259
+ Self :: Git { url : repo, rev }
237
260
}
238
261
239
262
/// `git clone` the `rust-gpu` repo. We use it to get the required Rust toolchain to compile
@@ -283,10 +306,10 @@ mod test {
283
306
let source = SpirvSource :: get_spirv_std_dep_definition ( & shader_template_path) ;
284
307
assert_eq ! (
285
308
source,
286
- SpirvSource :: Git ( (
287
- "https://github.com/Rust-GPU/rust-gpu" . to_owned( ) ,
288
- "82a0f69" . to_owned( )
289
- ) )
309
+ SpirvSource :: Git {
310
+ url : "https://github.com/Rust-GPU/rust-gpu" . to_owned( ) ,
311
+ rev : "82a0f69" . to_owned( )
312
+ }
290
313
) ;
291
314
}
292
315
@@ -297,10 +320,23 @@ mod test {
297
320
let source = SpirvSource :: parse_spirv_std_source_and_version ( definition) ;
298
321
assert_eq ! (
299
322
source,
300
- SpirvSource :: Git ( (
301
- "https://github.com/Rust-GPU/rust-gpu" . to_owned( ) ,
302
- "82a0f69" . to_owned( )
303
- ) )
323
+ SpirvSource :: Git {
324
+ url: "https://github.com/Rust-GPU/rust-gpu" . to_owned( ) ,
325
+ rev: "82a0f69" . to_owned( )
326
+ }
327
+ ) ;
328
+ }
329
+
330
+ #[ test_log:: test]
331
+ fn parsing_spirv_std_dep_for_git_source_hash ( ) {
332
+ let definition = "spirv-std v9.9.9 (https://github.com/Rust-GPU/rust-gpu#82a0f69) (*)" ;
333
+ let source = SpirvSource :: parse_spirv_std_source_and_version ( definition) ;
334
+ assert_eq ! (
335
+ source,
336
+ SpirvSource :: Git {
337
+ url: "https://github.com/Rust-GPU/rust-gpu" . to_owned( ) ,
338
+ rev: "82a0f69" . to_owned( )
339
+ }
304
340
) ;
305
341
}
306
342
}
0 commit comments