@@ -224,6 +224,15 @@ enum DirectoryRoot {
224
224
StandaloneTest ,
225
225
}
226
226
227
+ /// Don't add a suffix to the archive name as `args` are platform dependent, none-deterministic,
228
+ /// or otherwise don't influence the content of the archive.
229
+ /// Note that this also means that `args` won't be used to control the hash of the archive itself.
230
+ #[ derive( Copy , Clone ) ]
231
+ enum ArgsInHash {
232
+ Yes ,
233
+ No ,
234
+ }
235
+
227
236
/// Return the path to the `<crate-root>/tests/fixtures/<path>` directory.
228
237
pub fn fixture_path ( path : impl AsRef < Path > ) -> PathBuf {
229
238
fixture_path_inner ( path, DirectoryRoot :: IntegrationTest )
@@ -309,7 +318,19 @@ pub fn scripted_fixture_writable_with_args(
309
318
args : impl IntoIterator < Item = impl Into < String > > ,
310
319
mode : Creation ,
311
320
) -> Result < tempfile:: TempDir > {
312
- scripted_fixture_writable_with_args_inner ( script_name, args, mode, DirectoryRoot :: IntegrationTest )
321
+ scripted_fixture_writable_with_args_inner ( script_name, args, mode, DirectoryRoot :: IntegrationTest , ArgsInHash :: Yes )
322
+ }
323
+
324
+ /// Like [`scripted_fixture_writable()`], but passes `args` to `script_name` while providing control over
325
+ /// the way files are created with `mode`.
326
+ ///
327
+ /// See [`scripted_fixture_read_only_with_args_single_archive()`] for important details on what `single_archive` means.
328
+ pub fn scripted_fixture_writable_with_args_single_archive (
329
+ script_name : impl AsRef < Path > ,
330
+ args : impl IntoIterator < Item = impl Into < String > > ,
331
+ mode : Creation ,
332
+ ) -> Result < tempfile:: TempDir > {
333
+ scripted_fixture_writable_with_args_inner ( script_name, args, mode, DirectoryRoot :: IntegrationTest , ArgsInHash :: No )
313
334
}
314
335
315
336
/// Like [`scripted_fixture_writable_with_args`], but does not prefix the fixture directory with `tests`
@@ -318,24 +339,36 @@ pub fn scripted_fixture_writable_with_args_standalone(
318
339
args : impl IntoIterator < Item = impl Into < String > > ,
319
340
mode : Creation ,
320
341
) -> Result < tempfile:: TempDir > {
321
- scripted_fixture_writable_with_args_inner ( script_name, args, mode, DirectoryRoot :: StandaloneTest )
342
+ scripted_fixture_writable_with_args_inner ( script_name, args, mode, DirectoryRoot :: StandaloneTest , ArgsInHash :: Yes )
343
+ }
344
+
345
+ /// Like [`scripted_fixture_writable_with_args`], but does not prefix the fixture directory with `tests`
346
+ ///
347
+ /// See [`scripted_fixture_read_only_with_args_single_archive()`] for important details on what `single_archive` means.
348
+ pub fn scripted_fixture_writable_with_args_standalone_single_archive (
349
+ script_name : & str ,
350
+ args : impl IntoIterator < Item = impl Into < String > > ,
351
+ mode : Creation ,
352
+ ) -> Result < tempfile:: TempDir > {
353
+ scripted_fixture_writable_with_args_inner ( script_name, args, mode, DirectoryRoot :: StandaloneTest , ArgsInHash :: No )
322
354
}
323
355
324
356
fn scripted_fixture_writable_with_args_inner (
325
357
script_name : impl AsRef < Path > ,
326
358
args : impl IntoIterator < Item = impl Into < String > > ,
327
359
mode : Creation ,
328
360
root : DirectoryRoot ,
361
+ args_in_hash : ArgsInHash ,
329
362
) -> Result < tempfile:: TempDir > {
330
363
let dst = tempfile:: TempDir :: new ( ) ?;
331
364
Ok ( match mode {
332
365
Creation :: CopyFromReadOnly => {
333
- let ro_dir = scripted_fixture_read_only_with_args_inner ( script_name, args, None , root) ?;
366
+ let ro_dir = scripted_fixture_read_only_with_args_inner ( script_name, args, None , root, args_in_hash ) ?;
334
367
copy_recursively_into_existing_dir ( ro_dir, dst. path ( ) ) ?;
335
368
dst
336
369
}
337
370
Creation :: ExecuteScript => {
338
- scripted_fixture_read_only_with_args_inner ( script_name, args, dst. path ( ) . into ( ) , root) ?;
371
+ scripted_fixture_read_only_with_args_inner ( script_name, args, dst. path ( ) . into ( ) , root, args_in_hash ) ?;
339
372
dst
340
373
}
341
374
} )
@@ -365,22 +398,49 @@ pub fn scripted_fixture_read_only_with_args(
365
398
script_name : impl AsRef < Path > ,
366
399
args : impl IntoIterator < Item = impl Into < String > > ,
367
400
) -> Result < PathBuf > {
368
- scripted_fixture_read_only_with_args_inner ( script_name, args, None , DirectoryRoot :: IntegrationTest )
401
+ scripted_fixture_read_only_with_args_inner ( script_name, args, None , DirectoryRoot :: IntegrationTest , ArgsInHash :: Yes )
402
+ }
403
+
404
+ /// Like `scripted_fixture_read_only()`], but passes `args` to `script_name`.
405
+ ///
406
+ /// Also, don't add a suffix to the archive name as `args` are platform dependent, none-deterministic,
407
+ /// or otherwise don't influence the content of the archive.
408
+ /// Note that this also means that `args` won't be used to control the hash of the archive itself.
409
+ ///
410
+ /// Sometimes, this should be combined with adding the archive name to `.gitignore` to prevent its creation
411
+ /// in the first place.
412
+ ///
413
+ /// Note that suffixing archives by default helps to learn what calls are made, and forces the author to
414
+ /// think about what should be done to get it right.
415
+ pub fn scripted_fixture_read_only_with_args_single_archive (
416
+ script_name : impl AsRef < Path > ,
417
+ args : impl IntoIterator < Item = impl Into < String > > ,
418
+ ) -> Result < PathBuf > {
419
+ scripted_fixture_read_only_with_args_inner ( script_name, args, None , DirectoryRoot :: IntegrationTest , ArgsInHash :: No )
369
420
}
370
421
371
422
/// Like [`scripted_fixture_read_only_with_args()`], but does not prefix the fixture directory with `tests`
372
423
pub fn scripted_fixture_read_only_with_args_standalone (
373
424
script_name : impl AsRef < Path > ,
374
425
args : impl IntoIterator < Item = impl Into < String > > ,
375
426
) -> Result < PathBuf > {
376
- scripted_fixture_read_only_with_args_inner ( script_name, args, None , DirectoryRoot :: StandaloneTest )
427
+ scripted_fixture_read_only_with_args_inner ( script_name, args, None , DirectoryRoot :: StandaloneTest , ArgsInHash :: Yes )
428
+ }
429
+
430
+ /// Like [`scripted_fixture_read_only_with_args_standalone()`], only has a single archive.
431
+ pub fn scripted_fixture_read_only_with_args_standalone_single_archive (
432
+ script_name : impl AsRef < Path > ,
433
+ args : impl IntoIterator < Item = impl Into < String > > ,
434
+ ) -> Result < PathBuf > {
435
+ scripted_fixture_read_only_with_args_inner ( script_name, args, None , DirectoryRoot :: StandaloneTest , ArgsInHash :: No )
377
436
}
378
437
379
438
fn scripted_fixture_read_only_with_args_inner (
380
439
script_name : impl AsRef < Path > ,
381
440
args : impl IntoIterator < Item = impl Into < String > > ,
382
441
destination_dir : Option < & Path > ,
383
442
root : DirectoryRoot ,
443
+ args_in_hash : ArgsInHash ,
384
444
) -> Result < PathBuf > {
385
445
// Assure tempfiles get removed when aborting the test.
386
446
gix_tempfile:: signal:: setup (
@@ -414,11 +474,23 @@ fn scripted_fixture_read_only_with_args_inner(
414
474
415
475
let script_basename = script_location. file_stem ( ) . unwrap_or ( script_location. as_os_str ( ) ) ;
416
476
let archive_file_path = fixture_path_inner (
417
- Path :: new ( "generated-archives" ) . join ( format ! (
418
- "{}.tar{}" ,
419
- script_basename. to_str( ) . expect( "valid UTF-8" ) ,
420
- if cfg!( feature = "xz" ) { ".xz" } else { "" }
421
- ) ) ,
477
+ {
478
+ let suffix = match args_in_hash {
479
+ ArgsInHash :: Yes => {
480
+ let mut suffix = args. join ( "_" ) ;
481
+ if !suffix. is_empty ( ) {
482
+ suffix. insert ( 0 , '_' ) ;
483
+ }
484
+ suffix. replace ( [ '\\' , '/' , ' ' , '.' ] , "_" )
485
+ }
486
+ ArgsInHash :: No => "" . into ( ) ,
487
+ } ;
488
+ Path :: new ( "generated-archives" ) . join ( format ! (
489
+ "{}{suffix}.tar{}" ,
490
+ script_basename. to_str( ) . expect( "valid UTF-8" ) ,
491
+ if cfg!( feature = "xz" ) { ".xz" } else { "" }
492
+ ) )
493
+ } ,
422
494
root,
423
495
) ;
424
496
let ( force_run, script_result_directory) = destination_dir. map_or_else (
@@ -447,7 +519,15 @@ fn scripted_fixture_read_only_with_args_inner(
447
519
std:: fs:: remove_dir_all ( & script_result_directory) . map_err ( |err| format ! ( "Failed to remove '{script_result_directory:?}', please try to do that by hand. Original error: {err}" ) ) ?
448
520
}
449
521
std:: fs:: create_dir_all ( & script_result_directory) ?;
450
- match extract_archive ( & archive_file_path, & script_result_directory, script_identity) {
522
+ let script_identity_for_archive = match args_in_hash {
523
+ ArgsInHash :: Yes => script_identity,
524
+ ArgsInHash :: No => 0 ,
525
+ } ;
526
+ match extract_archive (
527
+ & archive_file_path,
528
+ & script_result_directory,
529
+ script_identity_for_archive,
530
+ ) {
451
531
Ok ( ( archive_id, platform) ) => {
452
532
eprintln ! (
453
533
"Extracted fixture from archive '{}' ({}, {:?})" ,
@@ -489,12 +569,15 @@ fn scripted_fixture_read_only_with_args_inner(
489
569
output. stdout. as_bstr( ) ,
490
570
output. stderr. as_bstr( )
491
571
) ;
492
- create_archive_if_not_on_ci ( & script_result_directory, & archive_file_path, script_identity) . map_err (
493
- |err| {
494
- write_failure_marker ( & failure_marker) ;
495
- err
496
- } ,
497
- ) ?;
572
+ create_archive_if_not_on_ci (
573
+ & script_result_directory,
574
+ & archive_file_path,
575
+ script_identity_for_archive,
576
+ )
577
+ . map_err ( |err| {
578
+ write_failure_marker ( & failure_marker) ;
579
+ err
580
+ } ) ?;
498
581
}
499
582
}
500
583
}
0 commit comments