@@ -18,10 +18,10 @@ static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG")
18
18
static GIT_PATH_FUNC (git_path_head_name , "head - name ")
19
19
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
+ static GIT_PATH_FUNC (git_path_bisect_run , "BISECT_RUN ")
21
22
22
23
static const char * const git_bisect_helper_usage [] = {
23
24
N_ ("git bisect--helper --bisect-reset [<commit>]" ),
24
- N_ ("git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]" ),
25
25
N_ ("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]" ),
26
26
N_ ("git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}=<term>]"
27
27
" [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]" ),
@@ -30,6 +30,8 @@ static const char * const git_bisect_helper_usage[] = {
30
30
N_ ("git bisect--helper --bisect-state (good|old) [<rev>...]" ),
31
31
N_ ("git bisect--helper --bisect-replay <filename>" ),
32
32
N_ ("git bisect--helper --bisect-skip [(<rev>|<range>)...]" ),
33
+ N_ ("git bisect--helper --bisect-visualize" ),
34
+ N_ ("git bisect--helper --bisect-run <cmd>..." ),
33
35
NULL
34
36
};
35
37
@@ -143,6 +145,19 @@ static int append_to_file(const char *path, const char *format, ...)
143
145
return res ;
144
146
}
145
147
148
+ static int print_file_to_stdout (const char * path )
149
+ {
150
+ int fd = open (path , O_RDONLY );
151
+ int ret = 0 ;
152
+
153
+ if (fd < 0 )
154
+ return error_errno (_ ("cannot open file '%s' for reading" ), path );
155
+ if (copy_fd (fd , 1 ) < 0 )
156
+ ret = error_errno (_ ("failed to read '%s'" ), path );
157
+ close (fd );
158
+ return ret ;
159
+ }
160
+
146
161
static int check_term_format (const char * term , const char * orig_term )
147
162
{
148
163
int res ;
@@ -1036,6 +1051,125 @@ static enum bisect_error bisect_skip(struct bisect_terms *terms, const char **ar
1036
1051
return res ;
1037
1052
}
1038
1053
1054
+ static int bisect_visualize (struct bisect_terms * terms , const char * * argv , int argc )
1055
+ {
1056
+ struct strvec args = STRVEC_INIT ;
1057
+ int flags = RUN_COMMAND_NO_STDIN , res = 0 ;
1058
+ struct strbuf sb = STRBUF_INIT ;
1059
+
1060
+ if (bisect_next_check (terms , NULL ) != 0 )
1061
+ return BISECT_FAILED ;
1062
+
1063
+ if (!argc ) {
1064
+ if ((getenv ("DISPLAY" ) || getenv ("SESSIONNAME" ) || getenv ("MSYSTEM" ) ||
1065
+ getenv ("SECURITYSESSIONID" )) && exists_in_PATH ("gitk" )) {
1066
+ strvec_push (& args , "gitk" );
1067
+ } else {
1068
+ strvec_push (& args , "log" );
1069
+ flags |= RUN_GIT_CMD ;
1070
+ }
1071
+ } else {
1072
+ if (argv [0 ][0 ] == '-' ) {
1073
+ strvec_push (& args , "log" );
1074
+ flags |= RUN_GIT_CMD ;
1075
+ } else if (strcmp (argv [0 ], "tig" ) && !starts_with (argv [0 ], "git" ))
1076
+ flags |= RUN_GIT_CMD ;
1077
+
1078
+ strvec_pushv (& args , argv );
1079
+ }
1080
+
1081
+ strvec_pushl (& args , "--bisect" , "--" , NULL );
1082
+
1083
+ strbuf_read_file (& sb , git_path_bisect_names (), 0 );
1084
+ sq_dequote_to_strvec (sb .buf , & args );
1085
+ strbuf_release (& sb );
1086
+
1087
+ res = run_command_v_opt (args .v , flags );
1088
+ strvec_clear (& args );
1089
+ return res ;
1090
+ }
1091
+
1092
+ static int bisect_run (struct bisect_terms * terms , const char * * argv , int argc )
1093
+ {
1094
+ int res = BISECT_OK ;
1095
+ struct strbuf command = STRBUF_INIT ;
1096
+ struct strvec args = STRVEC_INIT ;
1097
+ struct strvec run_args = STRVEC_INIT ;
1098
+ const char * new_state ;
1099
+ int temporary_stdout_fd , saved_stdout ;
1100
+
1101
+ if (bisect_next_check (terms , NULL ))
1102
+ return BISECT_FAILED ;
1103
+
1104
+ if (argc )
1105
+ sq_quote_argv (& command , argv );
1106
+ else {
1107
+ error (_ ("bisect run failed: no command provided." ));
1108
+ return BISECT_FAILED ;
1109
+ }
1110
+
1111
+ strvec_push (& run_args , command .buf );
1112
+
1113
+ while (1 ) {
1114
+ strvec_clear (& args );
1115
+
1116
+ printf (_ ("running %s\n" ), command .buf );
1117
+ res = run_command_v_opt (run_args .v , RUN_USING_SHELL );
1118
+
1119
+ if (res < 0 || 128 <= res ) {
1120
+ error (_ ("bisect run failed: exit code %d from"
1121
+ " '%s' is < 0 or >= 128" ), res , command .buf );
1122
+ strbuf_release (& command );
1123
+ return res ;
1124
+ }
1125
+
1126
+ if (res == 125 )
1127
+ new_state = "skip" ;
1128
+ else if (!res )
1129
+ new_state = terms -> term_good ;
1130
+ else
1131
+ new_state = terms -> term_bad ;
1132
+
1133
+ temporary_stdout_fd = open (git_path_bisect_run (), O_CREAT | O_WRONLY | O_TRUNC , 0666 );
1134
+
1135
+ if (temporary_stdout_fd < 0 )
1136
+ return error_errno (_ ("cannot open file '%s' for writing" ), git_path_bisect_run ());
1137
+
1138
+ fflush (stdout );
1139
+ saved_stdout = dup (1 );
1140
+ dup2 (temporary_stdout_fd , 1 );
1141
+
1142
+ res = bisect_state (terms , & new_state , 1 );
1143
+
1144
+ fflush (stdout );
1145
+ dup2 (saved_stdout , 1 );
1146
+ close (saved_stdout );
1147
+ close (temporary_stdout_fd );
1148
+
1149
+ print_file_to_stdout (git_path_bisect_run ());
1150
+
1151
+ if (res == BISECT_ONLY_SKIPPED_LEFT )
1152
+ error (_ ("bisect run cannot continue any more" ));
1153
+ else if (res == BISECT_INTERNAL_SUCCESS_MERGE_BASE ) {
1154
+ printf (_ ("bisect run success" ));
1155
+ res = BISECT_OK ;
1156
+ } else if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND ) {
1157
+ printf (_ ("bisect found first bad commit" ));
1158
+ res = BISECT_OK ;
1159
+ } else if (res ) {
1160
+ error (_ ("bisect run failed:'git bisect--helper --bisect-state"
1161
+ " %s' exited with error code %d" ), args .v [0 ], res );
1162
+ } else {
1163
+ continue ;
1164
+ }
1165
+
1166
+ strbuf_release (& command );
1167
+ strvec_clear (& args );
1168
+ strvec_clear (& run_args );
1169
+ return res ;
1170
+ }
1171
+ }
1172
+
1039
1173
int cmd_bisect__helper (int argc , const char * * argv , const char * prefix )
1040
1174
{
1041
1175
enum {
@@ -1048,7 +1182,9 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
1048
1182
BISECT_STATE ,
1049
1183
BISECT_LOG ,
1050
1184
BISECT_REPLAY ,
1051
- BISECT_SKIP
1185
+ BISECT_SKIP ,
1186
+ BISECT_VISUALIZE ,
1187
+ BISECT_RUN ,
1052
1188
} cmdmode = 0 ;
1053
1189
int res = 0 , nolog = 0 ;
1054
1190
struct option options [] = {
@@ -1070,6 +1206,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
1070
1206
N_ ("replay the bisection process from the given file" ), BISECT_REPLAY ),
1071
1207
OPT_CMDMODE (0 , "bisect-skip" , & cmdmode ,
1072
1208
N_ ("skip some commits for checkout" ), BISECT_SKIP ),
1209
+ OPT_CMDMODE (0 , "bisect-visualize" , & cmdmode ,
1210
+ N_ ("visualize the bisection" ), BISECT_VISUALIZE ),
1211
+ OPT_CMDMODE (0 , "bisect-run" , & cmdmode ,
1212
+ N_ ("use <cmd>... to automatically bisect." ), BISECT_RUN ),
1073
1213
OPT_BOOL (0 , "no-log" , & nolog ,
1074
1214
N_ ("no log for BISECT_WRITE" )),
1075
1215
OPT_END ()
@@ -1089,12 +1229,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
1089
1229
return error (_ ("--bisect-reset requires either no argument or a commit" ));
1090
1230
res = bisect_reset (argc ? argv [0 ] : NULL );
1091
1231
break ;
1092
- case BISECT_NEXT_CHECK :
1093
- if (argc != 2 && argc != 3 )
1094
- return error (_ ("--bisect-next-check requires 2 or 3 arguments" ));
1095
- set_terms (& terms , argv [1 ], argv [0 ]);
1096
- res = bisect_next_check (& terms , argc == 3 ? argv [2 ] : NULL );
1097
- break ;
1098
1232
case BISECT_TERMS :
1099
1233
if (argc > 1 )
1100
1234
return error (_ ("--bisect-terms requires 0 or 1 argument" ));
@@ -1131,6 +1265,16 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
1131
1265
get_terms (& terms );
1132
1266
res = bisect_skip (& terms , argv , argc );
1133
1267
break ;
1268
+ case BISECT_VISUALIZE :
1269
+ get_terms (& terms );
1270
+ res = bisect_visualize (& terms , argv , argc );
1271
+ break ;
1272
+ case BISECT_RUN :
1273
+ if (!argc )
1274
+ return error (_ ("bisect run failed: no command provided." ));
1275
+ get_terms (& terms );
1276
+ res = bisect_run (& terms , argv , argc );
1277
+ break ;
1134
1278
default :
1135
1279
BUG ("unknown subcommand %d" , cmdmode );
1136
1280
}
0 commit comments