Skip to content

Commit dc1c9bb

Browse files
committed
Merge branch 'js/am-3-merge-recursive-direct' into next
"git am -3" calls "git merge-recursive" when it needs to fall back to a three-way merge; this call has been turned into an internal subroutine call instead of spawning a separate subprocess. * js/am-3-merge-recursive-direct: merge-recursive: flush output buffer even when erroring out merge_trees(): ensure that the callers release output buffer merge-recursive: offer an option to retain the output in 'obuf' merge-recursive: write the commit title in one go merge-recursive: flush output buffer before printing error messages am -3: use merge_recursive() directly again merge-recursive: switch to returning errors instead of dying merge-recursive: handle return values indicating errors merge-recursive: allow write_tree_from_memory() to error out merge-recursive: avoid returning a wholesale struct merge_recursive: abort properly upon errors prepare the builtins for a libified merge_recursive() merge-recursive: clarify code in was_tracked() die(_("BUG")): avoid translating bug messages die("bug"): report bugs consistently t5520: verify that `pull --rebase` shows the helpful advice when failing
2 parents b31baa7 + 6999bc7 commit dc1c9bb

15 files changed

+419
-294
lines changed

builtin/am.c

Lines changed: 22 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,56 +1578,27 @@ static int build_fake_ancestor(const struct am_state *state, const char *index_f
15781578
return 0;
15791579
}
15801580

1581-
/**
1582-
* Do the three-way merge using fake ancestor, their tree constructed
1583-
* from the fake ancestor and the postimage of the patch, and our
1584-
* state.
1585-
*/
1586-
static int run_fallback_merge_recursive(const struct am_state *state,
1587-
unsigned char *orig_tree,
1588-
unsigned char *our_tree,
1589-
unsigned char *their_tree)
1590-
{
1591-
struct child_process cp = CHILD_PROCESS_INIT;
1592-
int status;
1593-
1594-
cp.git_cmd = 1;
1595-
1596-
argv_array_pushf(&cp.env_array, "GITHEAD_%s=%.*s",
1597-
sha1_to_hex(their_tree), linelen(state->msg), state->msg);
1598-
if (state->quiet)
1599-
argv_array_push(&cp.env_array, "GIT_MERGE_VERBOSITY=0");
1600-
1601-
argv_array_push(&cp.args, "merge-recursive");
1602-
argv_array_push(&cp.args, sha1_to_hex(orig_tree));
1603-
argv_array_push(&cp.args, "--");
1604-
argv_array_push(&cp.args, sha1_to_hex(our_tree));
1605-
argv_array_push(&cp.args, sha1_to_hex(their_tree));
1606-
1607-
status = run_command(&cp) ? (-1) : 0;
1608-
discard_cache();
1609-
read_cache();
1610-
return status;
1611-
}
1612-
16131581
/**
16141582
* Attempt a threeway merge, using index_path as the temporary index.
16151583
*/
16161584
static int fall_back_threeway(const struct am_state *state, const char *index_path)
16171585
{
1618-
unsigned char orig_tree[GIT_SHA1_RAWSZ], their_tree[GIT_SHA1_RAWSZ],
1619-
our_tree[GIT_SHA1_RAWSZ];
1586+
struct object_id orig_tree, their_tree, our_tree;
1587+
const struct object_id *bases[1] = { &orig_tree };
1588+
struct merge_options o;
1589+
struct commit *result;
1590+
char *their_tree_name;
16201591

1621-
if (get_sha1("HEAD", our_tree) < 0)
1622-
hashcpy(our_tree, EMPTY_TREE_SHA1_BIN);
1592+
if (get_oid("HEAD", &our_tree) < 0)
1593+
hashcpy(our_tree.hash, EMPTY_TREE_SHA1_BIN);
16231594

16241595
if (build_fake_ancestor(state, index_path))
16251596
return error("could not build fake ancestor");
16261597

16271598
discard_cache();
16281599
read_cache_from(index_path);
16291600

1630-
if (write_index_as_tree(orig_tree, &the_index, index_path, 0, NULL))
1601+
if (write_index_as_tree(orig_tree.hash, &the_index, index_path, 0, NULL))
16311602
return error(_("Repository lacks necessary blobs to fall back on 3-way merge."));
16321603

16331604
say(state, stdout, _("Using index info to reconstruct a base tree..."));
@@ -1643,7 +1614,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
16431614
init_revisions(&rev_info, NULL);
16441615
rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;
16451616
diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1, rev_info.prefix);
1646-
add_pending_sha1(&rev_info, "HEAD", our_tree, 0);
1617+
add_pending_sha1(&rev_info, "HEAD", our_tree.hash, 0);
16471618
diff_setup_done(&rev_info.diffopt);
16481619
run_diff_index(&rev_info, 1);
16491620
}
@@ -1652,7 +1623,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
16521623
return error(_("Did you hand edit your patch?\n"
16531624
"It does not apply to blobs recorded in its index."));
16541625

1655-
if (write_index_as_tree(their_tree, &the_index, index_path, 0, NULL))
1626+
if (write_index_as_tree(their_tree.hash, &the_index, index_path, 0, NULL))
16561627
return error("could not write tree");
16571628

16581629
say(state, stdout, _("Falling back to patching base and 3-way merge..."));
@@ -1668,11 +1639,22 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
16681639
* changes.
16691640
*/
16701641

1671-
if (run_fallback_merge_recursive(state, orig_tree, our_tree, their_tree)) {
1642+
init_merge_options(&o);
1643+
1644+
o.branch1 = "HEAD";
1645+
their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
1646+
o.branch2 = their_tree_name;
1647+
1648+
if (state->quiet)
1649+
o.verbosity = 0;
1650+
1651+
if (merge_recursive_generic(&o, &our_tree, &their_tree, 1, bases, &result)) {
16721652
rerere(state->allow_rerere_autoupdate);
1653+
free(their_tree_name);
16731654
return error(_("Failed to merge in the changes."));
16741655
}
16751656

1657+
free(their_tree_name);
16761658
return 0;
16771659
}
16781660

builtin/checkout.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,10 +567,13 @@ static int merge_working_tree(const struct checkout_opts *opts,
567567
o.ancestor = old->name;
568568
o.branch1 = new->name;
569569
o.branch2 = "local";
570-
merge_trees(&o, new->commit->tree, work,
570+
ret = merge_trees(&o, new->commit->tree, work,
571571
old->commit->tree, &result);
572+
if (ret < 0)
573+
exit(128);
572574
ret = reset_tree(new->commit->tree, opts, 0,
573575
writeout_error);
576+
strbuf_release(&o.obuf);
574577
if (ret)
575578
return ret;
576579
}

builtin/ls-files.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ static void show_killed_files(struct dir_struct *dir)
118118
*/
119119
pos = cache_name_pos(ent->name, ent->len);
120120
if (0 <= pos)
121-
die("bug in show-killed-files");
121+
die("BUG: killed-file %.*s not found",
122+
ent->len, ent->name);
122123
pos = -pos - 1;
123124
while (pos < active_nr &&
124125
ce_stage(active_cache[pos]))

builtin/merge.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,8 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
673673
hold_locked_index(&lock, 1);
674674
clean = merge_recursive(&o, head,
675675
remoteheads->item, reversed, &result);
676+
if (clean < 0)
677+
exit(128);
676678
if (active_cache_changed &&
677679
write_locked_index(&the_index, &lock, COMMIT_LOCK))
678680
die (_("unable to write %s"), get_index_file());

builtin/update-index.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1146,7 +1146,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
11461146
report(_("Untracked cache enabled for '%s'"), get_git_work_tree());
11471147
break;
11481148
default:
1149-
die("Bug: bad untracked_cache value: %d", untracked_cache);
1149+
die("BUG: bad untracked_cache value: %d", untracked_cache);
11501150
}
11511151

11521152
if (active_cache_changed) {

grep.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -693,10 +693,10 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)
693693

694694
for (p = opt->header_list; p; p = p->next) {
695695
if (p->token != GREP_PATTERN_HEAD)
696-
die("bug: a non-header pattern in grep header list.");
696+
die("BUG: a non-header pattern in grep header list.");
697697
if (p->field < GREP_HEADER_FIELD_MIN ||
698698
GREP_HEADER_FIELD_MAX <= p->field)
699-
die("bug: unknown header field %d", p->field);
699+
die("BUG: unknown header field %d", p->field);
700700
compile_regexp(p, opt);
701701
}
702702

@@ -709,7 +709,7 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)
709709

710710
h = compile_pattern_atom(&pp);
711711
if (!h || pp != p->next)
712-
die("bug: malformed header expr");
712+
die("BUG: malformed header expr");
713713
if (!header_group[p->field]) {
714714
header_group[p->field] = h;
715715
continue;
@@ -1514,7 +1514,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
15141514
case GREP_BINARY_TEXT:
15151515
break;
15161516
default:
1517-
die("bug: unknown binary handling mode");
1517+
die("BUG: unknown binary handling mode");
15181518
}
15191519
}
15201520

imap-send.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ static int nfsnprintf(char *buf, int blen, const char *fmt, ...)
511511

512512
va_start(va, fmt);
513513
if (blen <= 0 || (unsigned)(ret = vsnprintf(buf, blen, fmt, va)) >= (unsigned)blen)
514-
die("Fatal: buffer too small. Please report a bug.");
514+
die("BUG: buffer too small. Please report a bug.");
515515
va_end(va);
516516
return ret;
517517
}

0 commit comments

Comments
 (0)