@@ -20,9 +20,6 @@ static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
20
20
static GIT_PATH_FUNC (git_path_bisect_first_parent , "BISECT_FIRST_PARENT ")
21
21
22
22
static const char * const git_bisect_helper_usage [] = {
23
- N_ ("git bisect--helper --next-all" ),
24
- N_ ("git bisect--helper --write-terms <bad_term> <good_term>" ),
25
- N_ ("git bisect--helper --bisect-clean-state" ),
26
23
N_ ("git bisect--helper --bisect-reset [<commit>]" ),
27
24
N_ ("git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>" ),
28
25
N_ ("git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>" ),
@@ -32,7 +29,8 @@ static const char * const git_bisect_helper_usage[] = {
32
29
" [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]" ),
33
30
N_ ("git bisect--helper --bisect-next" ),
34
31
N_ ("git bisect--helper --bisect-auto-next" ),
35
- N_ ("git bisect--helper --bisect-autostart" ),
32
+ N_ ("git bisect--helper --bisect-state (bad|new) [<rev>]" ),
33
+ N_ ("git bisect--helper --bisect-state (good|old) [<rev>...]" ),
36
34
NULL
37
35
};
38
36
@@ -85,6 +83,19 @@ static int one_of(const char *term, ...)
85
83
return res ;
86
84
}
87
85
86
+ /*
87
+ * return code BISECT_INTERNAL_SUCCESS_MERGE_BASE
88
+ * and BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND are codes
89
+ * that indicate special success.
90
+ */
91
+
92
+ static int is_bisect_success (enum bisect_error res )
93
+ {
94
+ return !res ||
95
+ res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND ||
96
+ res == BISECT_INTERNAL_SUCCESS_MERGE_BASE ;
97
+ }
98
+
88
99
static int write_in_file (const char * path , const char * mode , const char * format , va_list args )
89
100
{
90
101
FILE * fp = NULL ;
@@ -174,30 +185,6 @@ static int write_terms(const char *bad, const char *good)
174
185
return res ;
175
186
}
176
187
177
- static int is_expected_rev (const char * expected_hex )
178
- {
179
- struct strbuf actual_hex = STRBUF_INIT ;
180
- int res = 0 ;
181
- if (strbuf_read_file (& actual_hex , git_path_bisect_expected_rev (), 0 ) >= 40 ) {
182
- strbuf_trim (& actual_hex );
183
- res = !strcmp (actual_hex .buf , expected_hex );
184
- }
185
- strbuf_release (& actual_hex );
186
- return res ;
187
- }
188
-
189
- static void check_expected_revs (const char * * revs , int rev_nr )
190
- {
191
- int i ;
192
-
193
- for (i = 0 ; i < rev_nr ; i ++ ) {
194
- if (!is_expected_rev (revs [i ])) {
195
- unlink_or_warn (git_path_bisect_ancestors_ok ());
196
- unlink_or_warn (git_path_bisect_expected_rev ());
197
- }
198
- }
199
- }
200
-
201
188
static int bisect_reset (const char * commit )
202
189
{
203
190
struct strbuf branch = STRBUF_INIT ;
@@ -609,12 +596,13 @@ static enum bisect_error bisect_auto_next(struct bisect_terms *terms, const char
609
596
return bisect_next (terms , prefix );
610
597
}
611
598
612
- static int bisect_start (struct bisect_terms * terms , const char * * argv , int argc )
599
+ static enum bisect_error bisect_start (struct bisect_terms * terms , const char * * argv , int argc )
613
600
{
614
601
int no_checkout = 0 ;
615
602
int first_parent_only = 0 ;
616
603
int i , has_double_dash = 0 , must_write_terms = 0 , bad_seen = 0 ;
617
- int flags , pathspec_pos , res = 0 ;
604
+ int flags , pathspec_pos ;
605
+ enum bisect_error res = BISECT_OK ;
618
606
struct string_list revs = STRING_LIST_INIT_DUP ;
619
607
struct string_list states = STRING_LIST_INIT_DUP ;
620
608
struct strbuf start_head = STRBUF_INIT ;
@@ -753,14 +741,7 @@ static int bisect_start(struct bisect_terms *terms, const char **argv, int argc)
753
741
* Get rid of any old bisect state.
754
742
*/
755
743
if (bisect_clean_state ())
756
- return -1 ;
757
-
758
- /*
759
- * In case of mistaken revs or checkout error, or signals received,
760
- * "bisect_auto_next" below may exit or misbehave.
761
- * We have to trap this to be able to clean up using
762
- * "bisect_clean_state".
763
- */
744
+ return BISECT_FAILED ;
764
745
765
746
/*
766
747
* Write new start state
@@ -777,7 +758,7 @@ static int bisect_start(struct bisect_terms *terms, const char **argv, int argc)
777
758
}
778
759
if (update_ref (NULL , "BISECT_HEAD" , & oid , NULL , 0 ,
779
760
UPDATE_REFS_MSG_ON_ERR )) {
780
- res = -1 ;
761
+ res = BISECT_FAILED ;
781
762
goto finish ;
782
763
}
783
764
}
@@ -789,25 +770,31 @@ static int bisect_start(struct bisect_terms *terms, const char **argv, int argc)
789
770
for (i = 0 ; i < states .nr ; i ++ )
790
771
if (bisect_write (states .items [i ].string ,
791
772
revs .items [i ].string , terms , 1 )) {
792
- res = -1 ;
773
+ res = BISECT_FAILED ;
793
774
goto finish ;
794
775
}
795
776
796
777
if (must_write_terms && write_terms (terms -> term_bad ,
797
778
terms -> term_good )) {
798
- res = -1 ;
779
+ res = BISECT_FAILED ;
799
780
goto finish ;
800
781
}
801
782
802
783
res = bisect_append_log_quoted (argv );
803
784
if (res )
804
- res = -1 ;
785
+ res = BISECT_FAILED ;
805
786
806
787
finish :
807
788
string_list_clear (& revs , 0 );
808
789
string_list_clear (& states , 0 );
809
790
strbuf_release (& start_head );
810
791
strbuf_release (& bisect_names );
792
+ if (res )
793
+ return res ;
794
+
795
+ res = bisect_auto_next (terms , NULL );
796
+ if (!is_bisect_success (res ))
797
+ bisect_clean_state ();
811
798
return res ;
812
799
}
813
800
@@ -843,33 +830,94 @@ static int bisect_autostart(struct bisect_terms *terms)
843
830
return res ;
844
831
}
845
832
833
+ static enum bisect_error bisect_state (struct bisect_terms * terms , const char * * argv ,
834
+ int argc )
835
+ {
836
+ const char * state ;
837
+ int i , verify_expected = 1 ;
838
+ struct object_id oid , expected ;
839
+ struct strbuf buf = STRBUF_INIT ;
840
+ struct oid_array revs = OID_ARRAY_INIT ;
841
+
842
+ if (!argc )
843
+ return error (_ ("Please call `--bisect-state` with at least one argument" ));
844
+
845
+ if (bisect_autostart (terms ))
846
+ return BISECT_FAILED ;
847
+
848
+ state = argv [0 ];
849
+ if (check_and_set_terms (terms , state ) ||
850
+ !one_of (state , terms -> term_good , terms -> term_bad , "skip" , NULL ))
851
+ return BISECT_FAILED ;
852
+
853
+ argv ++ ;
854
+ argc -- ;
855
+ if (argc > 1 && !strcmp (state , terms -> term_bad ))
856
+ return error (_ ("'git bisect %s' can take only one argument." ), terms -> term_bad );
857
+
858
+ if (argc == 0 ) {
859
+ const char * head = "BISECT_HEAD" ;
860
+ enum get_oid_result res_head = get_oid (head , & oid );
861
+
862
+ if (res_head == MISSING_OBJECT ) {
863
+ head = "HEAD" ;
864
+ res_head = get_oid (head , & oid );
865
+ }
866
+
867
+ if (res_head )
868
+ error (_ ("Bad rev input: %s" ), head );
869
+ oid_array_append (& revs , & oid );
870
+ }
871
+
872
+ /*
873
+ * All input revs must be checked before executing bisect_write()
874
+ * to discard junk revs.
875
+ */
876
+
877
+ for (; argc ; argc -- , argv ++ ) {
878
+ if (get_oid (* argv , & oid )){
879
+ error (_ ("Bad rev input: %s" ), * argv );
880
+ return BISECT_FAILED ;
881
+ }
882
+ oid_array_append (& revs , & oid );
883
+ }
884
+
885
+ if (strbuf_read_file (& buf , git_path_bisect_expected_rev (), 0 ) < the_hash_algo -> hexsz ||
886
+ get_oid_hex (buf .buf , & expected ) < 0 )
887
+ verify_expected = 0 ; /* Ignore invalid file contents */
888
+ strbuf_release (& buf );
889
+
890
+ for (i = 0 ; i < revs .nr ; i ++ ) {
891
+ if (bisect_write (state , oid_to_hex (& revs .oid [i ]), terms , 0 ))
892
+ return BISECT_FAILED ;
893
+
894
+ if (verify_expected && !oideq (& revs .oid [i ], & expected )) {
895
+ unlink_or_warn (git_path_bisect_ancestors_ok ());
896
+ unlink_or_warn (git_path_bisect_expected_rev ());
897
+ verify_expected = 0 ;
898
+ }
899
+ }
900
+
901
+ oid_array_clear (& revs );
902
+ return bisect_auto_next (terms , NULL );
903
+ }
904
+
846
905
int cmd_bisect__helper (int argc , const char * * argv , const char * prefix )
847
906
{
848
907
enum {
849
- NEXT_ALL = 1 ,
850
- WRITE_TERMS ,
851
- BISECT_CLEAN_STATE ,
852
- CHECK_EXPECTED_REVS ,
853
- BISECT_RESET ,
908
+ BISECT_RESET = 1 ,
854
909
BISECT_WRITE ,
855
910
CHECK_AND_SET_TERMS ,
856
911
BISECT_NEXT_CHECK ,
857
912
BISECT_TERMS ,
858
913
BISECT_START ,
859
914
BISECT_AUTOSTART ,
860
915
BISECT_NEXT ,
861
- BISECT_AUTO_NEXT
916
+ BISECT_AUTO_NEXT ,
917
+ BISECT_STATE
862
918
} cmdmode = 0 ;
863
919
int res = 0 , nolog = 0 ;
864
920
struct option options [] = {
865
- OPT_CMDMODE (0 , "next-all" , & cmdmode ,
866
- N_ ("perform 'git bisect next'" ), NEXT_ALL ),
867
- OPT_CMDMODE (0 , "write-terms" , & cmdmode ,
868
- N_ ("write the terms to .git/BISECT_TERMS" ), WRITE_TERMS ),
869
- OPT_CMDMODE (0 , "bisect-clean-state" , & cmdmode ,
870
- N_ ("cleanup the bisection state" ), BISECT_CLEAN_STATE ),
871
- OPT_CMDMODE (0 , "check-expected-revs" , & cmdmode ,
872
- N_ ("check for expected revs" ), CHECK_EXPECTED_REVS ),
873
921
OPT_CMDMODE (0 , "bisect-reset" , & cmdmode ,
874
922
N_ ("reset the bisection state" ), BISECT_RESET ),
875
923
OPT_CMDMODE (0 , "bisect-write" , & cmdmode ,
@@ -886,8 +934,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
886
934
N_ ("find the next bisection commit" ), BISECT_NEXT ),
887
935
OPT_CMDMODE (0 , "bisect-auto-next" , & cmdmode ,
888
936
N_ ("verify the next bisection state then checkout the next bisection commit" ), BISECT_AUTO_NEXT ),
889
- OPT_CMDMODE (0 , "bisect-autostart " , & cmdmode ,
890
- N_ ("start the bisection if it has not yet been started " ), BISECT_AUTOSTART ),
937
+ OPT_CMDMODE (0 , "bisect-state " , & cmdmode ,
938
+ N_ ("mark the state of ref (or refs) " ), BISECT_STATE ),
891
939
OPT_BOOL (0 , "no-log" , & nolog ,
892
940
N_ ("no log for BISECT_WRITE" )),
893
941
OPT_END ()
@@ -902,20 +950,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
902
950
usage_with_options (git_bisect_helper_usage , options );
903
951
904
952
switch (cmdmode ) {
905
- case NEXT_ALL :
906
- res = bisect_next_all (the_repository , prefix );
907
- break ;
908
- case WRITE_TERMS :
909
- if (argc != 2 )
910
- return error (_ ("--write-terms requires two arguments" ));
911
- return write_terms (argv [0 ], argv [1 ]);
912
- case BISECT_CLEAN_STATE :
913
- if (argc != 0 )
914
- return error (_ ("--bisect-clean-state requires no arguments" ));
915
- return bisect_clean_state ();
916
- case CHECK_EXPECTED_REVS :
917
- check_expected_revs (argv , argc );
918
- return 0 ;
919
953
case BISECT_RESET :
920
954
if (argc > 1 )
921
955
return error (_ ("--bisect-reset requires either no argument or a commit" ));
@@ -959,11 +993,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
959
993
get_terms (& terms );
960
994
res = bisect_auto_next (& terms , prefix );
961
995
break ;
962
- case BISECT_AUTOSTART :
963
- if (argc )
964
- return error (_ ("--bisect-autostart does not accept arguments" ));
996
+ case BISECT_STATE :
965
997
set_terms (& terms , "bad" , "good" );
966
- res = bisect_autostart (& terms );
998
+ get_terms (& terms );
999
+ res = bisect_state (& terms , argv , argc );
967
1000
break ;
968
1001
default :
969
1002
BUG ("unknown subcommand %d" , cmdmode );
0 commit comments