@@ -18,6 +18,7 @@ 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>]" ),
@@ -31,6 +32,7 @@ static const char * const git_bisect_helper_usage[] = {
31
32
N_ ("git bisect--helper --bisect-replay <filename>" ),
32
33
N_ ("git bisect--helper --bisect-skip [(<rev>|<range>)...]" ),
33
34
N_ ("git bisect--helper --bisect-visualize" ),
35
+ N_ ("git bisect--helper --bisect-run <cmd>..." ),
34
36
NULL
35
37
};
36
38
@@ -144,6 +146,19 @@ static int append_to_file(const char *path, const char *format, ...)
144
146
return res ;
145
147
}
146
148
149
+ static int print_file_to_stdout (const char * path )
150
+ {
151
+ int fd = open (path , O_RDONLY );
152
+ int ret = 0 ;
153
+
154
+ if (fd < 0 )
155
+ return error_errno (_ ("cannot open file '%s' for reading" ), path );
156
+ if (copy_fd (fd , 1 ) < 0 )
157
+ ret = error_errno (_ ("failed to read '%s'" ), path );
158
+ close (fd );
159
+ return ret ;
160
+ }
161
+
147
162
static int check_term_format (const char * term , const char * orig_term )
148
163
{
149
164
int res ;
@@ -1075,6 +1090,87 @@ static int bisect_visualize(struct bisect_terms *terms, const char **argv, int a
1075
1090
return res ;
1076
1091
}
1077
1092
1093
+ static int bisect_run (struct bisect_terms * terms , const char * * argv , int argc )
1094
+ {
1095
+ int res = BISECT_OK ;
1096
+ struct strbuf command = STRBUF_INIT ;
1097
+ struct strvec args = STRVEC_INIT ;
1098
+ struct strvec run_args = STRVEC_INIT ;
1099
+ const char * new_state ;
1100
+ int temporary_stdout_fd , saved_stdout ;
1101
+
1102
+ if (bisect_next_check (terms , NULL ))
1103
+ return BISECT_FAILED ;
1104
+
1105
+ if (argc )
1106
+ sq_quote_argv (& command , argv );
1107
+ else {
1108
+ error (_ ("bisect run failed: no command provided." ));
1109
+ return BISECT_FAILED ;
1110
+ }
1111
+
1112
+ strvec_push (& run_args , command .buf );
1113
+
1114
+ while (1 ) {
1115
+ strvec_clear (& args );
1116
+
1117
+ printf (_ ("running %s\n" ), command .buf );
1118
+ res = run_command_v_opt (run_args .v , RUN_USING_SHELL );
1119
+
1120
+ if (res < 0 || 128 <= res ) {
1121
+ error (_ ("bisect run failed: exit code %d from"
1122
+ " '%s' is < 0 or >= 128" ), res , command .buf );
1123
+ strbuf_release (& command );
1124
+ return res ;
1125
+ }
1126
+
1127
+ if (res == 125 )
1128
+ new_state = "skip" ;
1129
+ else if (!res )
1130
+ new_state = terms -> term_good ;
1131
+ else
1132
+ new_state = terms -> term_bad ;
1133
+
1134
+ temporary_stdout_fd = open (git_path_bisect_run (), O_CREAT | O_WRONLY | O_TRUNC , 0666 );
1135
+
1136
+ if (temporary_stdout_fd < 0 )
1137
+ return error_errno (_ ("cannot open file '%s' for writing" ), git_path_bisect_run ());
1138
+
1139
+ fflush (stdout );
1140
+ saved_stdout = dup (1 );
1141
+ dup2 (temporary_stdout_fd , 1 );
1142
+
1143
+ res = bisect_state (terms , & new_state , 1 );
1144
+
1145
+ fflush (stdout );
1146
+ dup2 (saved_stdout , 1 );
1147
+ close (saved_stdout );
1148
+ close (temporary_stdout_fd );
1149
+
1150
+ print_file_to_stdout (git_path_bisect_run ());
1151
+
1152
+ if (res == BISECT_ONLY_SKIPPED_LEFT )
1153
+ error (_ ("bisect run cannot continue any more" ));
1154
+ else if (res == BISECT_INTERNAL_SUCCESS_MERGE_BASE ) {
1155
+ printf (_ ("bisect run success" ));
1156
+ res = BISECT_OK ;
1157
+ } else if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND ) {
1158
+ printf (_ ("bisect found first bad commit" ));
1159
+ res = BISECT_OK ;
1160
+ } else if (res ) {
1161
+ error (_ ("bisect run failed:'git bisect--helper --bisect-state"
1162
+ " %s' exited with error code %d" ), args .v [0 ], res );
1163
+ } else {
1164
+ continue ;
1165
+ }
1166
+
1167
+ strbuf_release (& command );
1168
+ strvec_clear (& args );
1169
+ strvec_clear (& run_args );
1170
+ return res ;
1171
+ }
1172
+ }
1173
+
1078
1174
int cmd_bisect__helper (int argc , const char * * argv , const char * prefix )
1079
1175
{
1080
1176
enum {
@@ -1089,6 +1185,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
1089
1185
BISECT_REPLAY ,
1090
1186
BISECT_SKIP ,
1091
1187
BISECT_VISUALIZE ,
1188
+ BISECT_RUN ,
1092
1189
} cmdmode = 0 ;
1093
1190
int res = 0 , nolog = 0 ;
1094
1191
struct option options [] = {
@@ -1112,6 +1209,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
1112
1209
N_ ("skip some commits for checkout" ), BISECT_SKIP ),
1113
1210
OPT_CMDMODE (0 , "bisect-visualize" , & cmdmode ,
1114
1211
N_ ("visualize the bisection" ), BISECT_VISUALIZE ),
1212
+ OPT_CMDMODE (0 , "bisect-run" , & cmdmode ,
1213
+ N_ ("use <cmd>... to automatically bisect." ), BISECT_RUN ),
1115
1214
OPT_BOOL (0 , "no-log" , & nolog ,
1116
1215
N_ ("no log for BISECT_WRITE" )),
1117
1216
OPT_END ()
@@ -1177,6 +1276,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
1177
1276
get_terms (& terms );
1178
1277
res = bisect_visualize (& terms , argv , argc );
1179
1278
break ;
1279
+ case BISECT_RUN :
1280
+ if (!argc )
1281
+ return error (_ ("bisect run failed: no command provided." ));
1282
+ get_terms (& terms );
1283
+ res = bisect_run (& terms , argv , argc );
1284
+ break ;
1180
1285
default :
1181
1286
BUG ("unknown subcommand %d" , cmdmode );
1182
1287
}
0 commit comments