commit: Let the callback of for_each_mergetag return on error

This is yet another patch to be filed under the keyword "libification". There is one subtle change in behavior here, where a `git log` that has been asked to show the mergetags would now stop reporting the mergetags upon the first failure, whereas previously, it would have continued to the next mergetag, if any. In practice, that change should not matter, as it is 1) uncommon to perform octopus merges using multiple tags as merge heads, and 2) when the user asks to be shown those tags, they really should be there. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Apr 25, 2018 at 11:54 UTC fef461ea5d53dd84c6d946f57a018ffc9f391a05
4 files changed +18 -15
builtin/replace.c
+4 -4
@@ -345,7 +345,7 @@ struct check_mergetag_data {
345 const char **argv;
346 };
347
348 -static void check_one_mergetag(struct commit *commit,
348 +static int check_one_mergetag(struct commit *commit,
349 struct commit_extra_header *extra,
350 void *data)
351 {
@@ -368,20 +368,20 @@ static void check_one_mergetag(struct commit *commit,
368 if (get_oid(mergetag_data->argv[i], &oid) < 0)
369 die(_("Not a valid object name: '%s'"), mergetag_data->argv[i]);
370 if (!oidcmp(&tag->tagged->oid, &oid))
371 - return; /* found */
371 + return 0; /* found */
372 }
373
374 die(_("original commit '%s' contains mergetag '%s' that is discarded; "
375 "use --edit instead of --graft"), ref, oid_to_hex(&tag_oid));
376 }
377
378 -static void check_mergetags(struct commit *commit, int argc, const char **argv)
378 +static int check_mergetags(struct commit *commit, int argc, const char **argv)
379 {
380 struct check_mergetag_data mergetag_data;
381
382 mergetag_data.argc = argc;
383 mergetag_data.argv = argv;
384 - for_each_mergetag(check_one_mergetag, commit, &mergetag_data);
384 + return for_each_mergetag(check_one_mergetag, commit, &mergetag_data);
385 }
386
387 static int create_graft(int argc, const char **argv, int force)
commit.c
+5 -3
@@ -1288,17 +1288,19 @@ struct commit_extra_header *read_commit_extra_headers(struct commit *commit,
1288 return extra;
1289 }
1290
1291 -void for_each_mergetag(each_mergetag_fn fn, struct commit *commit, void *data)
1291 +int for_each_mergetag(each_mergetag_fn fn, struct commit *commit, void *data)
1292 {
1293 struct commit_extra_header *extra, *to_free;
1294 + int res = 0;
1295
1296 to_free = read_commit_extra_headers(commit, NULL);
1296 - for (extra = to_free; extra; extra = extra->next) {
1297 + for (extra = to_free; !res && extra; extra = extra->next) {
1298 if (strcmp(extra->key, "mergetag"))
1299 continue; /* not a merge tag */
1299 - fn(commit, extra, data);
1300 + res = fn(commit, extra, data);
1301 }
1302 free_commit_extra_headers(to_free);
1303 + return res;
1304 }
1305
1306 static inline int standard_header_field(const char *field, size_t len)
commit.h
+2 -2
@@ -291,10 +291,10 @@ extern const char *find_commit_header(const char *msg, const char *key,
291 /* Find the end of the log message, the right place for a new trailer. */
292 extern int ignore_non_trailer(const char *buf, size_t len);
293
294 -typedef void (*each_mergetag_fn)(struct commit *commit, struct commit_extra_header *extra,
294 +typedef int (*each_mergetag_fn)(struct commit *commit, struct commit_extra_header *extra,
295 void *cb_data);
296
297 -extern void for_each_mergetag(each_mergetag_fn fn, struct commit *commit, void *data);
297 +extern int for_each_mergetag(each_mergetag_fn fn, struct commit *commit, void *data);
298
299 struct merge_remote_desc {
300 struct object *obj; /* the named object, could be a tag */
log-tree.c
+7 -6
@@ -488,9 +488,9 @@ static int is_common_merge(const struct commit *commit)
488 && !commit->parents->next->next);
489 }
490
491 -static void show_one_mergetag(struct commit *commit,
492 - struct commit_extra_header *extra,
493 - void *data)
491 +static int show_one_mergetag(struct commit *commit,
492 + struct commit_extra_header *extra,
493 + void *data)
494 {
495 struct rev_info *opt = (struct rev_info *)data;
496 struct object_id oid;
@@ -502,7 +502,7 @@ static void show_one_mergetag(struct commit *commit,
502 hash_object_file(extra->value, extra->len, type_name(OBJ_TAG), &oid);
503 tag = lookup_tag(&oid);
504 if (!tag)
505 - return; /* error message already given */
505 + return -1; /* error message already given */
506
507 strbuf_init(&verify_message, 256);
508 if (parse_tag_buffer(tag, extra->value, extra->len))
@@ -536,11 +536,12 @@ static void show_one_mergetag(struct commit *commit,
536
537 show_sig_lines(opt, status, verify_message.buf);
538 strbuf_release(&verify_message);
539 + return 0;
540 }
541
541 -static void show_mergetag(struct rev_info *opt, struct commit *commit)
542 +static int show_mergetag(struct rev_info *opt, struct commit *commit)
543 {
543 - for_each_mergetag(show_one_mergetag, commit, opt);
544 + return for_each_mergetag(show_one_mergetag, commit, opt);
545 }
546
547 void show_log(struct rev_info *opt)