In this series, I show the new merge API I have developed in merge-ort, and show how it differs from that provided by merge-recursive. I do this in four steps, each corresponding to a patch. Changes since v2: * Extended comments in struct merge_result and in front of function definitions to make API usage clearer; in particular, noting how this merge backend differs in not using the index (and only updating it as part of merge_switch_to_result()). * Drop the other private field of struct merge_result, for now. * Rename merge_inmemory_* to merge_incore_* Elijah Newren (4): merge-ort: barebones API of new merge strategy with empty implementation merge-ort-wrappers: new convience wrappers to mimic the old merge API fast-rebase: demonstrate merge-ort's API via temporary/hidden command merge,rebase,revert: select ort or recursive by config or environment Makefile | 3 + builtin.h | 1 + builtin/fast-rebase.c | 210 ++++++++++++++++++++++++++++++++++++++++++ builtin/merge.c | 26 +++++- builtin/rebase.c | 9 +- builtin/revert.c | 2 + git.c | 1 + merge-ort-wrappers.c | 62 +++++++++++++ merge-ort-wrappers.h | 25 +++++ merge-ort.c | 52 +++++++++++ merge-ort.h | 58 ++++++++++++ sequencer.c | 71 +++++++++++--- 12 files changed, 505 insertions(+), 15 deletions(-) create mode 100644 builtin/fast-rebase.c create mode 100644 merge-ort-wrappers.c create mode 100644 merge-ort-wrappers.h create mode 100644 merge-ort.c create mode 100644 merge-ort.h base-commit: 69986e19ffcfb9af674ae5180689ab7bbf92ed28 Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-895%2Fnewren%2Fort-api-with-empty-implementation-v3 Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-895/newren/ort-api-with-empty-implementation-v3 Pull-Request: https://github.com/git/git/pull/895 Range-diff vs v2: 1: b9e73975ea ! 1: 3357ea415e merge-ort: barebones API of new merge strategy with empty implementation @@ merge-ort.c (new) + die("Not yet implemented"); +} + -+void merge_inmemory_nonrecursive(struct merge_options *opt, -+ struct tree *merge_base, -+ struct tree *side1, -+ struct tree *side2, -+ struct merge_result *result) ++void merge_incore_nonrecursive(struct merge_options *opt, ++ struct tree *merge_base, ++ struct tree *side1, ++ struct tree *side2, ++ struct merge_result *result) +{ + die("Not yet implemented"); +} + -+void merge_inmemory_recursive(struct merge_options *opt, -+ struct commit_list *merge_bases, -+ struct commit *side1, -+ struct commit *side2, -+ struct merge_result *result) ++void merge_incore_recursive(struct merge_options *opt, ++ struct commit_list *merge_bases, ++ struct commit *side1, ++ struct commit *side2, ++ struct merge_result *result) +{ + die("Not yet implemented"); +} @@ merge-ort.h (new) +struct tree; + +struct merge_result { -+ /* whether the merge is clean */ ++ /* Whether the merge is clean */ + int clean; + -+ /* Result of merge. If !clean, represents what would go in worktree */ ++ /* ++ * Result of merge. If !clean, represents what would go in worktree ++ * (thus possibly including files containing conflict markers). ++ */ + struct tree *tree; + + /* + * Additional metadata used by merge_switch_to_result() or future calls -+ * to merge_inmemory_*(). Not for external use. ++ * to merge_incore_*(). Includes data needed to update the index (if ++ * !clean) and to print "CONFLICT" messages. Not for external use. + */ + void *priv; -+ unsigned ate; +}; + -+/* rename-detecting three-way merge with recursive ancestor consolidation. */ -+void merge_inmemory_recursive(struct merge_options *opt, -+ struct commit_list *merge_bases, -+ struct commit *side1, -+ struct commit *side2, -+ struct merge_result *result); ++/* ++ * rename-detecting three-way merge with recursive ancestor consolidation. ++ * working tree and index are untouched. ++ */ ++void merge_incore_recursive(struct merge_options *opt, ++ struct commit_list *merge_bases, ++ struct commit *side1, ++ struct commit *side2, ++ struct merge_result *result); + -+/* rename-detecting three-way merge, no recursion. */ -+void merge_inmemory_nonrecursive(struct merge_options *opt, -+ struct tree *merge_base, -+ struct tree *side1, -+ struct tree *side2, -+ struct merge_result *result); ++/* ++ * rename-detecting three-way merge, no recursion. ++ * working tree and index are untouched. ++ */ ++void merge_incore_nonrecursive(struct merge_options *opt, ++ struct tree *merge_base, ++ struct tree *side1, ++ struct tree *side2, ++ struct merge_result *result); + -+/* Update the working tree and index from head to result after inmemory merge */ ++/* Update the working tree and index from head to result after incore merge */ +void merge_switch_to_result(struct merge_options *opt, + struct tree *head, + struct merge_result *result, 2: a9fff811a2 ! 2: d7f6a834ab merge-ort-wrappers: new convience wrappers to mimic the old merge API @@ merge-ort-wrappers.c (new) + } + + memset(&result, 0, sizeof(result)); -+ merge_inmemory_nonrecursive(opt, merge_base, head, merge, &result); ++ merge_incore_nonrecursive(opt, merge_base, head, merge, &result); + merge_switch_to_result(opt, head, &result, 1, 1); + + return result.clean; @@ merge-ort-wrappers.c (new) + return -1; + + memset(&tmp, 0, sizeof(tmp)); -+ merge_inmemory_recursive(opt, merge_bases, side1, side2, &tmp); ++ merge_incore_recursive(opt, merge_bases, side1, side2, &tmp); + merge_switch_to_result(opt, head, &tmp, 1, 1); + *result = NULL; + 3: f38d140c15 ! 3: 27ad756600 fast-rebase: demonstrate merge-ort's API via temporary/hidden command @@ builtin/fast-rebase.c (new) + merge_opt.branch2 = short_commit_name(commit); + merge_opt.ancestor = xstrfmt("parent of %s", merge_opt.branch2); + -+ merge_inmemory_nonrecursive(&merge_opt, -+ base_tree, -+ result.tree, -+ next_tree, -+ &result); ++ merge_incore_nonrecursive(&merge_opt, ++ base_tree, ++ result.tree, ++ next_tree, ++ &result); + + free((char*)merge_opt.ancestor); + merge_opt.ancestor = NULL; 4: 5f6c97b889 ! 4: 0479d59c33 merge,rebase,revert: select ort or recursive by config or environment @@ sequencer.c: static int do_recursive_merge(struct repository *r, - strbuf_release(&o.obuf); + if (opts->strategy && !strcmp(opts->strategy, "ort")) { + memset(&result, 0, sizeof(result)); -+ merge_inmemory_nonrecursive(&o, base_tree, head_tree, next_tree, ++ merge_incore_nonrecursive(&o, base_tree, head_tree, next_tree, + &result); + show_output = !is_rebase_i(opts) || !result.clean; + /* @@ sequencer.c: static int do_merge(struct repository *r, - ret = merge_recursive(&o, head_commit, merge_commit, reversed, &i); + if (opts->strategy && !strcmp(opts->strategy, "ort")) { + /* -+ * TODO: Should use merge_inmemory_recursive() and ++ * TODO: Should use merge_incore_recursive() and + * merge_switch_to_result(), skipping the call to + * merge_switch_to_result() when we don't actually need to + * update the index and working copy immediately. -- gitgitgadget