@@ -10,7 +10,7 @@ use std::time::SystemTime;
10
10
11
11
use cursive_core:: theme:: Effect ;
12
12
use cursive_core:: utils:: markup:: StyledString ;
13
- use git_branchless_opts:: Revset ;
13
+ use git_branchless_opts:: { Revset , TestSearchStrategy } ;
14
14
use git_branchless_test:: {
15
15
run_tests, FixInfo , ResolvedTestOptions , TestOutput , TestResults , TestStatus ,
16
16
TestingAbortedError , Verbosity ,
@@ -373,7 +373,7 @@ impl Forge for PhabricatorForge<'_> {
373
373
TestCommand :: Args ( args. into_iter ( ) . map ( ToString :: to_string) . collect ( ) )
374
374
} else {
375
375
TestCommand :: String (
376
- r#"git commit --amend --message "$(git show --no-patch --format=%B HEAD)
376
+ r#"(git show | grep 'BROKEN') && exit 1 || git commit --amend --message "$(git show --no-patch --format=%B HEAD)
377
377
378
378
Differential Revision: https://phabricator.example.com/D000$(git rev-list --count HEAD)
379
379
"
@@ -394,7 +394,7 @@ Differential Revision: https://phabricator.example.com/D000$(git rev-list --coun
394
394
& ResolvedTestOptions {
395
395
command,
396
396
execution_strategy : * execution_strategy,
397
- search_strategy : None ,
397
+ search_strategy : Some ( TestSearchStrategy :: Linear ) ,
398
398
is_dry_run : false ,
399
399
use_cache : false ,
400
400
is_interactive : false ,
@@ -429,10 +429,23 @@ Differential Revision: https://phabricator.example.com/D000$(git rev-list --coun
429
429
return Ok ( Err ( ExitCode ( 1 ) ) ) ;
430
430
}
431
431
432
- let rebase_plan = {
432
+ enum ErrorReason {
433
+ NotTested ,
434
+ TestFailed ,
435
+ }
436
+ let ( maybe_rebase_plan, error_commits) = {
433
437
let mut builder = RebasePlanBuilder :: new ( self . dag , permissions) ;
434
- for ( commit_oid, test_output) in test_outputs {
435
- let head_commit_oid = match test_output. test_status {
438
+ let mut error_commits = HashMap :: new ( ) ;
439
+ for commit_oid in commit_oids. iter ( ) . copied ( ) {
440
+ let test_output = match test_outputs. get ( & commit_oid) {
441
+ Some ( test_output) => test_output,
442
+ None => {
443
+ // Testing was aborted due to a previous commit failing.
444
+ error_commits. insert ( commit_oid, ErrorReason :: NotTested ) ;
445
+ continue ;
446
+ }
447
+ } ;
448
+ match test_output. test_status {
436
449
TestStatus :: CheckoutFailed
437
450
| TestStatus :: SpawnTestFailed ( _)
438
451
| TestStatus :: TerminatedBySignal
@@ -442,7 +455,7 @@ Differential Revision: https://phabricator.example.com/D000$(git rev-list --coun
442
455
| TestStatus :: Abort { .. }
443
456
| TestStatus :: Failed { .. } => {
444
457
self . render_failed_test ( commit_oid, & test_output) ?;
445
- return Ok ( Err ( ExitCode ( 1 ) ) ) ;
458
+ error_commits . insert ( commit_oid , ErrorReason :: TestFailed ) ;
446
459
}
447
460
TestStatus :: Passed {
448
461
cached : _,
@@ -452,66 +465,86 @@ Differential Revision: https://phabricator.example.com/D000$(git rev-list --coun
452
465
snapshot_tree_oid : _,
453
466
} ,
454
467
interactive : _,
455
- } => head_commit_oid,
456
- } ;
457
-
458
- let commit = self . repo . find_commit_or_fail ( commit_oid) ?;
459
- builder. move_subtree ( commit. get_oid ( ) , commit. get_parent_oids ( ) ) ?;
460
- builder. replace_commit ( commit. get_oid ( ) , head_commit_oid. unwrap_or ( commit_oid) ) ?;
468
+ } => {
469
+ let commit = self . repo . find_commit_or_fail ( commit_oid) ?;
470
+ builder. move_subtree ( commit. get_oid ( ) , commit. get_parent_oids ( ) ) ?;
471
+ builder. replace_commit (
472
+ commit. get_oid ( ) ,
473
+ head_commit_oid. unwrap_or ( commit_oid) ,
474
+ ) ?;
475
+ }
476
+ }
461
477
}
462
478
463
479
let pool = ThreadPoolBuilder :: new ( ) . build ( ) ?;
464
480
let repo_pool = RepoResource :: new_pool ( self . repo ) ?;
465
- match builder. build ( self . effects , & pool, & repo_pool) ? {
466
- Ok ( Some ( rebase_plan) ) => rebase_plan,
467
- Ok ( None ) => return Ok ( Ok ( Default :: default ( ) ) ) ,
481
+ let maybe_rebase_plan = match builder. build ( self . effects , & pool, & repo_pool) ? {
482
+ Ok ( maybe_rebase_plan) => maybe_rebase_plan,
468
483
Err ( err) => {
469
484
err. describe ( self . effects , self . repo , self . dag ) ?;
470
485
return Ok ( Err ( ExitCode ( 1 ) ) ) ;
471
486
}
472
- }
487
+ } ;
488
+ ( maybe_rebase_plan, error_commits)
473
489
} ;
474
490
475
- let rewritten_oids = match execute_rebase_plan (
476
- self . effects ,
477
- self . git_run_info ,
478
- self . repo ,
479
- self . event_log_db ,
480
- & rebase_plan,
481
- & execute_options,
482
- ) ? {
483
- ExecuteRebasePlanResult :: Succeeded {
484
- rewritten_oids : Some ( rewritten_oids) ,
485
- } => rewritten_oids,
486
- ExecuteRebasePlanResult :: Succeeded {
487
- rewritten_oids : None ,
488
- } => {
489
- warn ! ( "No rewritten commit OIDs were produced by rebase plan execution" ) ;
490
- Default :: default ( )
491
- }
492
- ExecuteRebasePlanResult :: DeclinedToMerge {
493
- failed_merge_info : _,
494
- } => {
495
- writeln ! (
496
- self . effects. get_error_stream( ) ,
497
- "BUG: Merge failed, but rewording shouldn't cause any merge failures."
498
- ) ?;
499
- return Ok ( Err ( ExitCode ( 1 ) ) ) ;
500
- }
501
- ExecuteRebasePlanResult :: Failed { exit_code } => {
502
- return Ok ( Err ( exit_code) ) ;
503
- }
491
+ let rewritten_oids = match maybe_rebase_plan {
492
+ None => Default :: default ( ) ,
493
+ Some ( rebase_plan) => match execute_rebase_plan (
494
+ self . effects ,
495
+ self . git_run_info ,
496
+ self . repo ,
497
+ self . event_log_db ,
498
+ & rebase_plan,
499
+ & execute_options,
500
+ ) ? {
501
+ ExecuteRebasePlanResult :: Succeeded {
502
+ rewritten_oids : Some ( rewritten_oids) ,
503
+ } => rewritten_oids,
504
+ ExecuteRebasePlanResult :: Succeeded {
505
+ rewritten_oids : None ,
506
+ } => {
507
+ warn ! ( "No rewritten commit OIDs were produced by rebase plan execution" ) ;
508
+ Default :: default ( )
509
+ }
510
+ ExecuteRebasePlanResult :: DeclinedToMerge {
511
+ failed_merge_info : _,
512
+ } => {
513
+ writeln ! (
514
+ self . effects. get_error_stream( ) ,
515
+ "BUG: Merge failed, but rewording shouldn't cause any merge failures."
516
+ ) ?;
517
+ return Ok ( Err ( ExitCode ( 1 ) ) ) ;
518
+ }
519
+ ExecuteRebasePlanResult :: Failed { exit_code } => {
520
+ return Ok ( Err ( exit_code) ) ;
521
+ }
522
+ } ,
504
523
} ;
505
524
506
525
let mut create_statuses = HashMap :: new ( ) ;
507
526
for commit_oid in commit_oids {
527
+ if let Some ( error_reason) = error_commits. get ( & commit_oid) {
528
+ create_statuses. insert (
529
+ commit_oid,
530
+ match error_reason {
531
+ ErrorReason :: NotTested => CreateStatus :: Skipped { commit_oid } ,
532
+ ErrorReason :: TestFailed => CreateStatus :: Err { commit_oid } ,
533
+ } ,
534
+ ) ;
535
+ continue ;
536
+ }
537
+
508
538
let final_commit_oid = match rewritten_oids. get ( & commit_oid) {
509
539
Some ( MaybeZeroOid :: NonZero ( commit_oid) ) => * commit_oid,
510
540
Some ( MaybeZeroOid :: Zero ) => {
511
541
warn ! ( ?commit_oid, "Commit was rewritten to the zero OID" , ) ;
512
542
commit_oid
513
543
}
514
- None => commit_oid,
544
+ None => {
545
+ create_statuses. insert ( commit_oid, CreateStatus :: Skipped { commit_oid } ) ;
546
+ continue ;
547
+ }
515
548
} ;
516
549
let local_branch_name = {
517
550
match self . get_revision_id ( final_commit_oid) ? {
@@ -527,13 +560,14 @@ Differential Revision: https://phabricator.example.com/D000$(git rev-list --coun
527
560
) ?
528
561
) ?,
529
562
) ?;
530
- return Ok ( Err ( ExitCode ( 1 ) ) ) ;
563
+ create_statuses. insert ( commit_oid, CreateStatus :: Err { commit_oid } ) ;
564
+ continue ;
531
565
}
532
566
}
533
567
} ;
534
568
create_statuses. insert (
535
569
commit_oid,
536
- CreateStatus {
570
+ CreateStatus :: Created {
537
571
final_commit_oid,
538
572
local_branch_name,
539
573
} ,
@@ -542,12 +576,12 @@ Differential Revision: https://phabricator.example.com/D000$(git rev-list --coun
542
576
543
577
let final_commit_oids: CommitSet = create_statuses
544
578
. values ( )
545
- . map ( |create_status| {
546
- let CreateStatus {
579
+ . filter_map ( |create_status| match create_status {
580
+ CreateStatus :: Created {
547
581
final_commit_oid,
548
582
local_branch_name : _,
549
- } = create_status ;
550
- * final_commit_oid
583
+ } => Some ( * final_commit_oid ) ,
584
+ CreateStatus :: Skipped { .. } | CreateStatus :: Err { .. } => None ,
551
585
} )
552
586
. collect ( ) ;
553
587
self . dag . sync_from_oids (
0 commit comments