This is the second iteration of the long-awaited re-roll of the attempt to avoid spawning merge-recursive from the builtin am and use merge_recursive() directly instead. The *real* reason for the reroll is that I need a libified recursive merge to accelerate the interactive rebase by teaching the sequencer to do rebase -i's grunt work. In this endeavor, we need to be extra careful to retain backwards compatibility. The test script t6022-merge-rename.sh, for example, verifies that `git pull` exits with status 128 in case of a fatal error. To that end, we need to make sure that fatal errors are handled by existing (builtin) users via exit(128) (or die(), which calls exit(128) at the end). New users (such as a builtin helper doing rebase -i's grunt work) may want to print some helpful advice what happened and how to get out of this mess before erroring out. The changes relative to the second iteration of this patch series: - the was_tracked() function was adjusted as per Junio's suggestions - the "counter gender bias" patch was submitted separately, in $gmane/299009 (please note that the "am -3: use merge_recursive() directly again" patch is now slightly awkward as a consequence) - this patch series is on top of 'pu', to address the conflicts with the 'jh/clean-smudge-annex' and the 'bc/cocci' branches - please note that the interdiff does not show the full picture: I generated it relative to v2 rebased on top of pu (resolving many merge conflicts in the process that are hidden from the interdiff) This patch series touches rather important code. Now that I addressed concerns such as fixing translated bug reports, I would appreciate thorough reviews with a focus on the critical parts of the code, those that could result in regressions. Johannes Schindelin (16): Verify that `git pull --rebase` shows the helpful advice when failing Report bugs consistently Avoid translating bug messages merge-recursive: clarify code in was_tracked() Prepare the builtins for a libified merge_recursive() merge_recursive: abort properly upon errors merge-recursive: avoid returning a wholesale struct merge-recursive: allow write_tree_from_memory() to error out merge-recursive: handle return values indicating errors merge-recursive: switch to returning errors instead of dying am -3: use merge_recursive() directly again merge-recursive: flush output buffer before printing error messages merge-recursive: write the commit title in one go merge-recursive: offer an option to retain the output in 'obuf' Ensure that the output buffer is released after calling merge_trees() merge-recursive: flush output buffer even when erroring out builtin/am.c | 63 +++--- builtin/checkout.c | 5 +- builtin/ls-files.c | 3 +- builtin/merge.c | 2 + builtin/update-index.c | 2 +- grep.c | 8 +- imap-send.c | 4 +- merge-recursive.c | 508 +++++++++++++++++++++++++++++-------------------- merge-recursive.h | 2 +- sequencer.c | 5 + sha1_file.c | 4 +- t/t5520-pull.sh | 30 +++ trailer.c | 2 +- transport.c | 2 +- wt-status.c | 4 +- 15 files changed, 382 insertions(+), 262 deletions(-) Published-As: https://github.com/dscho/git/releases/tag/am-3-merge-recursive-direct-v3 Interdiff vs v2: diff --git a/builtin/am.c b/builtin/am.c index d626532..8dc4239 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -29,6 +29,7 @@ #include "prompt.h" #include "mailinfo.h" #include "apply.h" +#include "object.h" /** * Returns the length of the first line of msg. @@ -1627,15 +1628,14 @@ static int build_fake_ancestor(const struct am_state *state, const char *index_f */ static int fall_back_threeway(const struct am_state *state, const char *index_path) { - unsigned char orig_tree[GIT_SHA1_RAWSZ], her_tree[GIT_SHA1_RAWSZ], - our_tree[GIT_SHA1_RAWSZ]; - const unsigned char *bases[1] = {orig_tree}; + struct object_id orig_tree, her_tree, our_tree; + const struct object_id *bases[1] = { &orig_tree }; struct merge_options o; struct commit *result; char *her_tree_name; - if (get_sha1("HEAD", our_tree) < 0) - hashcpy(our_tree, EMPTY_TREE_SHA1_BIN); + if (get_oid("HEAD", &our_tree) < 0) + hashcpy(our_tree.hash, EMPTY_TREE_SHA1_BIN); if (build_fake_ancestor(state, index_path)) return error("could not build fake ancestor"); @@ -1643,7 +1643,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa discard_cache(); read_cache_from(index_path); - if (write_index_as_tree(orig_tree, &the_index, index_path, 0, NULL)) + if (write_index_as_tree(orig_tree.hash, &the_index, index_path, 0, NULL)) return error(_("Repository lacks necessary blobs to fall back on 3-way merge.")); say(state, stdout, _("Using index info to reconstruct a base tree...")); @@ -1659,7 +1659,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa init_revisions(&rev_info, NULL); rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS; diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1, rev_info.prefix); - add_pending_sha1(&rev_info, "HEAD", our_tree, 0); + add_pending_sha1(&rev_info, "HEAD", our_tree.hash, 0); diff_setup_done(&rev_info.diffopt); run_diff_index(&rev_info, 1); } @@ -1668,7 +1668,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa return error(_("Did you hand edit your patch?\n" "It does not apply to blobs recorded in its index.")); - if (write_index_as_tree(her_tree, &the_index, index_path, 0, NULL)) + if (write_index_as_tree(her_tree.hash, &the_index, index_path, 0, NULL)) return error("could not write tree"); say(state, stdout, _("Falling back to patching base and 3-way merge...")); @@ -1678,7 +1678,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa /* * This is not so wrong. Depending on which base we picked, orig_tree - * may be wildly different from ours, but her_tree has the same set of + * may be wildly different from ours, but his_tree has the same set of * wildly different changes in parts the patch did not touch, so * recursive ends up canceling them, saying that we reverted all those * changes. @@ -1693,7 +1693,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa if (state->quiet) o.verbosity = 0; - if (merge_recursive_generic(&o, our_tree, her_tree, 1, bases, &result)) { + if (merge_recursive_generic(&o, &our_tree, &her_tree, 1, bases, &result)) { rerere(state->allow_rerere_autoupdate); free(her_tree_name); return error(_("Failed to merge in the changes.")); diff --git a/merge-recursive.c b/merge-recursive.c index f80ad35..cb701ee 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -686,20 +686,19 @@ static int was_tracked(const char *path) { int pos = cache_name_pos(path, strlen(path)); - if (pos >= 0) - return pos < active_nr; + if (0 <= pos) + /* we have been tracking this path */ + return 1; + /* - * cache_name_pos() looks for stage == 0, even if we did not ask for - * it. Let's look for stage == 2 now. + * Look for an unmerged entry for the path, + * specifically stage #2, which would indicate + * that "our" side before the merge started + * had the path tracked (and resulted in a conflict). */ - for (pos = -1 - pos; pos < active_nr && - !strcmp(path, active_cache[pos]->name); pos++) - /* - * If stage #0, it is definitely tracked. - * If it has stage #2 then it was tracked - * before this merge started. All other - * cases the path was not tracked. - */ + for (pos = -1 - pos; + pos < active_nr && !strcmp(path, active_cache[pos]->name); + pos++) if (ce_stage(active_cache[pos]) == 2) return 1; return 0; -- 2.9.0.278.g1caae67 base-commit: 6addd022ce5331ee7dc41781ded714e5d5f01206 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html