@@ -258,13 +258,16 @@ pub fn assert_matches_path(
258
258
. matches_path ( expected_path, buf) ;
259
259
}
260
260
261
- pub fn register_example ( name : & str , shell : completest:: Shell ) {
261
+ pub fn register_example < R : completest:: RuntimeBuilder > ( context : & str , name : & str ) {
262
+ use completest:: Runtime as _;
263
+
262
264
let scratch = snapbox:: path:: PathFixture :: mutable_temp ( ) . unwrap ( ) ;
263
265
let scratch_path = scratch. path ( ) . unwrap ( ) ;
264
266
265
- let shell_name = shell . name ( ) ;
267
+ let shell_name = R :: name ( ) ;
266
268
let home = std:: path:: Path :: new ( env ! ( "CARGO_MANIFEST_DIR" ) )
267
269
. join ( "tests/snapshots/home" )
270
+ . join ( context)
268
271
. join ( name)
269
272
. join ( shell_name) ;
270
273
println ! ( "Compiling" ) ;
@@ -275,10 +278,17 @@ pub fn register_example(name: &str, shell: completest::Shell) {
275
278
println ! ( "Compiled" ) ;
276
279
let bin_root = bin_path. parent ( ) . unwrap ( ) . to_owned ( ) ;
277
280
278
- let registration = std:: process:: Command :: new ( & bin_path)
279
- . arg ( format ! ( "--generate={shell_name}" ) )
280
- . output ( )
281
- . unwrap ( ) ;
281
+ let mut registration = std:: process:: Command :: new ( & bin_path) ;
282
+ match context {
283
+ "static" => registration. args ( [ format ! ( "--generate={shell_name}" ) ] ) ,
284
+ "dynamic" => registration. args ( [
285
+ "complete" . to_owned ( ) ,
286
+ "--register=-" . to_owned ( ) ,
287
+ format ! ( "--shell={shell_name}" ) ,
288
+ ] ) ,
289
+ _ => unreachable ! ( "unsupported context {}" , context) ,
290
+ } ;
291
+ let registration = registration. output ( ) . unwrap ( ) ;
282
292
assert ! (
283
293
registration. status. success( ) ,
284
294
"{}" ,
@@ -287,7 +297,7 @@ pub fn register_example(name: &str, shell: completest::Shell) {
287
297
let registration = std:: str:: from_utf8 ( & registration. stdout ) . unwrap ( ) ;
288
298
assert ! ( !registration. is_empty( ) ) ;
289
299
290
- let mut runtime = shell . init ( bin_root, scratch_path. to_owned ( ) ) . unwrap ( ) ;
300
+ let mut runtime = R :: new ( bin_root, scratch_path. to_owned ( ) ) . unwrap ( ) ;
291
301
292
302
runtime. register ( name, registration) . unwrap ( ) ;
293
303
@@ -296,14 +306,23 @@ pub fn register_example(name: &str, shell: completest::Shell) {
296
306
scratch. close ( ) . unwrap ( ) ;
297
307
}
298
308
299
- pub fn load_runtime ( name : & str , shell : completest:: Shell ) -> Box < dyn completest:: Runtime > {
300
- let shell_name = shell. name ( ) ;
309
+ pub fn load_runtime < R : completest:: RuntimeBuilder > (
310
+ context : & str ,
311
+ name : & str ,
312
+ ) -> Box < dyn completest:: Runtime >
313
+ where
314
+ <R as completest:: RuntimeBuilder >:: Runtime : ' static ,
315
+ {
316
+ let shell_name = R :: name ( ) ;
301
317
let home = std:: path:: Path :: new ( env ! ( "CARGO_MANIFEST_DIR" ) )
302
318
. join ( "tests/snapshots/home" )
319
+ . join ( context)
303
320
. join ( name)
304
321
. join ( shell_name) ;
305
- std:: fs:: create_dir_all ( & home) . unwrap ( ) ;
306
- let scratch = snapbox:: path:: PathFixture :: immutable ( & home) ;
322
+ let scratch = snapbox:: path:: PathFixture :: mutable_temp ( )
323
+ . unwrap ( )
324
+ . with_template ( & home)
325
+ . unwrap ( ) ;
307
326
let home = scratch. path ( ) . unwrap ( ) . to_owned ( ) ;
308
327
println ! ( "Compiling" ) ;
309
328
let manifest_path = std:: path:: Path :: new ( env ! ( "CARGO_MANIFEST_DIR" ) ) . join ( "Cargo.toml" ) ;
@@ -313,11 +332,11 @@ pub fn load_runtime(name: &str, shell: completest::Shell) -> Box<dyn completest:
313
332
println ! ( "Compiled" ) ;
314
333
let bin_root = bin_path. parent ( ) . unwrap ( ) . to_owned ( ) ;
315
334
316
- let runtime = shell . with_home ( bin_root, home) . unwrap ( ) ;
335
+ let runtime = R :: with_home ( bin_root, home) . unwrap ( ) ;
317
336
318
337
Box :: new ( ScratchRuntime {
319
338
_scratch : scratch,
320
- runtime,
339
+ runtime : Box :: new ( runtime ) ,
321
340
} )
322
341
}
323
342
@@ -345,3 +364,56 @@ impl completest::Runtime for ScratchRuntime {
345
364
Ok ( output)
346
365
}
347
366
}
367
+
368
+ pub fn has_command ( command : & str ) -> bool {
369
+ let output = match std:: process:: Command :: new ( command)
370
+ . arg ( "--version" )
371
+ . output ( )
372
+ {
373
+ Ok ( output) => output,
374
+ Err ( e) => {
375
+ // CI is expected to support all of the commands
376
+ if is_ci ( ) && cfg ! ( linux) {
377
+ panic ! (
378
+ "expected command `{}` to be somewhere in PATH: {}" ,
379
+ command, e
380
+ ) ;
381
+ }
382
+ return false ;
383
+ }
384
+ } ;
385
+ if !output. status . success ( ) {
386
+ panic ! (
387
+ "expected command `{}` to be runnable, got error {}:\n \
388
+ stderr:{}\n \
389
+ stdout:{}\n ",
390
+ command,
391
+ output. status,
392
+ String :: from_utf8_lossy( & output. stderr) ,
393
+ String :: from_utf8_lossy( & output. stdout)
394
+ ) ;
395
+ }
396
+ let stdout = String :: from_utf8_lossy ( & output. stdout ) ;
397
+ println ! (
398
+ "$ {command} --version
399
+ {}" ,
400
+ stdout
401
+ ) ;
402
+ if cfg ! ( target_os = "macos" ) && stdout. starts_with ( "GNU bash, version 3" ) {
403
+ return false ;
404
+ }
405
+ if cfg ! ( target_os = "macos" ) && command == "zsh" {
406
+ // HACK: At least on CI, the prompt override is not working
407
+ return false ;
408
+ }
409
+
410
+ true
411
+ }
412
+
413
+ /// Whether or not this running in a Continuous Integration environment.
414
+ fn is_ci ( ) -> bool {
415
+ // Consider using `tracked_env` instead of option_env! when it is stabilized.
416
+ // `tracked_env` will handle changes, but not require rebuilding the macro
417
+ // itself like option_env does.
418
+ option_env ! ( "CI" ) . is_some ( ) || option_env ! ( "TF_BUILD" ) . is_some ( )
419
+ }
0 commit comments