@@ -10,7 +10,7 @@ use std::time::SystemTime;
1010
1111use cursive_core:: theme:: Effect ;
1212use cursive_core:: utils:: markup:: StyledString ;
13- use git_branchless_opts:: Revset ;
13+ use git_branchless_opts:: { Revset , TestSearchStrategy } ;
1414use git_branchless_test:: {
1515 run_tests, FixInfo , ResolvedTestOptions , TestOutput , TestResults , TestStatus ,
1616 TestingAbortedError , Verbosity ,
@@ -373,7 +373,7 @@ impl Forge for PhabricatorForge<'_> {
373373 TestCommand :: Args ( args. into_iter ( ) . map ( ToString :: to_string) . collect ( ) )
374374 } else {
375375 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)
377377
378378Differential Revision: https://phabricator.example.com/D000$(git rev-list --count HEAD)
379379 "
@@ -394,7 +394,7 @@ Differential Revision: https://phabricator.example.com/D000$(git rev-list --coun
394394 & ResolvedTestOptions {
395395 command,
396396 execution_strategy : * execution_strategy,
397- search_strategy : None ,
397+ search_strategy : Some ( TestSearchStrategy :: Linear ) ,
398398 is_dry_run : false ,
399399 use_cache : false ,
400400 is_interactive : false ,
@@ -429,10 +429,23 @@ Differential Revision: https://phabricator.example.com/D000$(git rev-list --coun
429429 return Ok ( Err ( ExitCode ( 1 ) ) ) ;
430430 }
431431
432- let rebase_plan = {
432+ enum ErrorReason {
433+ NotTested ,
434+ TestFailed ,
435+ }
436+ let ( maybe_rebase_plan, error_commits) = {
433437 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 {
436449 TestStatus :: CheckoutFailed
437450 | TestStatus :: SpawnTestFailed ( _)
438451 | TestStatus :: TerminatedBySignal
@@ -442,7 +455,7 @@ Differential Revision: https://phabricator.example.com/D000$(git rev-list --coun
442455 | TestStatus :: Abort { .. }
443456 | TestStatus :: Failed { .. } => {
444457 self . render_failed_test ( commit_oid, & test_output) ?;
445- return Ok ( Err ( ExitCode ( 1 ) ) ) ;
458+ error_commits . insert ( commit_oid , ErrorReason :: TestFailed ) ;
446459 }
447460 TestStatus :: Passed {
448461 cached : _,
@@ -452,66 +465,86 @@ Differential Revision: https://phabricator.example.com/D000$(git rev-list --coun
452465 snapshot_tree_oid : _,
453466 } ,
454467 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+ }
461477 }
462478
463479 let pool = ThreadPoolBuilder :: new ( ) . build ( ) ?;
464480 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,
468483 Err ( err) => {
469484 err. describe ( self . effects , self . repo , self . dag ) ?;
470485 return Ok ( Err ( ExitCode ( 1 ) ) ) ;
471486 }
472- }
487+ } ;
488+ ( maybe_rebase_plan, error_commits)
473489 } ;
474490
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+ } ,
504523 } ;
505524
506525 let mut create_statuses = HashMap :: new ( ) ;
507526 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+
508538 let final_commit_oid = match rewritten_oids. get ( & commit_oid) {
509539 Some ( MaybeZeroOid :: NonZero ( commit_oid) ) => * commit_oid,
510540 Some ( MaybeZeroOid :: Zero ) => {
511541 warn ! ( ?commit_oid, "Commit was rewritten to the zero OID" , ) ;
512542 commit_oid
513543 }
514- None => commit_oid,
544+ None => {
545+ create_statuses. insert ( commit_oid, CreateStatus :: Skipped { commit_oid } ) ;
546+ continue ;
547+ }
515548 } ;
516549 let local_branch_name = {
517550 match self . get_revision_id ( final_commit_oid) ? {
@@ -527,13 +560,14 @@ Differential Revision: https://phabricator.example.com/D000$(git rev-list --coun
527560 ) ?
528561 ) ?,
529562 ) ?;
530- return Ok ( Err ( ExitCode ( 1 ) ) ) ;
563+ create_statuses. insert ( commit_oid, CreateStatus :: Err { commit_oid } ) ;
564+ continue ;
531565 }
532566 }
533567 } ;
534568 create_statuses. insert (
535569 commit_oid,
536- CreateStatus {
570+ CreateStatus :: Created {
537571 final_commit_oid,
538572 local_branch_name,
539573 } ,
@@ -542,12 +576,12 @@ Differential Revision: https://phabricator.example.com/D000$(git rev-list --coun
542576
543577 let final_commit_oids: CommitSet = create_statuses
544578 . values ( )
545- . map ( |create_status| {
546- let CreateStatus {
579+ . filter_map ( |create_status| match create_status {
580+ CreateStatus :: Created {
547581 final_commit_oid,
548582 local_branch_name : _,
549- } = create_status ;
550- * final_commit_oid
583+ } => Some ( * final_commit_oid ) ,
584+ CreateStatus :: Skipped { .. } | CreateStatus :: Err { .. } => None ,
551585 } )
552586 . collect ( ) ;
553587 self . dag . sync_from_oids (
0 commit comments