@@ -572,7 +572,7 @@ static int sqrti(int val)
572
572
{
573
573
float d , x = val ;
574
574
575
- if (val == 0 )
575
+ if (! val )
576
576
return 0 ;
577
577
578
578
do {
@@ -661,11 +661,11 @@ static void bisect_common(struct rev_info *revs)
661
661
mark_edges_uninteresting (revs , NULL , 0 );
662
662
}
663
663
664
- static void exit_if_skipped_commits (struct commit_list * tried ,
664
+ static enum bisect_error error_if_skipped_commits (struct commit_list * tried ,
665
665
const struct object_id * bad )
666
666
{
667
667
if (!tried )
668
- return ;
668
+ return BISECT_OK ;
669
669
670
670
printf ("There are only 'skip'ped commits left to test.\n"
671
671
"The first %s commit could be any of:\n" , term_bad );
@@ -676,7 +676,8 @@ static void exit_if_skipped_commits(struct commit_list *tried,
676
676
if (bad )
677
677
printf ("%s\n" , oid_to_hex (bad ));
678
678
printf (_ ("We cannot bisect more!\n" ));
679
- exit (2 );
679
+
680
+ return BISECT_ONLY_SKIPPED_LEFT ;
680
681
}
681
682
682
683
static int is_expected_rev (const struct object_id * oid )
@@ -703,9 +704,10 @@ static int is_expected_rev(const struct object_id *oid)
703
704
return res ;
704
705
}
705
706
706
- static int bisect_checkout (const struct object_id * bisect_rev , int no_checkout )
707
+ static enum bisect_error bisect_checkout (const struct object_id * bisect_rev , int no_checkout )
707
708
{
708
709
char bisect_rev_hex [GIT_MAX_HEXSZ + 1 ];
710
+ enum bisect_error res = BISECT_OK ;
709
711
710
712
memcpy (bisect_rev_hex , oid_to_hex (bisect_rev ), the_hash_algo -> hexsz + 1 );
711
713
update_ref (NULL , "BISECT_EXPECTED_REV" , bisect_rev , NULL , 0 , UPDATE_REFS_DIE_ON_ERR );
@@ -715,14 +717,24 @@ static int bisect_checkout(const struct object_id *bisect_rev, int no_checkout)
715
717
update_ref (NULL , "BISECT_HEAD" , bisect_rev , NULL , 0 ,
716
718
UPDATE_REFS_DIE_ON_ERR );
717
719
} else {
718
- int res ;
719
720
res = run_command_v_opt (argv_checkout , RUN_GIT_CMD );
720
721
if (res )
721
- exit (res );
722
+ /*
723
+ * Errors in `run_command()` itself, signaled by res < 0,
724
+ * and errors in the child process, signaled by res > 0
725
+ * can both be treated as regular BISECT_FAILURE (-1).
726
+ */
727
+ return - abs (res );
722
728
}
723
729
724
730
argv_show_branch [1 ] = bisect_rev_hex ;
725
- return run_command_v_opt (argv_show_branch , RUN_GIT_CMD );
731
+ res = run_command_v_opt (argv_show_branch , RUN_GIT_CMD );
732
+ /*
733
+ * Errors in `run_command()` itself, signaled by res < 0,
734
+ * and errors in the child process, signaled by res > 0
735
+ * can both be treated as regular BISECT_FAILURE (-1).
736
+ */
737
+ return - abs (res );
726
738
}
727
739
728
740
static struct commit * get_commit_reference (struct repository * r ,
@@ -749,7 +761,7 @@ static struct commit **get_bad_and_good_commits(struct repository *r,
749
761
return rev ;
750
762
}
751
763
752
- static void handle_bad_merge_base (void )
764
+ static enum bisect_error handle_bad_merge_base (void )
753
765
{
754
766
if (is_expected_rev (current_bad_oid )) {
755
767
char * bad_hex = oid_to_hex (current_bad_oid );
@@ -770,14 +782,14 @@ static void handle_bad_merge_base(void)
770
782
"between %s and [%s].\n" ),
771
783
bad_hex , term_bad , term_good , bad_hex , good_hex );
772
784
}
773
- exit ( 3 ) ;
785
+ return BISECT_MERGE_BASE_CHECK ;
774
786
}
775
787
776
788
fprintf (stderr , _ ("Some %s revs are not ancestors of the %s rev.\n"
777
789
"git bisect cannot work properly in this case.\n"
778
790
"Maybe you mistook %s and %s revs?\n" ),
779
791
term_good , term_bad , term_good , term_bad );
780
- exit ( 1 ) ;
792
+ return BISECT_FAILED ;
781
793
}
782
794
783
795
static void handle_skipped_merge_base (const struct object_id * mb )
@@ -799,32 +811,43 @@ static void handle_skipped_merge_base(const struct object_id *mb)
799
811
* "check_merge_bases" checks that merge bases are not "bad" (or "new").
800
812
*
801
813
* - If one is "bad" (or "new"), it means the user assumed something wrong
802
- * and we must exit with a non 0 error code.
814
+ * and we must return error with a non 0 error code.
803
815
* - If one is "good" (or "old"), that's good, we have nothing to do.
804
816
* - If one is "skipped", we can't know but we should warn.
805
817
* - If we don't know, we should check it out and ask the user to test.
818
+ * - If a merge base must be tested, on success return
819
+ * BISECT_INTERNAL_SUCCESS_MERGE_BASE (-11) a special condition
820
+ * for early success, this will be converted back to 0 in
821
+ * check_good_are_ancestors_of_bad().
806
822
*/
807
- static void check_merge_bases (int rev_nr , struct commit * * rev , int no_checkout )
823
+ static enum bisect_error check_merge_bases (int rev_nr , struct commit * * rev , int no_checkout )
808
824
{
825
+ enum bisect_error res = BISECT_OK ;
809
826
struct commit_list * result ;
810
827
811
828
result = get_merge_bases_many (rev [0 ], rev_nr - 1 , rev + 1 );
812
829
813
830
for (; result ; result = result -> next ) {
814
831
const struct object_id * mb = & result -> item -> object .oid ;
815
832
if (oideq (mb , current_bad_oid )) {
816
- handle_bad_merge_base ();
833
+ res = handle_bad_merge_base ();
834
+ break ;
817
835
} else if (0 <= oid_array_lookup (& good_revs , mb )) {
818
836
continue ;
819
837
} else if (0 <= oid_array_lookup (& skipped_revs , mb )) {
820
838
handle_skipped_merge_base (mb );
821
839
} else {
822
840
printf (_ ("Bisecting: a merge base must be tested\n" ));
823
- exit (bisect_checkout (mb , no_checkout ));
841
+ res = bisect_checkout (mb , no_checkout );
842
+ if (!res )
843
+ /* indicate early success */
844
+ res = BISECT_INTERNAL_SUCCESS_MERGE_BASE ;
845
+ break ;
824
846
}
825
847
}
826
848
827
849
free_commit_list (result );
850
+ return res ;
828
851
}
829
852
830
853
static int check_ancestors (struct repository * r , int rev_nr ,
@@ -850,43 +873,58 @@ static int check_ancestors(struct repository *r, int rev_nr,
850
873
*
851
874
* If that's not the case, we need to check the merge bases.
852
875
* If a merge base must be tested by the user, its source code will be
853
- * checked out to be tested by the user and we will exit .
876
+ * checked out to be tested by the user and we will return .
854
877
*/
855
- static void check_good_are_ancestors_of_bad (struct repository * r ,
878
+
879
+ static enum bisect_error check_good_are_ancestors_of_bad (struct repository * r ,
856
880
const char * prefix ,
857
881
int no_checkout )
858
882
{
859
- char * filename = git_pathdup ( "BISECT_ANCESTORS_OK" ) ;
883
+ char * filename ;
860
884
struct stat st ;
861
885
int fd , rev_nr ;
886
+ enum bisect_error res = BISECT_OK ;
862
887
struct commit * * rev ;
863
888
864
889
if (!current_bad_oid )
865
- die (_ ("a %s revision is needed" ), term_bad );
890
+ return error (_ ("a %s revision is needed" ), term_bad );
891
+
892
+ filename = git_pathdup ("BISECT_ANCESTORS_OK" );
866
893
867
894
/* Check if file BISECT_ANCESTORS_OK exists. */
868
895
if (!stat (filename , & st ) && S_ISREG (st .st_mode ))
869
896
goto done ;
870
897
871
898
/* Bisecting with no good rev is ok. */
872
- if (good_revs .nr == 0 )
899
+ if (! good_revs .nr )
873
900
goto done ;
874
901
875
902
/* Check if all good revs are ancestor of the bad rev. */
903
+
876
904
rev = get_bad_and_good_commits (r , & rev_nr );
877
905
if (check_ancestors (r , rev_nr , rev , prefix ))
878
- check_merge_bases (rev_nr , rev , no_checkout );
906
+ res = check_merge_bases (rev_nr , rev , no_checkout );
879
907
free (rev );
880
908
881
- /* Create file BISECT_ANCESTORS_OK. */
882
- fd = open (filename , O_CREAT | O_TRUNC | O_WRONLY , 0600 );
883
- if (fd < 0 )
884
- warning_errno (_ ("could not create file '%s'" ),
885
- filename );
886
- else
887
- close (fd );
909
+ if (!res ) {
910
+ /* Create file BISECT_ANCESTORS_OK. */
911
+ fd = open (filename , O_CREAT | O_TRUNC | O_WRONLY , 0600 );
912
+ if (fd < 0 )
913
+ /*
914
+ * BISECT_ANCESTORS_OK file is not absolutely necessary,
915
+ * the bisection process will continue at the next
916
+ * bisection step.
917
+ * So, just signal with a warning that something
918
+ * might be wrong.
919
+ */
920
+ warning_errno (_ ("could not create file '%s'" ),
921
+ filename );
922
+ else
923
+ close (fd );
924
+ }
888
925
done :
889
926
free (filename );
927
+ return res ;
890
928
}
891
929
892
930
/*
@@ -938,26 +976,29 @@ void read_bisect_terms(const char **read_bad, const char **read_good)
938
976
}
939
977
940
978
/*
941
- * We use the convention that exiting with an exit code 10 means that
979
+ * We use the convention that return BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND (-10) means
942
980
* the bisection process finished successfully.
943
- * In this case the calling shell script should exit 0.
944
- *
981
+ * In this case the calling function or command should not turn a
982
+ * BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND return code into an error or a non zero exit code.
945
983
* If no_checkout is non-zero, the bisection process does not
946
984
* checkout the trial commit but instead simply updates BISECT_HEAD.
947
985
*/
948
- int bisect_next_all (struct repository * r , const char * prefix , int no_checkout )
986
+ enum bisect_error bisect_next_all (struct repository * r , const char * prefix , int no_checkout )
949
987
{
950
988
struct rev_info revs ;
951
989
struct commit_list * tried ;
952
990
int reaches = 0 , all = 0 , nr , steps ;
991
+ enum bisect_error res = BISECT_OK ;
953
992
struct object_id * bisect_rev ;
954
993
char * steps_msg ;
955
994
956
995
read_bisect_terms (& term_bad , & term_good );
957
996
if (read_bisect_refs ())
958
997
die (_ ("reading bisect refs failed" ));
959
998
960
- check_good_are_ancestors_of_bad (r , prefix , no_checkout );
999
+ res = check_good_are_ancestors_of_bad (r , prefix , no_checkout );
1000
+ if (res )
1001
+ return res ;
961
1002
962
1003
bisect_rev_setup (r , & revs , prefix , "%s" , "^%s" , 1 );
963
1004
revs .limited = 1 ;
@@ -969,33 +1010,45 @@ int bisect_next_all(struct repository *r, const char *prefix, int no_checkout)
969
1010
970
1011
if (!revs .commits ) {
971
1012
/*
972
- * We should exit here only if the "bad"
1013
+ * We should return error here only if the "bad"
973
1014
* commit is also a "skip" commit.
974
1015
*/
975
- exit_if_skipped_commits (tried , NULL );
976
-
1016
+ res = error_if_skipped_commits (tried , NULL );
1017
+ if (res < 0 )
1018
+ return res ;
977
1019
printf (_ ("%s was both %s and %s\n" ),
978
1020
oid_to_hex (current_bad_oid ),
979
1021
term_good ,
980
1022
term_bad );
981
- exit (1 );
1023
+
1024
+ return BISECT_FAILED ;
982
1025
}
983
1026
984
1027
if (!all ) {
985
1028
fprintf (stderr , _ ("No testable commit found.\n"
986
1029
"Maybe you started with bad path parameters?\n" ));
987
- exit (4 );
1030
+
1031
+ return BISECT_NO_TESTABLE_COMMIT ;
988
1032
}
989
1033
990
1034
bisect_rev = & revs .commits -> item -> object .oid ;
991
1035
992
1036
if (oideq (bisect_rev , current_bad_oid )) {
993
- exit_if_skipped_commits (tried , current_bad_oid );
1037
+ res = error_if_skipped_commits (tried , current_bad_oid );
1038
+ if (res )
1039
+ return res ;
994
1040
printf ("%s is the first %s commit\n" , oid_to_hex (bisect_rev ),
995
1041
term_bad );
1042
+
996
1043
show_diff_tree (r , prefix , revs .commits -> item );
997
- /* This means the bisection process succeeded. */
998
- exit (10 );
1044
+ /*
1045
+ * This means the bisection process succeeded.
1046
+ * Using BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND (-10)
1047
+ * so that the call chain can simply check
1048
+ * for negative return values for early returns up
1049
+ * until the cmd_bisect__helper() caller.
1050
+ */
1051
+ return BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND ;
999
1052
}
1000
1053
1001
1054
nr = all - reaches - 1 ;
0 commit comments