24
static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG")
25
static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
26
static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
27
+static GIT_PATH_FUNC(git_path_bisect_reset_when_found, "BISECT_RESET_WHEN_FOUND")
28
static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
29
30
#define BUILTIN_GIT_BISECT_START_USAGE \
31
N_("git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n" \
31
- " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]")
32
+ " [--no-checkout] [--first-parent] [--reset-when-found[=<where>]] [<bad> [<good>...]] [--] [<pathspec>...]")
33
#define BUILTIN_GIT_BISECT_BAD_USAGE \
34
N_("git bisect (bad|new|<term-new>) [<rev>]")
35
#define BUILTIN_GIT_BISECT_GOOD_USAGE \
49
#define BUILTIN_GIT_BISECT_LOG_USAGE \
50
"git bisect log"
51
#define BUILTIN_GIT_BISECT_RUN_USAGE \
51
- N_("git bisect run <cmd> [<arg>...]")
52
+ N_("git bisect run [--reset-when-found[=<where>]] <cmd> [<arg>...]")
53
#define BUILTIN_GIT_BISECT_HELP_USAGE \
54
"git bisect help"
55
69
NULL
70
};
71
72
+enum reset_when_found_mode {
73
+ RESET_WHEN_FOUND_NONE,
74
+ RESET_WHEN_FOUND_TO_ORIGINAL,
75
+ RESET_WHEN_FOUND_TO_FOUND,
76
+};
77
+
78
struct add_bisect_ref_data {
79
struct rev_info *revs;
80
unsigned int object_flags;
276
}
277
278
strbuf_release(&branch);
272
- return bisect_clean_state();
279
+ return 0;
280
+}
281
+
282
+static int parse_reset_when_found(const char *value,
283
+ enum reset_when_found_mode *mode)
284
+{
285
+ if (!strcmp(value, "original"))
286
+ *mode = RESET_WHEN_FOUND_TO_ORIGINAL;
287
+ else if (!strcmp(value, "found"))
288
+ *mode = RESET_WHEN_FOUND_TO_FOUND;
289
+ else
290
+ return error(_("invalid value for '--reset-when-found': '%s'"),
291
+ value);
292
+
293
+ return 0;
294
+}
295
+
296
+static const char *reset_when_found_mode_name(enum reset_when_found_mode mode)
297
+{
298
+ switch (mode) {
299
+ case RESET_WHEN_FOUND_TO_ORIGINAL:
300
+ return "original";
301
+ case RESET_WHEN_FOUND_TO_FOUND:
302
+ return "found";
303
+ case RESET_WHEN_FOUND_NONE:
304
+ BUG("no name for unset reset-when-found mode");
305
+ }
306
+ BUG("unknown reset-when-found mode %d", mode);
307
+}
308
+
309
+static int read_reset_when_found(enum reset_when_found_mode *mode)
310
+{
311
+ struct strbuf value = STRBUF_INIT;
312
+ int res = 0;
313
+
314
+ *mode = RESET_WHEN_FOUND_NONE;
315
+ if (is_empty_or_missing_file(git_path_bisect_reset_when_found()))
316
+ return 0;
317
+
318
+ if (strbuf_read_file(&value, git_path_bisect_reset_when_found(), 0) < 0) {
319
+ res = error_errno(_("could not read '%s'"),
320
+ git_path_bisect_reset_when_found());
321
+ goto out;
322
+ }
323
+ strbuf_trim(&value);
324
+ if (parse_reset_when_found(value.buf, mode))
325
+ res = -1;
326
+
327
+out:
328
+ strbuf_release(&value);
329
+ return res;
330
+}
331
+
332
+static int bisect_reset_when_found(enum reset_when_found_mode mode)
333
+{
334
+ struct bisect_terms terms = { 0 };
335
+ char *commit = NULL;
336
+ int res;
337
+
338
+ if (mode == RESET_WHEN_FOUND_TO_FOUND) {
339
+ read_bisect_terms(&terms.term_bad, &terms.term_good);
340
+ commit = xstrfmt("refs/bisect/%s", terms.term_bad);
341
+ } else if (mode == RESET_WHEN_FOUND_NONE) {
342
+ BUG("automatic reset requested without a reset mode");
343
+ }
344
+
345
+ res = bisect_reset(commit, true);
346
+ if (!res)
347
+ res = bisect_clean_state();
348
+
349
+ free(commit);
350
+ free_terms(&terms);
351
+ return res;
352
}
353
354
static void log_commit(FILE *fp,
756
return res;
757
}
758
680
-static enum bisect_error bisect_next(struct bisect_terms *terms, const char *prefix)
759
+static enum bisect_error bisect_next(struct bisect_terms *terms,
760
+ const char *prefix)
761
{
762
enum bisect_error res;
763
780
return res;
781
}
782
703
-static enum bisect_error bisect_auto_next(struct bisect_terms *terms, const char *prefix)
783
+static enum bisect_error bisect_auto_next(struct bisect_terms *terms,
784
+ const char *prefix)
785
{
786
if (bisect_next_check(terms, NULL)) {
787
bisect_print_status(terms);
805
struct strbuf bisect_names = STRBUF_INIT;
806
struct object_id head_oid;
807
struct object_id oid;
808
+ enum reset_when_found_mode reset_when_found = RESET_WHEN_FOUND_NONE;
809
const char *head;
810
811
if (is_bare_repository(the_repository))
829
no_checkout = 1;
830
} else if (!strcmp(arg, "--first-parent")) {
831
first_parent_only = 1;
832
+ } else if (!strcmp(arg, "--reset-when-found")) {
833
+ reset_when_found = RESET_WHEN_FOUND_TO_ORIGINAL;
834
+ } else if (skip_prefix(arg, "--reset-when-found=", &arg)) {
835
+ if (parse_reset_when_found(arg, &reset_when_found)) {
836
+ res = BISECT_FAILED;
837
+ goto finish;
838
+ }
839
} else if (!strcmp(arg, "--term-good") ||
840
!strcmp(arg, "--term-old")) {
841
i++;
873
break;
874
}
875
}
876
+ if (reset_when_found != RESET_WHEN_FOUND_NONE && no_checkout) {
877
+ res = error(_("options '%s' and '%s' cannot be used together"),
878
+ "--reset-when-found", "--no-checkout");
879
+ goto finish;
880
+ }
881
pathspec_pos = i;
882
883
/*
955
if (first_parent_only)
956
write_file(git_path_bisect_first_parent(), "\n");
957
958
+ if (reset_when_found != RESET_WHEN_FOUND_NONE)
959
+ write_file(git_path_bisect_reset_when_found(), "%s\n",
960
+ reset_when_found_mode_name(reset_when_found));
961
+
962
if (no_checkout) {
963
if (repo_get_oid(the_repository, start_head.buf, &oid) < 0) {
964
res = error(_("invalid ref: '%s'"), start_head.buf);
1189
if (is_empty_or_missing_file(filename))
1190
return error(_("cannot read file '%s' for replaying"), filename);
1191
1094
- if (bisect_reset(NULL, false))
1192
+ if (bisect_clean_state())
1193
return BISECT_FAILED;
1194
1195
fp = fopen(filename, "r");
1337
{
1338
int res = BISECT_OK;
1339
struct strbuf command = STRBUF_INIT;
1340
+ const char *reset_when_found_arg;
1341
const char *new_state;
1342
int temporary_stdout_fd, saved_stdout;
1343
int is_first_run = 1;
1344
+ enum reset_when_found_mode reset_when_found = RESET_WHEN_FOUND_NONE;
1345
1346
if (bisect_next_check(terms, NULL))
1347
return BISECT_FAILED;
1348
1349
+ if (argc && !strcmp(argv[0], "--reset-when-found")) {
1350
+ reset_when_found = RESET_WHEN_FOUND_TO_ORIGINAL;
1351
+ } else if (argc && skip_prefix(argv[0], "--reset-when-found=",
1352
+ &reset_when_found_arg)) {
1353
+ if (parse_reset_when_found(reset_when_found_arg,
1354
+ &reset_when_found))
1355
+ return BISECT_FAILED;
1356
+ }
1357
+
1358
+ if (reset_when_found != RESET_WHEN_FOUND_NONE &&
1359
+ refs_ref_exists(get_main_ref_store(the_repository), "BISECT_HEAD"))
1360
+ return error(_("options '%s' and '%s' cannot be used together"),
1361
+ "--reset-when-found", "--no-checkout");
1362
+
1363
+ if (reset_when_found != RESET_WHEN_FOUND_NONE) {
1364
+ write_file(git_path_bisect_reset_when_found(), "%s\n",
1365
+ reset_when_found_mode_name(reset_when_found));
1366
+ argc--;
1367
+ argv++;
1368
+ }
1369
+
1370
if (!argc) {
1371
error(_("bisect run failed: no command provided."));
1372
return BISECT_FAILED;
1441
res = BISECT_OK;
1442
} else if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) {
1443
printf(_("bisect found first '%s' commit\n"), terms->term_bad);
1323
- res = BISECT_OK;
1444
} else if (res) {
1445
error(_("bisect run failed: 'git bisect %s'"
1446
" exited with error code %d"), new_state, res);
1457
static int cmd_bisect__reset(int argc, const char **argv, const char *prefix UNUSED,
1458
struct repository *repo UNUSED)
1459
{
1460
+ int res;
1461
+
1462
if (argc > 1)
1463
return error(_("'%s' requires either no argument or a commit"),
1464
"git bisect reset");
1343
- return bisect_reset(argc ? argv[0] : NULL, false);
1465
+ res = bisect_reset(argc ? argv[0] : NULL, false);
1466
+ if (res)
1467
+ return res;
1468
+ return bisect_clean_state();
1469
}
1470
1471
static int cmd_bisect__terms(int argc, const char **argv, const char *prefix UNUSED,
1607
!one_of(argv[0], terms.term_good, terms.term_bad, NULL))
1608
usage_msg_optf(_("unknown command: '%s'"), git_bisect_usage,
1609
options, argv[0]);
1485
- res = bisect_state(&terms, argc, argv);
1610
+ else
1611
+ res = bisect_state(&terms, argc, argv);
1612
free_terms(&terms);
1613
} else {
1614
argc--;
1616
res = fn(argc, argv, prefix, repo);
1617
}
1618
1619
+ if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) {
1620
+ enum reset_when_found_mode mode;
1621
+
1622
+ if (read_reset_when_found(&mode))
1623
+ res = BISECT_FAILED;
1624
+ else if (mode != RESET_WHEN_FOUND_NONE &&
1625
+ bisect_reset_when_found(mode))
1626
+ res = BISECT_FAILED;
1627
+ }
1628
+
1629
return is_bisect_success(res) ? 0 : -res;
1630
}