12
static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, "BISECT_ANCESTORS_OK")
13
static GIT_PATH_FUNC(git_path_bisect_start, "BISECT_START")
14
static GIT_PATH_FUNC(git_path_bisect_head, "BISECT_HEAD")
15
+static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG")
16
17
static const char * const git_bisect_helper_usage[] = {
18
N_("git bisect--helper --next-all [--no-checkout]"),
19
N_("git bisect--helper --write-terms <bad_term> <good_term>"),
20
N_("git bisect--helper --bisect-clean-state"),
21
N_("git bisect--helper --bisect-reset [<commit>]"),
22
+ N_("git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>"),
23
NULL
24
};
25
26
+struct bisect_terms {
27
+ char *term_good;
28
+ char *term_bad;
29
+};
30
+
31
+static void free_terms(struct bisect_terms *terms)
32
+{
33
+ FREE_AND_NULL(terms->term_good);
34
+ FREE_AND_NULL(terms->term_bad);
35
+}
36
+
37
+static void set_terms(struct bisect_terms *terms, const char *bad,
38
+ const char *good)
39
+{
40
+ free((void *)terms->term_good);
41
+ terms->term_good = xstrdup(good);
42
+ free((void *)terms->term_bad);
43
+ terms->term_bad = xstrdup(bad);
44
+}
45
+
46
/*
47
* Check whether the string `term` belongs to the set of strings
48
* included in the variable arguments.
170
return bisect_clean_state();
171
}
172
173
+static void log_commit(FILE *fp, char *fmt, const char *state,
174
+ struct commit *commit)
175
+{
176
+ struct pretty_print_context pp = {0};
177
+ struct strbuf commit_msg = STRBUF_INIT;
178
+ char *label = xstrfmt(fmt, state);
179
+
180
+ format_commit_message(commit, "%s", &commit_msg, &pp);
181
+
182
+ fprintf(fp, "# %s: [%s] %s\n", label, oid_to_hex(&commit->object.oid),
183
+ commit_msg.buf);
184
+
185
+ strbuf_release(&commit_msg);
186
+ free(label);
187
+}
188
+
189
+static int bisect_write(const char *state, const char *rev,
190
+ const struct bisect_terms *terms, int nolog)
191
+{
192
+ struct strbuf tag = STRBUF_INIT;
193
+ struct object_id oid;
194
+ struct commit *commit;
195
+ FILE *fp = NULL;
196
+ int retval = 0;
197
+
198
+ if (!strcmp(state, terms->term_bad)) {
199
+ strbuf_addf(&tag, "refs/bisect/%s", state);
200
+ } else if (one_of(state, terms->term_good, "skip", NULL)) {
201
+ strbuf_addf(&tag, "refs/bisect/%s-%s", state, rev);
202
+ } else {
203
+ retval = error(_("Bad bisect_write argument: %s"), state);
204
+ goto finish;
205
+ }
206
+
207
+ if (get_oid(rev, &oid)) {
208
+ retval = error(_("couldn't get the oid of the rev '%s'"), rev);
209
+ goto finish;
210
+ }
211
+
212
+ if (update_ref(NULL, tag.buf, &oid, NULL, 0,
213
+ UPDATE_REFS_MSG_ON_ERR)) {
214
+ retval = -1;
215
+ goto finish;
216
+ }
217
+
218
+ fp = fopen(git_path_bisect_log(), "a");
219
+ if (!fp) {
220
+ retval = error_errno(_("couldn't open the file '%s'"), git_path_bisect_log());
221
+ goto finish;
222
+ }
223
+
224
+ commit = lookup_commit_reference(the_repository, &oid);
225
+ log_commit(fp, "%s", state, commit);
226
+
227
+ if (!nolog)
228
+ fprintf(fp, "git bisect %s %s\n", state, rev);
229
+
230
+finish:
231
+ if (fp)
232
+ fclose(fp);
233
+ strbuf_release(&tag);
234
+ return retval;
235
+}
236
+
237
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
238
{
239
enum {
241
WRITE_TERMS,
242
BISECT_CLEAN_STATE,
243
CHECK_EXPECTED_REVS,
158
- BISECT_RESET
244
+ BISECT_RESET,
245
+ BISECT_WRITE
246
} cmdmode = 0;
160
- int no_checkout = 0;
247
+ int no_checkout = 0, res = 0, nolog = 0;
248
struct option options[] = {
249
OPT_CMDMODE(0, "next-all", &cmdmode,
250
N_("perform 'git bisect next'"), NEXT_ALL),
256
N_("check for expected revs"), CHECK_EXPECTED_REVS),
257
OPT_CMDMODE(0, "bisect-reset", &cmdmode,
258
N_("reset the bisection state"), BISECT_RESET),
259
+ OPT_CMDMODE(0, "bisect-write", &cmdmode,
260
+ N_("write out the bisection state in BISECT_LOG"), BISECT_WRITE),
261
OPT_BOOL(0, "no-checkout", &no_checkout,
262
N_("update BISECT_HEAD instead of checking out the current commit")),
263
+ OPT_BOOL(0, "no-log", &nolog,
264
+ N_("no log for BISECT_WRITE ")),
265
OPT_END()
266
};
267
+ struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL };
268
269
argc = parse_options(argc, argv, prefix, options,
270
git_bisect_helper_usage, 0);
290
if (argc > 1)
291
return error(_("--bisect-reset requires either no argument or a commit"));
292
return !!bisect_reset(argc ? argv[0] : NULL);
293
+ case BISECT_WRITE:
294
+ if (argc != 4 && argc != 5)
295
+ return error(_("--bisect-write requires either 4 or 5 arguments"));
296
+ set_terms(&terms, argv[3], argv[2]);
297
+ res = bisect_write(argv[0], argv[1], &terms, nolog);
298
+ break;
299
default:
300
return error("BUG: unknown subcommand '%d'", cmdmode);
301
}
204
- return 0;
302
+ free_terms(&terms);
303
+ return !!res;
304
}