From fa78782f67d17c5b139a2bbe3ceefe54c8c71dd3 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 22 Oct 2015 17:00:09 -0400 Subject: [PATCH 01/17] merge: rename `git_merge_tree_flags_t` -> `git_merge_flags_t` --- CHANGELOG.md | 8 ++++++++ include/git2/merge.h | 36 ++++++++++++++++++----------------- src/merge.c | 12 ++++++------ src/merge.h | 4 ++-- tests/cherrypick/workdir.c | 4 ++-- tests/merge/trees/commits.c | 2 +- tests/merge/trees/treediff.c | 2 +- tests/merge/workdir/renames.c | 6 +++--- tests/revert/workdir.c | 4 ++-- 9 files changed, 44 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d5a4166a..196ad705a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,14 @@ v0.23 + 1 ### Breaking API changes +* The `git_merge_tree_flag_t` is now `git_merge_flag_t`. Subsequently, + its members are no longer prefixed with `GIT_MERGE_TREE_FLAG` but are + now prefixed with `GIT_MERGE_FLAG`, and the `tree_flags` field of the + `git_merge_options` structure is now named `flags`. + +* The `git_merge_file_flags_t` enum is now `git_merge_file_flag_t` for + consistency with other enum type names. + * `git_cert` descendent types now have a proper `parent` member * It is the responsibility of the refdb backend to decide what to do diff --git a/include/git2/merge.h b/include/git2/merge.h index b7da63e0e..de224aeac 100644 --- a/include/git2/merge.h +++ b/include/git2/merge.h @@ -62,8 +62,8 @@ GIT_EXTERN(int) git_merge_file_init_input( unsigned int version); /** - * Flags for `git_merge_tree` options. A combination of these flags can be - * passed in via the `tree_flags` value in the `git_merge_options`. + * Flags for `git_merge` options. A combination of these flags can be + * passed in via the `flags` value in the `git_merge_options`. */ typedef enum { /** @@ -71,20 +71,20 @@ typedef enum { * side or the common ancestor and the "theirs" side. This will enable * the ability to merge between a modified and renamed file. */ - GIT_MERGE_TREE_FIND_RENAMES = (1 << 0), + GIT_MERGE_FIND_RENAMES = (1 << 0), + + /** + * Do not write the REUC extension on the generated index + */ + GIT_MERGE_SKIP_REUC = (1 << 2), /** * If a conflict occurs, exit immediately instead of attempting to * continue resolving conflicts. The merge operation will fail with * GIT_EMERGECONFLICT and no index will be returned. */ - GIT_MERGE_TREE_FAIL_ON_CONFLICT = (1 << 1), - - /** - * Do not write the REUC extension on the generated index - */ - GIT_MERGE_TREE_SKIP_REUC = (1 << 2), -} git_merge_tree_flag_t; + GIT_MERGE_FAIL_ON_CONFLICT = (1 << 1), +} git_merge_flag_t; /** * Merge file favor options for `git_merge_options` instruct the file-level @@ -152,7 +152,7 @@ typedef enum { /** Take extra time to find minimal diff */ GIT_MERGE_FILE_DIFF_MINIMAL = (1 << 7), -} git_merge_file_flags_t; +} git_merge_file_flag_t; /** * Options for merging a file @@ -181,8 +181,8 @@ typedef struct { /** The file to favor in region conflicts. */ git_merge_file_favor_t favor; - /** see `git_merge_file_flags_t` above */ - unsigned int flags; + /** see `git_merge_file_flag_t` above */ + git_merge_file_flag_t flags; } git_merge_file_options; #define GIT_MERGE_FILE_OPTIONS_VERSION 1 @@ -232,11 +232,13 @@ typedef struct { */ typedef struct { unsigned int version; - git_merge_tree_flag_t tree_flags; + + /** See `git_merge_flag_t` above */ + git_merge_flag_t flags; /** * Similarity to consider a file renamed (default 50). If - * `GIT_MERGE_TREE_FIND_RENAMES` is enabled, added files will be compared + * `GIT_MERGE_FIND_RENAMES` is enabled, added files will be compared * with deleted files to determine their similarity. Files that are * more similar than the rename threshold (percentage-wise) will be * treated as a rename. @@ -258,8 +260,8 @@ typedef struct { /** Flags for handling conflicting content. */ git_merge_file_favor_t file_favor; - /** see `git_merge_file_flags_t` above */ - unsigned int file_flags; + /** see `git_merge_file_flag_t` above */ + git_merge_file_flag_t file_flags; } git_merge_options; #define GIT_MERGE_OPTIONS_VERSION 1 diff --git a/src/merge.c b/src/merge.c index bad5f9552..d7b23e2c8 100644 --- a/src/merge.c +++ b/src/merge.c @@ -1296,7 +1296,7 @@ int git_merge_diff_list__find_renames( assert(diff_list && opts); - if ((opts->tree_flags & GIT_MERGE_TREE_FIND_RENAMES) == 0) + if ((opts->flags & GIT_MERGE_FIND_RENAMES) == 0) return 0; similarity_ours = git__calloc(diff_list->conflicts.length, @@ -1632,8 +1632,8 @@ static int merge_normalize_opts( git_merge_options init = GIT_MERGE_OPTIONS_INIT; memcpy(opts, &init, sizeof(init)); - opts->tree_flags = GIT_MERGE_TREE_FIND_RENAMES; - opts->rename_threshold = GIT_MERGE_TREE_RENAME_THRESHOLD; + opts->flags = GIT_MERGE_FIND_RENAMES; + opts->rename_threshold = GIT_MERGE_DEFAULT_RENAME_THRESHOLD; } if (!opts->target_limit) { @@ -1643,7 +1643,7 @@ static int merge_normalize_opts( limit = git_config__get_int_force(cfg, "diff.renamelimit", 0); opts->target_limit = (limit <= 0) ? - GIT_MERGE_TREE_TARGET_LIMIT : (unsigned int)limit; + GIT_MERGE_DEFAULT_TARGET_LIMIT : (unsigned int)limit; } /* assign the internal metric with whitespace flag as payload */ @@ -1864,7 +1864,7 @@ int git_merge__iterators( goto done; if (!resolved) { - if ((opts.tree_flags & GIT_MERGE_TREE_FAIL_ON_CONFLICT)) { + if ((opts.flags & GIT_MERGE_FAIL_ON_CONFLICT)) { giterr_set(GITERR_MERGE, "merge conflicts exist"); error = GIT_EMERGECONFLICT; goto done; @@ -1875,7 +1875,7 @@ int git_merge__iterators( } error = index_from_diff_list(out, diff_list, - (opts.tree_flags & GIT_MERGE_TREE_SKIP_REUC)); + (opts.flags & GIT_MERGE_SKIP_REUC)); done: if (!given_opts || !given_opts->metric) diff --git a/src/merge.h b/src/merge.h index 3caf617c6..bd839be49 100644 --- a/src/merge.h +++ b/src/merge.h @@ -19,8 +19,8 @@ #define GIT_MERGE_MODE_FILE "MERGE_MODE" #define GIT_MERGE_FILE_MODE 0666 -#define GIT_MERGE_TREE_RENAME_THRESHOLD 50 -#define GIT_MERGE_TREE_TARGET_LIMIT 1000 +#define GIT_MERGE_DEFAULT_RENAME_THRESHOLD 50 +#define GIT_MERGE_DEFAULT_TARGET_LIMIT 1000 /** Types of changes when files are merged from branch to branch. */ typedef enum { diff --git a/tests/cherrypick/workdir.c b/tests/cherrypick/workdir.c index 787f1f4d4..2b45f5a33 100644 --- a/tests/cherrypick/workdir.c +++ b/tests/cherrypick/workdir.c @@ -300,7 +300,7 @@ void test_cherrypick_workdir__rename(void) { 0100644, "28d9eb4208074ad1cc84e71ccc908b34573f05d2", 0, "file3.txt.renamed" }, }; - opts.merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES; + opts.merge_opts.flags |= GIT_MERGE_FIND_RENAMES; opts.merge_opts.rename_threshold = 50; git_oid_fromstr(&head_oid, "cfc4f0999a8367568e049af4f72e452d40828a15"); @@ -335,7 +335,7 @@ void test_cherrypick_workdir__both_renamed(void) { 0100644, "28d9eb4208074ad1cc84e71ccc908b34573f05d2", 2, "file3.txt.renamed_on_branch" }, }; - opts.merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES; + opts.merge_opts.flags |= GIT_MERGE_FIND_RENAMES; opts.merge_opts.rename_threshold = 50; git_oid_fromstr(&head_oid, "44cd2ed2052c9c68f9a439d208e9614dc2a55c70"); diff --git a/tests/merge/trees/commits.c b/tests/merge/trees/commits.c index 2e3c4578b..dd1e383ac 100644 --- a/tests/merge/trees/commits.c +++ b/tests/merge/trees/commits.c @@ -134,7 +134,7 @@ void test_merge_trees_commits__fail_on_conflict(void) git_index *index; git_merge_options opts = GIT_MERGE_OPTIONS_INIT; - opts.tree_flags |= GIT_MERGE_TREE_FAIL_ON_CONFLICT; + opts.flags |= GIT_MERGE_FAIL_ON_CONFLICT; cl_git_fail_with(GIT_EMERGECONFLICT, merge_trees_from_branches(&index, repo, "df_side1", "df_side2", &opts)); diff --git a/tests/merge/trees/treediff.c b/tests/merge/trees/treediff.c index f21d99b6d..3634568de 100644 --- a/tests/merge/trees/treediff.c +++ b/tests/merge/trees/treediff.c @@ -47,7 +47,7 @@ static void test_find_differences( git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT; git_merge_options opts = GIT_MERGE_OPTIONS_INIT; - opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES; + opts.flags |= GIT_MERGE_FIND_RENAMES; opts.target_limit = 1000; opts.rename_threshold = 50; diff --git a/tests/merge/workdir/renames.c b/tests/merge/workdir/renames.c index 83006a703..fabcda2a8 100644 --- a/tests/merge/workdir/renames.c +++ b/tests/merge/workdir/renames.c @@ -63,7 +63,7 @@ void test_merge_workdir_renames__renames(void) { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" }, }; - merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES; + merge_opts.flags |= GIT_MERGE_FIND_RENAMES; merge_opts.rename_threshold = 50; cl_git_pass(merge_branches(repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &merge_opts, NULL)); @@ -99,7 +99,7 @@ void test_merge_workdir_renames__ours(void) { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "7-both-renamed.txt" }, }; - merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES; + merge_opts.flags |= GIT_MERGE_FIND_RENAMES; merge_opts.rename_threshold = 50; checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS; @@ -147,7 +147,7 @@ void test_merge_workdir_renames__similar(void) { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" }, }; - merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES; + merge_opts.flags |= GIT_MERGE_FIND_RENAMES; merge_opts.rename_threshold = 50; cl_git_pass(merge_branches(repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &merge_opts, NULL)); diff --git a/tests/revert/workdir.c b/tests/revert/workdir.c index 9f83bd842..802819c75 100644 --- a/tests/revert/workdir.c +++ b/tests/revert/workdir.c @@ -410,7 +410,7 @@ void test_revert_workdir__rename_1_of_2(void) { 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 2, "file6.txt" }, }; - opts.merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES; + opts.merge_opts.flags |= GIT_MERGE_FIND_RENAMES; opts.merge_opts.rename_threshold = 50; git_oid_fromstr(&head_oid, "cef56612d71a6af8d8015691e4865f7fece905b5"); @@ -444,7 +444,7 @@ void test_revert_workdir__rename(void) { "file4.txt", "file5.txt", "" }, }; - opts.merge_opts.tree_flags |= GIT_MERGE_TREE_FIND_RENAMES; + opts.merge_opts.flags |= GIT_MERGE_FIND_RENAMES; opts.merge_opts.rename_threshold = 50; git_oid_fromstr(&head_oid, "55568c8de5322ff9a95d72747a239cdb64a19965"); From 86c8d02c071d3713e1c9f0b95d9f4599108d2c29 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 22 Oct 2015 20:20:07 -0400 Subject: [PATCH 02/17] merge: add simple recursive test Add a simple recursive test - where multiple ancestors exist and creating a virtual merge base from them would prevent a conflict. --- include/git2/merge.h | 18 ++- tests/merge/merge_helpers.c | 3 +- tests/merge/trees/recursive.c | 110 ++++++++++++++++++ tests/resources/merge-recursive/.gitted/HEAD | Bin 0 -> 26 bytes .../resources/merge-recursive/.gitted/config | Bin 0 -> 137 bytes tests/resources/merge-recursive/.gitted/index | Bin 0 -> 632 bytes .../merge-recursive/.gitted/info/refs | Bin 0 -> 59 bytes .../00/6b298c5702b04c00370d0414959765b82fd722 | Bin 0 -> 207 bytes .../01/6eef4a6fefd36bdcaa93ad773449ddc5c73cbb | Bin 0 -> 208 bytes .../05/c6a04ac101ab1a9836a95d5ec8d16b6f6304fd | Bin 0 -> 208 bytes .../07/10c3c796e0704361472ecb904413fca0107a25 | Bin 0 -> 208 bytes .../07/2d89dcf3a7671ac34a8e875bb72fb39bcf14d7 | Bin 0 -> 208 bytes .../0b/b7ed583d7e9ad507e8b902594f5c9126ea456b | Bin 0 -> 161 bytes .../12/4d4fe29d3433fdaa2f0f455d226f2c79d89cf3 | Bin 0 -> 208 bytes .../16/895aa5e13f8907d4adab81285557d938fad342 | Bin 0 -> 634 bytes .../3a/3f5a6ec1c968d1d2d5d20dee0d161a4351f279 | Bin 0 -> 162 bytes .../3b/919b6e8a575b4779c8243ebea3e3beb436e88f | Bin 0 -> 208 bytes .../3f/d41804a7906db846af5e868444782e546af46a | Bin 0 -> 206 bytes .../42/1b392106e079df6d412babd5636697938269ec | Bin 0 -> 163 bytes .../42/cdad903aef3e7b614675e6584a8be417941911 | Bin 0 -> 208 bytes .../43/2faca0c62dc556ad71a22f23e541a46a8b0f6f | Bin 0 -> 207 bytes .../43/5424798e5e1b21dd4588d1c291ba4eb179a838 | Bin 0 -> 208 bytes .../4b/7c5650008b2e747fe1809eeb5a1dde0e80850a | Bin 0 -> 615 bytes .../4c/49317a0912ca559d2048bc329994eb7d10474f | Bin 0 -> 183 bytes .../4e/21d2d63357bde5027d1625f5ec6b430cdeb143 | Bin 0 -> 662 bytes .../53/9bd011c4822c560c1d17cab095006b7a10f707 | Bin 0 -> 163 bytes .../65/bea8448ca5b3104628ffbca553c54bde54b0fc | Bin 0 -> 160 bytes .../66/6ffdfcf1eaa5641fa31064bf2607327e843c09 | Bin 0 -> 664 bytes .../68/af1fc7407fd9addf1701a87eb1c95c7494c598 | Bin 0 -> 443 bytes .../68/f6182f4c85d39e1309d97c7e456156dc9c0096 | Bin 0 -> 755 bytes .../71/3e438567b28543235faf265c4c5b02b437c7fd | Bin 0 -> 207 bytes .../72/3181f1bfd30e47a6d1d36a4d874e31e7a0a1a4 | Bin 0 -> 163 bytes .../74/4df1bdf0f7bca20deb23e5a5eb8255fc237901 | Bin 0 -> 207 bytes .../7c/7bf85e978f1d18c0566f702d2cb7766b9c8d4f | Bin 0 -> 198 bytes .../7c/7e08f9559d9e1551b91e1cf68f1d0066109add | Bin 0 -> 443 bytes .../88/eb3f98849f4b8d0555395f514800900a01dc8f | Bin 0 -> 209 bytes .../8f/35f30bfe09513f96cf8aa4df0834ae34e93bae | Bin 0 -> 161 bytes .../94/d2c01087f48213bd157222d54edfefd77c9bba | Bin 0 -> 621 bytes .../95/78b04e2087976e382622322ba476aa40398dc7 | Bin 0 -> 620 bytes .../97/3b70322e758da87e1ce21d2195d86c5e4e9647 | Bin 0 -> 207 bytes .../9c/3f1c70db28c00ce74b22ba3edafe16d9cf03d4 | Bin 0 -> 208 bytes .../a0/65d3022e99a1943177c10a53cce38bc2127042 | Bin 0 -> 162 bytes .../a2/fa36ffc4a565a223e225d15b18774f87d0c4f0 | Bin 0 -> 167 bytes .../a3/4e5a16feabbd0335a633aadb8217c9f3dba58d | Bin 0 -> 164 bytes .../a7/b066537e6be7109abfe4ff97b675d4e077da20 | Bin 0 -> 621 bytes .../a8/2a121ea36b115548d6dad2cd86ec27f06f7b30 | Bin 0 -> 208 bytes .../b2/a81ead9e722af0099fccfb478cea88eea749a2 | Bin 0 -> 664 bytes .../b4/cefb3c75770e57bb8bb44e4a50d9578009e847 | Bin 0 -> 639 bytes .../c4/e6cca3ec6ae0148ed231f97257df8c311e015f | Bin 0 -> 268 bytes .../cb/49ad76147f5f9439cbd6133708b76142660660 | Bin 0 -> 641 bytes .../d0/dd5d9083bda65ec99aa8b9b64a5a278771b70a | Bin 0 -> 620 bytes .../de/a7215f259b2cced87d1bda6c72f8b4ce37a2ff | Bin 0 -> 357 bytes .../e2/93bfdddb81a853bbb16b8b58e68626f30841a4 | Bin 0 -> 207 bytes .../e2/c84bb33992a455b1a7a5019f0e38d883d3f475 | Bin 0 -> 208 bytes .../f1/3e1bc6ba935fce2efffa5be4c4832404034ef1 | Bin 0 -> 206 bytes .../f3/5f159ff5d44dfd9f52d63dd5b659f0521ff569 | Bin 0 -> 669 bytes .../f5/1658077d85f2264fa179b4d0848268cb3475c3 | Bin 0 -> 355 bytes .../fa/567f568ed72157c0c617438d077695b99d9aac | Bin 0 -> 662 bytes .../fd/8b5fe88cda995e70a22ed98701e65b843e05ec | Bin 0 -> 165 bytes .../fe/f01f3104c8047d05e8572e521c454f8fd4b8db | Bin 0 -> 207 bytes .../ff/b36e513f5fdf8a6ba850a20142676a2ac4807d | Bin 0 -> 355 bytes .../.gitted/refs/heads/branchA-1 | Bin 0 -> 41 bytes .../.gitted/refs/heads/branchA-2 | Bin 0 -> 41 bytes .../.gitted/refs/heads/branchB-1 | Bin 0 -> 41 bytes .../.gitted/refs/heads/branchB-2 | Bin 0 -> 41 bytes tests/resources/merge-recursive/asparagus.txt | Bin 0 -> 587 bytes tests/resources/merge-recursive/beef.txt | Bin 0 -> 1372 bytes tests/resources/merge-recursive/bouilli.txt | Bin 0 -> 1092 bytes tests/resources/merge-recursive/gravy.txt | Bin 0 -> 390 bytes tests/resources/merge-recursive/oyster.txt | Bin 0 -> 774 bytes tests/resources/merge-recursive/veal.txt | Bin 0 -> 1095 bytes 71 files changed, 125 insertions(+), 6 deletions(-) create mode 100644 tests/merge/trees/recursive.c create mode 100644 tests/resources/merge-recursive/.gitted/HEAD create mode 100644 tests/resources/merge-recursive/.gitted/config create mode 100644 tests/resources/merge-recursive/.gitted/index create mode 100644 tests/resources/merge-recursive/.gitted/info/refs create mode 100644 tests/resources/merge-recursive/.gitted/objects/00/6b298c5702b04c00370d0414959765b82fd722 create mode 100644 tests/resources/merge-recursive/.gitted/objects/01/6eef4a6fefd36bdcaa93ad773449ddc5c73cbb create mode 100644 tests/resources/merge-recursive/.gitted/objects/05/c6a04ac101ab1a9836a95d5ec8d16b6f6304fd create mode 100644 tests/resources/merge-recursive/.gitted/objects/07/10c3c796e0704361472ecb904413fca0107a25 create mode 100644 tests/resources/merge-recursive/.gitted/objects/07/2d89dcf3a7671ac34a8e875bb72fb39bcf14d7 create mode 100644 tests/resources/merge-recursive/.gitted/objects/0b/b7ed583d7e9ad507e8b902594f5c9126ea456b create mode 100644 tests/resources/merge-recursive/.gitted/objects/12/4d4fe29d3433fdaa2f0f455d226f2c79d89cf3 create mode 100644 tests/resources/merge-recursive/.gitted/objects/16/895aa5e13f8907d4adab81285557d938fad342 create mode 100644 tests/resources/merge-recursive/.gitted/objects/3a/3f5a6ec1c968d1d2d5d20dee0d161a4351f279 create mode 100644 tests/resources/merge-recursive/.gitted/objects/3b/919b6e8a575b4779c8243ebea3e3beb436e88f create mode 100644 tests/resources/merge-recursive/.gitted/objects/3f/d41804a7906db846af5e868444782e546af46a create mode 100644 tests/resources/merge-recursive/.gitted/objects/42/1b392106e079df6d412babd5636697938269ec create mode 100644 tests/resources/merge-recursive/.gitted/objects/42/cdad903aef3e7b614675e6584a8be417941911 create mode 100644 tests/resources/merge-recursive/.gitted/objects/43/2faca0c62dc556ad71a22f23e541a46a8b0f6f create mode 100644 tests/resources/merge-recursive/.gitted/objects/43/5424798e5e1b21dd4588d1c291ba4eb179a838 create mode 100644 tests/resources/merge-recursive/.gitted/objects/4b/7c5650008b2e747fe1809eeb5a1dde0e80850a create mode 100644 tests/resources/merge-recursive/.gitted/objects/4c/49317a0912ca559d2048bc329994eb7d10474f create mode 100644 tests/resources/merge-recursive/.gitted/objects/4e/21d2d63357bde5027d1625f5ec6b430cdeb143 create mode 100644 tests/resources/merge-recursive/.gitted/objects/53/9bd011c4822c560c1d17cab095006b7a10f707 create mode 100644 tests/resources/merge-recursive/.gitted/objects/65/bea8448ca5b3104628ffbca553c54bde54b0fc create mode 100644 tests/resources/merge-recursive/.gitted/objects/66/6ffdfcf1eaa5641fa31064bf2607327e843c09 create mode 100644 tests/resources/merge-recursive/.gitted/objects/68/af1fc7407fd9addf1701a87eb1c95c7494c598 create mode 100644 tests/resources/merge-recursive/.gitted/objects/68/f6182f4c85d39e1309d97c7e456156dc9c0096 create mode 100644 tests/resources/merge-recursive/.gitted/objects/71/3e438567b28543235faf265c4c5b02b437c7fd create mode 100644 tests/resources/merge-recursive/.gitted/objects/72/3181f1bfd30e47a6d1d36a4d874e31e7a0a1a4 create mode 100644 tests/resources/merge-recursive/.gitted/objects/74/4df1bdf0f7bca20deb23e5a5eb8255fc237901 create mode 100644 tests/resources/merge-recursive/.gitted/objects/7c/7bf85e978f1d18c0566f702d2cb7766b9c8d4f create mode 100644 tests/resources/merge-recursive/.gitted/objects/7c/7e08f9559d9e1551b91e1cf68f1d0066109add create mode 100644 tests/resources/merge-recursive/.gitted/objects/88/eb3f98849f4b8d0555395f514800900a01dc8f create mode 100644 tests/resources/merge-recursive/.gitted/objects/8f/35f30bfe09513f96cf8aa4df0834ae34e93bae create mode 100644 tests/resources/merge-recursive/.gitted/objects/94/d2c01087f48213bd157222d54edfefd77c9bba create mode 100644 tests/resources/merge-recursive/.gitted/objects/95/78b04e2087976e382622322ba476aa40398dc7 create mode 100644 tests/resources/merge-recursive/.gitted/objects/97/3b70322e758da87e1ce21d2195d86c5e4e9647 create mode 100644 tests/resources/merge-recursive/.gitted/objects/9c/3f1c70db28c00ce74b22ba3edafe16d9cf03d4 create mode 100644 tests/resources/merge-recursive/.gitted/objects/a0/65d3022e99a1943177c10a53cce38bc2127042 create mode 100644 tests/resources/merge-recursive/.gitted/objects/a2/fa36ffc4a565a223e225d15b18774f87d0c4f0 create mode 100644 tests/resources/merge-recursive/.gitted/objects/a3/4e5a16feabbd0335a633aadb8217c9f3dba58d create mode 100644 tests/resources/merge-recursive/.gitted/objects/a7/b066537e6be7109abfe4ff97b675d4e077da20 create mode 100644 tests/resources/merge-recursive/.gitted/objects/a8/2a121ea36b115548d6dad2cd86ec27f06f7b30 create mode 100644 tests/resources/merge-recursive/.gitted/objects/b2/a81ead9e722af0099fccfb478cea88eea749a2 create mode 100644 tests/resources/merge-recursive/.gitted/objects/b4/cefb3c75770e57bb8bb44e4a50d9578009e847 create mode 100644 tests/resources/merge-recursive/.gitted/objects/c4/e6cca3ec6ae0148ed231f97257df8c311e015f create mode 100644 tests/resources/merge-recursive/.gitted/objects/cb/49ad76147f5f9439cbd6133708b76142660660 create mode 100644 tests/resources/merge-recursive/.gitted/objects/d0/dd5d9083bda65ec99aa8b9b64a5a278771b70a create mode 100644 tests/resources/merge-recursive/.gitted/objects/de/a7215f259b2cced87d1bda6c72f8b4ce37a2ff create mode 100644 tests/resources/merge-recursive/.gitted/objects/e2/93bfdddb81a853bbb16b8b58e68626f30841a4 create mode 100644 tests/resources/merge-recursive/.gitted/objects/e2/c84bb33992a455b1a7a5019f0e38d883d3f475 create mode 100644 tests/resources/merge-recursive/.gitted/objects/f1/3e1bc6ba935fce2efffa5be4c4832404034ef1 create mode 100644 tests/resources/merge-recursive/.gitted/objects/f3/5f159ff5d44dfd9f52d63dd5b659f0521ff569 create mode 100644 tests/resources/merge-recursive/.gitted/objects/f5/1658077d85f2264fa179b4d0848268cb3475c3 create mode 100644 tests/resources/merge-recursive/.gitted/objects/fa/567f568ed72157c0c617438d077695b99d9aac create mode 100644 tests/resources/merge-recursive/.gitted/objects/fd/8b5fe88cda995e70a22ed98701e65b843e05ec create mode 100644 tests/resources/merge-recursive/.gitted/objects/fe/f01f3104c8047d05e8572e521c454f8fd4b8db create mode 100644 tests/resources/merge-recursive/.gitted/objects/ff/b36e513f5fdf8a6ba850a20142676a2ac4807d create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchA-1 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchA-2 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchB-1 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchB-2 create mode 100644 tests/resources/merge-recursive/asparagus.txt create mode 100644 tests/resources/merge-recursive/beef.txt create mode 100644 tests/resources/merge-recursive/bouilli.txt create mode 100644 tests/resources/merge-recursive/gravy.txt create mode 100644 tests/resources/merge-recursive/oyster.txt create mode 100644 tests/resources/merge-recursive/veal.txt diff --git a/include/git2/merge.h b/include/git2/merge.h index de224aeac..a272e8be4 100644 --- a/include/git2/merge.h +++ b/include/git2/merge.h @@ -73,17 +73,25 @@ typedef enum { */ GIT_MERGE_FIND_RENAMES = (1 << 0), - /** - * Do not write the REUC extension on the generated index - */ - GIT_MERGE_SKIP_REUC = (1 << 2), - /** * If a conflict occurs, exit immediately instead of attempting to * continue resolving conflicts. The merge operation will fail with * GIT_EMERGECONFLICT and no index will be returned. */ GIT_MERGE_FAIL_ON_CONFLICT = (1 << 1), + + /** + * Do not write the REUC extension on the generated index + */ + GIT_MERGE_SKIP_REUC = (1 << 2), + + /** + * If the commits being merged have multiple merge bases, do not build + * a recursive merge base (by merging the multiple merge bases), + * instead simply use the first base. This flag provides a similar + * merge base to `git-merge-resolve`. + */ + GIT_MERGE_NO_RECURSIVE = (1 << 3), } git_merge_flag_t; /** diff --git a/tests/merge/merge_helpers.c b/tests/merge/merge_helpers.c index 986a365db..4b1b7d262 100644 --- a/tests/merge/merge_helpers.c +++ b/tests/merge/merge_helpers.c @@ -4,6 +4,7 @@ #include "tree.h" #include "merge_helpers.h" #include "merge.h" +#include "index.h" #include "git2/merge.h" #include "git2/sys/index.h" #include "git2/annotated_commit.h" @@ -239,7 +240,7 @@ int merge_test_index(git_index *index, const struct merge_index_entry expected[] const git_index_entry *index_entry; /* - dump_index_entries(&index->entries); + merge__dump_index_entries(&index->entries); */ if (git_index_entrycount(index) != expected_len) diff --git a/tests/merge/trees/recursive.c b/tests/merge/trees/recursive.c new file mode 100644 index 000000000..1d3586162 --- /dev/null +++ b/tests/merge/trees/recursive.c @@ -0,0 +1,110 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "merge.h" +#include "../merge_helpers.h" + +static git_repository *repo; + +#define TEST_REPO_PATH "merge-recursive" + +void test_merge_trees_recursive__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); +} + +void test_merge_trees_recursive__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_merge_trees_recursive__one(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "dea7215f259b2cced87d1bda6c72f8b4ce37a2ff", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" }, + }; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchA-1", "branchA-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 6)); + + git_index_free(index); +} + +void test_merge_trees_recursive__one_norecursive(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "dea7215f259b2cced87d1bda6c72f8b4ce37a2ff", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" }, + }; + + opts.flags |= GIT_MERGE_NO_RECURSIVE; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchA-1", "branchA-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 6)); + + git_index_free(index); +} + +void test_merge_trees_recursive__two(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "666ffdfcf1eaa5641fa31064bf2607327e843c09", 0, "veal.txt" }, + }; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchB-1", "branchB-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 6)); + + git_index_free(index); +} + +void test_merge_trees_recursive__two_norecursive(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + opts.flags |= GIT_MERGE_NO_RECURSIVE; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "cb49ad76147f5f9439cbd6133708b76142660660", 1, "veal.txt" }, + { 0100644, "b2a81ead9e722af0099fccfb478cea88eea749a2", 2, "veal.txt" }, + { 0100644, "4e21d2d63357bde5027d1625f5ec6b430cdeb143", 3, "veal.txt" }, + }; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchB-1", "branchB-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 8)); + + git_index_free(index); +} + diff --git a/tests/resources/merge-recursive/.gitted/HEAD b/tests/resources/merge-recursive/.gitted/HEAD new file mode 100644 index 0000000000000000000000000000000000000000..77e35742d01dcf26e0594d689548d3ae37549fca GIT binary patch literal 26 hcmXR)O|w!cN=+-)&qz&7Db`OaO3X{naMCs80swu12*UsX literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/config b/tests/resources/merge-recursive/.gitted/config new file mode 100644 index 0000000000000000000000000000000000000000..6c9406b7d9320db083eca69b3f8bee9a6c7b50d4 GIT binary patch literal 137 zcmYk#%?-jZ3KJaaM(b)IThRcka) zn6vinzTI-FENHqTG;JZL7ug4u#6zM7i5Th{J5BgE#z&9!LjG%xu(tTZ>RkRd-|~Df A#{d8T literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/index b/tests/resources/merge-recursive/.gitted/index new file mode 100644 index 0000000000000000000000000000000000000000..1e47851a50c3550bd04e7e1a481346d39b101267 GIT binary patch literal 632 zcmZ?q402{*U|<4bjxf!rYe1R-Ml%A%8G{Pq7#JFtFfcHF1xkqkg}nc7&I`1Uzu%R; zB481tQ+k%xk%n3Z-o)a9#G=IX(qg@miV~19Ky$+7kZFi{d2>8O z=gpcr*Tk?pa~P&Ea3rOsra_FtVa_~Mb68xwYr+B;y7fxxA2!T;9VL5@uc4KTfjcR` zG&3hB6YeUU?wXHk9%I{)XJ;0_$$B8tcggT)QTY8HLpjEH2F~=N#Ij1TX*k@q0M#63 zwv6@i#~tc#uDvhLxT0?3$(WKUM`ti_ literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/info/refs b/tests/resources/merge-recursive/.gitted/info/refs new file mode 100644 index 0000000000000000000000000000000000000000..96482e6cb196feb3c5c51b901f02ede9aa30f38f GIT binary patch literal 59 zcmV~$xe>r13m_Qw&% literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/00/6b298c5702b04c00370d0414959765b82fd722 b/tests/resources/merge-recursive/.gitted/objects/00/6b298c5702b04c00370d0414959765b82fd722 new file mode 100644 index 0000000000000000000000000000000000000000..d3fb85fcabae19adf089fc080e9075f72b41fe6f GIT binary patch literal 207 zcmV;=05Jb}0V^p=O;s>5GG{O}FfcPQQAjKi J1OUKwTBN=BVB7!z literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/01/6eef4a6fefd36bdcaa93ad773449ddc5c73cbb b/tests/resources/merge-recursive/.gitted/objects/01/6eef4a6fefd36bdcaa93ad773449ddc5c73cbb new file mode 100644 index 0000000000000000000000000000000000000000..90085847c54162c46a745b3561e2efa9d09a3cb6 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKNcK?DVcI~22@p9YGMvp&D4qwehTf=^DNYqjI@`Ot#YvJ KJq`f;l3aIJ+G3Re literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/05/c6a04ac101ab1a9836a95d5ec8d16b6f6304fd b/tests/resources/merge-recursive/.gitted/objects/05/c6a04ac101ab1a9836a95d5ec8d16b6f6304fd new file mode 100644 index 0000000000000000000000000000000000000000..c6a3a3b8def22521b0be327923d3bb028613e4e4 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKdv{d K)&Ky^dR($J31Z&> literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/07/10c3c796e0704361472ecb904413fca0107a25 b/tests/resources/merge-recursive/.gitted/objects/07/10c3c796e0704361472ecb904413fca0107a25 new file mode 100644 index 0000000000000000000000000000000000000000..9f48594b5e9dd2d86998975017e8b841120dcc46 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKNcK?DVcI~22@p9YGMvp&6G05AV|0V^p=O;s>5GG{O}FfcPQQAjK9+jN$ zO%DLOR++W2fmr~9up}2^BE;EY8b=2(r$nAcM=`1=R(>=s*0GHgVqbY79#}-sM+Sn) z4Pd}HV6h6fwv?(b>4i1v>r(Ps9{R{V{irj4i=R7C$tP_AyoYJ_M(;bvsGjz-jsL_b PT>E>xZL4|%(vDH^g)m9w literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/12/4d4fe29d3433fdaa2f0f455d226f2c79d89cf3 b/tests/resources/merge-recursive/.gitted/objects/12/4d4fe29d3433fdaa2f0f455d226f2c79d89cf3 new file mode 100644 index 0000000000000000000000000000000000000000..f0ea020fb001f27b4f65ca32006f9280676ad0e1 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKNrj^%~6Yxstxo^mZp7Iv;f>@s$ z+FYKFlXO5E@vh^#(X$OS+2u^0K`m1oohQj`d*}B$HN}$TOftI#7fkFrD_{mjyHe#q z>rEBrEy?79F8|3Eod1VaRu#?o7)DNK%64Xo7zYmhV+BHoj=D4sL;XJ{w!-8FNZgG8 z$@i3;FlZ=_rP29n%ot-&9j*gralZ}+Ku!r{+j@RqZ4~%uz;y7C2)=2j0Ao~FH4&V4 z_H#8#M|m8DT1H5LHr7NWCkwTCa$>M3mjp68Yx|xgE==7N5l>I6P2zb!YfkC-C9$l? zl-iwohB%hSNOnnMIN%kj-p5I;joO6bG}OhAT_`S$gf`Wwf)lT^lNF;eVr%WeHFY=< zN=ED$IDEhQn(T%HWUi^{2Gx0@%V6}Q+6dJYP*@ag;4Y&XvN40l&8KS3TX6shywzT) zE8WZi9L=V|bS3p3`Kez>8|qK=7!z{qCW}7M9t$mYuYI!A$KUWdxs}0qu{nxyp`pPg zL6UY>?bm9+Gc+Ygqh6wMum-+Nyug{71`WLZ)$f9tpym45Hf=EO?sYYEqGVeAl^G76 z=!gDaY=0&01cSR$HA_(ot-gxerXqN+roGj_zMDjI UDBY|+At``qBPE~AAEX6|z4XmEIRF3v literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/3a/3f5a6ec1c968d1d2d5d20dee0d161a4351f279 b/tests/resources/merge-recursive/.gitted/objects/3a/3f5a6ec1c968d1d2d5d20dee0d161a4351f279 new file mode 100644 index 0000000000000000000000000000000000000000..f39a1271fc3ea3223935f59995dfd19bc503e815 GIT binary patch literal 162 zcmV;T0A2rh0i{pd4FVw$^qVSZK(pY&LSl?R*MSZ2SaK%bVGy-_(b$21^TCeflPfAKm%vzCMmXyf ziL8x2xr{}GN1tnxQ+|b(<$12ly{_`WL;au=e~lm8rMeuYLNvyJvrcXS0mM+p*v@~} Qh$)ZDPYze{1{JSPI$SSJ%K!iX literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/3b/919b6e8a575b4779c8243ebea3e3beb436e88f b/tests/resources/merge-recursive/.gitted/objects/3b/919b6e8a575b4779c8243ebea3e3beb436e88f new file mode 100644 index 0000000000000000000000000000000000000000..c85731d6bddd857db09da0d014be4038dfe35be3 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKTj;SFV484ZsWk8T$lY^VAlR8|EF&&z4D;^ KmI44rFkeE4X<!?*!?#? z_;cH~%K&1!8C?~Sa}e~BEm}!d;zB_p7uLKK8&ar&(AQ#KrRzRmsl=5qRmI4bY7Dt9 zBED2y$cvKKNJ;c}PePR?Xtp_qNi42#aadGw;;ndMTisnW@;27i;jz3+FYvs!?b>!Y z=}bS>S-*-OcbnUG57v8TwhjXv(Ic9f&T~Wmi7`*wUlhJ+aQN$m16=meAa&XE`fzmS I18dK3v%N-Vt^fc4 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/42/1b392106e079df6d412babd5636697938269ec b/tests/resources/merge-recursive/.gitted/objects/42/1b392106e079df6d412babd5636697938269ec new file mode 100644 index 0000000000000000000000000000000000000000..3a8324c1b1bab7a033edfd165fdba6cfb84bfb39 GIT binary patch literal 163 zcmV;U09^lg0i};o3c@fDME%Ywasg!%H^~-6{OJw6K$G32f^DQmy}nhvfqye^V3;X& znl87akNM3?>1p_K6V|Tqxm~H#(K^HskfMur3kYCVx{ht~ RXN~E3z5JBnYTiBXPm^J?P0RoQ literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/42/cdad903aef3e7b614675e6584a8be417941911 b/tests/resources/merge-recursive/.gitted/objects/42/cdad903aef3e7b614675e6584a8be417941911 new file mode 100644 index 0000000000000000000000000000000000000000..99b5e6d2c8f1feb318ae3effc47c16d1f66918ce GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjK5GG{O}FfcPQQAjKVORhF literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/43/5424798e5e1b21dd4588d1c291ba4eb179a838 b/tests/resources/merge-recursive/.gitted/objects/43/5424798e5e1b21dd4588d1c291ba4eb179a838 new file mode 100644 index 0000000000000000000000000000000000000000..58ab2391707739b6ce0fe4b0c7c9f33400b20ee7 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKX{GYz9^vZ+s KTM7VwgIs}8-eWre literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/4b/7c5650008b2e747fe1809eeb5a1dde0e80850a b/tests/resources/merge-recursive/.gitted/objects/4b/7c5650008b2e747fe1809eeb5a1dde0e80850a new file mode 100644 index 0000000000000000000000000000000000000000..016398531ebf1408a8bcff0d4a2974da890c3874 GIT binary patch literal 615 zcmV-t0+{`H0Zo(5j@vK{gnRZ=@BzF*+grQ0qCgv9fi2Ko^eo%7Em#pD%8Onl|EL(9jB2A{ZB9%z(Q zDp~`0c9}Zy!LU4TnP`R_a2j)I$sDeGffp+4!3AhA43rTJ zWFou6(+HCX3{H(@VP2uCCwfgfFK{R0k?|pZ5Tn=5VX^q(kEe+?4x#DTDaRH8q9={` zWw}8EEsSAvd9G9{tKCHm=?0zGU48B3V`RP-+bXJ(v;jb>SGxw2^@RZPNXkU^> z6Gz{R_OmI(24P;kl#I&RsBV>}TARmX?7g^Q>{EiS6pz508ZlJQ-6Vs%~M z*Ma+pM6e6PV2lD}J@`D|vUsK*C(2mlkIO%jE^wf>mCH&U9&2BqrrV&ut0!AnSYv1%RxAJj literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/4e/21d2d63357bde5027d1625f5ec6b430cdeb143 b/tests/resources/merge-recursive/.gitted/objects/4e/21d2d63357bde5027d1625f5ec6b430cdeb143 new file mode 100644 index 0000000000000000000000000000000000000000..34f183dd17d3105fc11c39606b2e10b2924c3024 GIT binary patch literal 662 zcmV;H0%`qt0Zo)abJH*og*oe2EccL^a^R9v4(ZSthJ-eyXW3rc8q1Q=${6$Oc`GNt zt&yeGd*6F%kLet8AD4_Hxcb!nhHpBD6nuz3N;Wqb93@*xZf*3t(n}#HgOm!a-PeYSU;(0x2 zPHFojah{MVRVy_Nb1XX}*(Jrejn_$KKUNB0#WY1^TE~!Gm|f@y+{>vMD_+m`R*c4o zTT2gase?qAGh)Yqjr)yjvI`cFxu&K!sLwq;wMKswjBrgMW^^sJTxT>x7G~(Ub1Gh&ahNcABDN8gCXuzfC5oAgl)bjGzzYC^^mjyW{ybf(J_O9h> z_(aLH`V%tm7XuWuD^;O_mv<9oSI z)1_IDxM_>3W%BI2Q|{v6TnI=Kg~ex~sM+@gV(Ett%#9bFnZsr1=XSYH2kQ_&04er%3kYD=bcJpD R=ZrbYdikk*HE-92PWSkwP(uI! literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/65/bea8448ca5b3104628ffbca553c54bde54b0fc b/tests/resources/merge-recursive/.gitted/objects/65/bea8448ca5b3104628ffbca553c54bde54b0fc new file mode 100644 index 0000000000000000000000000000000000000000..031c91359a1032ccb0cebabf44195a087d265f35 GIT binary patch literal 160 zcmV;R0AK%j0i}-74FVw$ME#};8qlyT9FQ2}j~&>+9=n$_k;5Qr`<})Q{F`}`OkS>~ zT)MWHHob{xu{pYNL`=z&^L_*h1v*Yb2aJ4U!?JAu_OK&(^Sr zVHkiMdYEiTiXMHgO`rHhjrDo1_iV1m_K&Yk4=R+m`knz literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/66/6ffdfcf1eaa5641fa31064bf2607327e843c09 b/tests/resources/merge-recursive/.gitted/objects/66/6ffdfcf1eaa5641fa31064bf2607327e843c09 new file mode 100644 index 0000000000000000000000000000000000000000..8d6be4216a30ddcf37e38c8dfa900b9b9c2439bf GIT binary patch literal 664 zcmV;J0%!er0Zo*#a@#NvL{sA{F1?}|r%0npg*@?$$8u~ru0irhVh92Z4h+M5efB^p zNoRq;VfXFAm5&wO-F^P@;rr?MNU!I&=e;q{Zx?!ax}51q&*uwWzP_AJ^zH5Va(Sim zJ-r_OO?0vKod_BCz|3M8g6!ELqmCq zxK)oFg_$!mkR7K}WGTX-awVdkXoa8_Py%U3r@|++>&)TLTi6c|pN5s?6WRrMa z51LcjK1rM>q)gRH4Z|GE&PaAiF>d2^QrVA{0$4Fk5t-I8WEW-^Is*4{YQ~D!v%M9g zG2+(JgKO#_5$258abV+q<(lk*1!S(N=?&_0PY^Q-~Q|OD)$K&5(r|I&Pc_ znjf>nkibjng;J>p4$x>84W^z`3Ia1k_NTB{PpjG>EUHTjtQ?r8;rec zxf(uEGOhl^41#-l*YBfkuEL$*;Hpy1IIED&WXY_&Gg#aD6oX&)bPO0}Q@*j)S8=;( y7Q9ze-RfW7O`;*p^`M-P6ozRdCF6g`1trr(3nN{hSC9xyiE9x0X#N1NX^iCWjYJFp literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/68/af1fc7407fd9addf1701a87eb1c95c7494c598 b/tests/resources/merge-recursive/.gitted/objects/68/af1fc7407fd9addf1701a87eb1c95c7494c598 new file mode 100644 index 0000000000000000000000000000000000000000..6aaf79fcbfc06afb1e1f44d7b4d3b28dc0039f73 GIT binary patch literal 443 zcmV;s0Yv_I0cBD^J)#)~`ji=kUB$8BMjIypcL0h$;xRP)6!ZczhVDt&1Uz7p0H#<{OJl97U zgcwL^i5W6ZZB!^p_&s_KCn&Y+wT76b&1wP);T2CVV{KWjLBcUKIyRwQV5gK<6 z)~_RqSxxl-GK~?&j23};H_~@_E=n^{u@yQ>XL$7&gwgEO=&L0>iH;?yFt$ALrztI(nqaC8z&a>7Zp&I8pAN0WCFP$2O-q(?ym5+LeLvPrCSY~yt{$?L+G6)tk4kU%Y>M`aoYkefxZI?kit~>LRrGIFjO%(nP(;)X}h2946ur z+LbAYF6|e45M+MnQfz#Cg!Q=4 zcScoIbgOWsAqe9+zywtAm4JvTr`nO`;^Q?4rJEG{3*AXqz;l)RAP<^TiqjU1LQY#8 zWu!jvaHT9cOX*tOx+lA!9O@(b7D2)2Q&eZP)c?X6q-l}(Qc33dRH8Kk2>NQ?wqlvpHMgV+B-53jsBV)y09GA#Q*rNI9BU?-PR8n4rX8b{NiUDrkJS z#>IVIL}6sEP#W!F$k9Vhr9Eu{287ne%oiFZ_yGf?T1>7bFzwL9(DilYug92+rlY;JP3e_oWtY%)Op0?3(po5hq;V1r2sz+akEz z?=)AlD5y6_xc@uC++(7eNLWJI3%(6++bHOZX5GG{O}FfcPQQAjKTj;SFV484ZsW?AiFEQdC+9rnV945H2X<%(J;g~EU(}5nuN{Vx(L{|D_S)wu%0h7* zeMH0%tsDsuDSGs|HW>4ZT88snmwR2|z(POOiNAwiw@Y<7f5GG{O}FfcPQQAjKO^aWb JodCsxT!hleVc-A& literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/7c/7bf85e978f1d18c0566f702d2cb7766b9c8d4f b/tests/resources/merge-recursive/.gitted/objects/7c/7bf85e978f1d18c0566f702d2cb7766b9c8d4f new file mode 100644 index 0000000000000000000000000000000000000000..fe8b15777c9b82728282919b53e65c78672beb47 GIT binary patch literal 198 zcmV;%06G770i}(xPQ)+}M5+B1tE=H;=Nu=I5P|{;`V;-e-dt9Sy^-x)exHE&1G<^_ zq!}+Ua)qXM4>c2kZG6Bm=nK+xp>A}>x~?VH_7?k*tmy`824fU%b(Re8VaFWcI!i2) z;F%8klV0gp{I#=}_yWf2)-|T>H9TpnwL0i=Ug@7R>N9a=Tp-h(3rkY!4JO*5$hIEP z^GXG#ED=uEnc$1_jT0k$$X00QiB6AzcjN`fg@6;(nbf+C3wsC>k<(dy15#OGDOags A)Bpeg literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/7c/7e08f9559d9e1551b91e1cf68f1d0066109add b/tests/resources/merge-recursive/.gitted/objects/7c/7e08f9559d9e1551b91e1cf68f1d0066109add new file mode 100644 index 0000000000000000000000000000000000000000..48d22f6a920dbfbeac68d36f21840d9254bf22bb GIT binary patch literal 443 zcmV;s0Yv_I0cBFXZrm^o?yRR^cQ;dk44FH0O3|b!I?6U>5hsg|M4jumFDc(8Lr00^ z_eYM2M|gbv`sw-4%j>tF@bdiY$7kn$`x?RL8Rp_CgX|1%%@?V_0r;qbr4Fz)0g1Q* zXV^)iJ__PTr`x?Y4!3X4#JR#0dE0P?wrN3ex!meC(S)5Kq0bQgstl;T#hH@olRUx5 zlz^0$Qi6hWn-q#Oeu+MX0jhMp)({J~MNL2@yyD;rN-Jt5A|!fiGy`Sf{@z$lGip__ zP6OsN6x1Bv{TjKulPk~xz97^V0!@Tj(gCy14?Q`FG+po{tlYLUp}?)Uy0In^TIw80 zzs@KYHPr(sG)0&SS_J0ZL?4(gy;$ilWZYfy>H(Lf!ibu)t^iZ|NXSFL9ahRsG*usT z6CLNKi}C_gZH12V1HAeR!en+Nda;CO*0Ib2Q!8_NH>E{W6HK)MSO;a7+Pc*zs93IO z(|5l;ZeQgd;t9W_64~___4i0QXUzR9bn`RSiMtIGX)Ahg{{W#06#c{j+qVD! literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/88/eb3f98849f4b8d0555395f514800900a01dc8f b/tests/resources/merge-recursive/.gitted/objects/88/eb3f98849f4b8d0555395f514800900a01dc8f new file mode 100644 index 0000000000000000000000000000000000000000..41c812f10d9ba495e041524671e43bfacaf76380 GIT binary patch literal 209 zcmV;?051P{0i};SP6RO!M2US0XB!Q&`{R$aLTo@t#s&OoGaJkp86&RG0Lux8s_Ip% zr7C^fu2Unx-5es?TNJ{;&SwZr2*@opa9pTxHjoK@@vW-2G-RKez-EkKjT7TzZLX4q zoN{G{&P5+FfQwT8?h~|xuC+pm9VY-30Irs^4c=1=zM4YKsPr+{KJ-)lOrz?TwQuiz z*JnBCw|kVI;+F19-yXCjVx|xx>&1{U>Y&HCDgS(&Liz*)u&&*EO64-efAr_ LELMF1OGsspd1+=4 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/8f/35f30bfe09513f96cf8aa4df0834ae34e93bae b/tests/resources/merge-recursive/.gitted/objects/8f/35f30bfe09513f96cf8aa4df0834ae34e93bae new file mode 100644 index 0000000000000000000000000000000000000000..1011a885dad02485ffb3df66146a55cf0416c94e GIT binary patch literal 161 zcmV;S0ABxi0i{pN2?8+?^_(iwfRcY^LBz{;U;~-VgcV#PF>3opu>)`K1MidTx}Li< z&TV>QmTV@Ag@_Pz0&fvf2L$xM0fGs|DsVbEaZ8P_UB(=-fafVf(WD_OA3}-BkjWTh z2smXRS44XBr8YU!D>ag*rLOmSm3toQ2Oarq{Matn^&qu#-uuyKwVy1p-r|;GVp2~W$cLKNM%oUK{=F;c3zVALLE5QQ@Nl(JJ(P;zT>A#b=A* zgg2yiA1AFgW)q6j(U4;CvHEx=w5d&1oCKSlS)Ij*t*r;Q)Zs*|1+in`^!?^*<{byf z+)}d*rt?Bile3RzBUDpFVNtY6hJt43E&?8RpPDr<)dM8T-g;rK42wi?bh`yJ)I0{{ zXMQ1VsK3ysl#$yoGx|VBs zmuMWUfiJVHaHgd}lk9)>`{-t9xjnYs8jQO~TMeBknN@!ifrA(NVgFYiZ^XS~@Gz=w ztw!V&*)nVI4ARa%r5KJ2Jw`y`ec!#cS8?A|74Oyc_xiVYlWB={Sj;CR1u$!*mW%rX H{Cb92!PzdT literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/95/78b04e2087976e382622322ba476aa40398dc7 b/tests/resources/merge-recursive/.gitted/objects/95/78b04e2087976e382622322ba476aa40398dc7 new file mode 100644 index 0000000000000000000000000000000000000000..e3d15aac36c0fbbfd053d8ab640d1422fdfebd9f GIT binary patch literal 620 zcmV-y0+aoC0Zmi8uGBCPrS?}0eON(3fwrOm2?>cSA)uZllZ_R}&h^-Y@b#Q=c7ZaE z=gfJz52>d&uiw3W@%_X5&-C@nx2KoRJ=H=!mPAZjDpckyLeG_RQA!i-TqJk*;}m_0 zN&`l8kI*SooTMzE3!--f6V#mPg``y>fI}VV! zrDhvU=Y>8^&OVxrP)!kqMbRc13Yww22zWevYSuhg50EH(>xH>8EE2)d?H0^X^B9ny z`GvHh{z4y9MsCB*=mQ<8(#l8c6VsS}!{_Wb0ppcRQs-kwlh2AIc`@zxYQQrzC2D70 zqH(YWzRa@1nU)4kvj5fZqnn}S{@8YFFzz00HFTn6R{c!`4qoVo{a<;!6ZeY2!>GEo z8j(|E%dEXKNIUzKVmL1JJ^~8w`{Avl6NZB)akV zn~^5Bb-nDs!Z&+21C;C)on}JPL>dEojZ(yNDCCo`p3&7Zy=u2@1eL3(w@f+uL6o^j znX#DRz)2ko)%h;|@}aU+##9ZX5ZCB)4XUnG4D8g{S>&WP>D#`v4v*zsdx7Vrt=G1} z$%gx>&i3{Axo&e??}3~X5uzw?M29#HcZ}QZpEc8y^%sNhHaPrs!T~PZ-XL||^73$` J=>uRAa5Ko2Zmj?S literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/9c/3f1c70db28c00ce74b22ba3edafe16d9cf03d4 b/tests/resources/merge-recursive/.gitted/objects/9c/3f1c70db28c00ce74b22ba3edafe16d9cf03d4 new file mode 100644 index 0000000000000000000000000000000000000000..b0ef1af86c8ef909ea5a8c752c205e591fedf38d GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKw?ZxlQ5_CD}FxvcBC zX+Yex%B(FQp)f=ma2SMA0x^Q)NB~YC`$!>X8PqLRzBcW%pCybOeGp4FWHUM^-T*x;%4xSN@mOlDG@ z=SPzo!lA9q(oh%zIrh<_B|r?xYcNb44I5$t)1fco8CPDK#DrA5<$%5ndGJYD=L#yF zbs|LPs25}?BJORfs~qzyu36ruI&XE6XYT1oUHJ=s?v(0$kpqCW;GMGas6Z*v(>}KG VpEY94{c_y;g?QgL@dgtZQTd25Q}_S? literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/a3/4e5a16feabbd0335a633aadb8217c9f3dba58d b/tests/resources/merge-recursive/.gitted/objects/a3/4e5a16feabbd0335a633aadb8217c9f3dba58d new file mode 100644 index 0000000000000000000000000000000000000000..00f9c2ddd1d8e6b2df28ccc58ebedb4e3369507d GIT binary patch literal 164 zcmV;V09*ff0i}=K4FVw$gngz88qn~wu#gzz%XMG_!0zQtJTZvczG&>gx0!E}$xNy1 zdhXHyYQpSGzyV#(Xy$BVF0%$gaZ8P_T}HGSl{JRZ1xf)~7dD!V zj*fyaj)9{G6zS2I+T=v9)JUF|y58$m?s?FUI`TL8xm~I2L23Z!oHoJBtpcUQpkr+3 SKWoH9lIJ-a@ z$8+Yq+=tZD+c)puz54#)=`(%(^6mNJ+;c7DV@brcr9x%SBJ@%@7o{}O&P8%}KTgr7 zs5D?iR}P`06vgS5Qk-hA>wVy1p-r|;GVp2~W$cLKNM%oUK{=F;c3<2ht)u`f#+VIn}IJ(#5a1;LR5xTw{XwHZoM`8?_-rwp z@P^dxM!&$W#l%@j6TqjDy@99J~55yH+;^16EI%6By~P^H2JJZk{8o{uLe9rQ=)d} zB^n27;L9v4oM~y$B>P|eKDrrN?vHJ^2IKD0RzoLBX4T(B;NXRR*#DKsJ8`cVJdCPa zs}VUxw#?c)gS4|xDTd=hPZ3af-w$u?RXjFT#d~%AqyFvPWLjb!7V`;70n8ey<>LMT HT=<4_?*22G literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/a8/2a121ea36b115548d6dad2cd86ec27f06f7b30 b/tests/resources/merge-recursive/.gitted/objects/a8/2a121ea36b115548d6dad2cd86ec27f06f7b30 new file mode 100644 index 0000000000000000000000000000000000000000..e740872fa03f7c70cd80cba278edec8365618b7b GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKTj;SFV484ZsW<738(nBvk`QV@dir7t@=1fT|i4aAqT&k-2^_`{c zwzrrfmosmMseG*H;o;Ng58qG6uk?C;yX=j*yj|((`Ff@!UCvj!et9{a=-b=z<@!qJ zM|wYAPcJ*lePX5oJmIO{f^GhCnHmgp`AU&mMU-SfhL|NPBg_iG~DdShKBMI zb%R)+ceJ?NZ!2jVZN$5pMR$0%fqFY0@K+|6sfx~%WVVg-YdO`&Imv-!a3eODSl3pd z42o8j%7G?GbRkDQZ%KL=bo5WQ(ER^cRaK@LA4A9KK-ms3isP6=|5QQH=A&F1+qQh~ z5?f(%EiA4^Fv&NRoG@hQ97~<^1xy!XLp8Qz%;9dX&3PsA8Mpd0|aNaam3&>nk(;L+1o}OBxKMF>;rVul_mRhbenjs4_blf== zG(TpCA%U0D3#C#I9H7xG8caQ>#v?!Fg|y**PmeJnx4O6J1FdnU(XORWmYVn*oRgav zibtEH7#DWbx+F-_4(k0@4KPDfg6xzf8V5As((?#1B@JqM`Rm^W)5FVx91~uLHW+)? zay5LSWLo`+83gzAuHQ%7+=M&9!BwT2aaJLl$&y)lXRx;QDF(mp=@>A|rhI3sui}2w yEO@V`y4SzFn?ysH>p?joDGbv_O2+?=D@vw|7Dl>0uOJba64xNKH-7-HgN*UF>qEl; literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/b4/cefb3c75770e57bb8bb44e4a50d9578009e847 b/tests/resources/merge-recursive/.gitted/objects/b4/cefb3c75770e57bb8bb44e4a50d9578009e847 new file mode 100644 index 0000000000000000000000000000000000000000..836bb4edcb1dec682ff243dd480df1024b5c1553 GIT binary patch literal 639 zcmV-_0)YK^0Zml9uGBCPrS@0M2ZWWNpxNpcAR!@fC0_L;nQW{$cCN=JgsoAr8w1K*ZaW3LYr)xWZ=~}%GeRdk;Ep1!KGnf1v4-@jH*Q19;z_Uq_dB<{HHKD z{|{@d8k!3!-XveC@FJ8j4jlT&3WQD_ZE2dO_WhQHRme|}csK=87%6)d&@ddPn-9&H zTS_AhxDJ@r|2iE2IU`WG5AwR%sPNH&=@cLleDgsO#+a^VA~+oqmS&WV%I&7q3qp#t zizT8ZGt`#ZtHYvFGsxI1k0WVXg@!pHo{=`r8sxZIPWk+#scy)W`h!M+IML2&@!4WH z;SH(X$4RS=*@WVBG^AL3tUlfdZE8~$C&6ZCR%bC{YwN*1bvO}gLF^bfeZTvfdB*`V zx72Kd>AcX#$=Q!)BUDpFVNtY6hJt43E&?78pPDr<)dM8T-g;rK42wi?bh`yJ)I0{{ zXMQ1VsK3yMl#$yoGx|VBs zmuMWUfiJVHaHgd}lk9)>`{-t9xj(ku8jQO~TMeBknN@!ifrA(NVc%CC@5H@g@Gz=w ztw!V&*)nVI4ARa%r5KJ2Jw-s_eLuXlSMk_X74OyckNUTFlWB={Sj;CR1u$!*7W{X7 ZMak@tA>=lf15QMtECU?6xIZ-FkkMG{L{+DzX0l7ngPDQ6qH@4`Z1v)B;k{EET)RHf_-&f9U0!fjS z`XoJGUZ0;XU++J^xPE+pof#bXwHmP}3$b>vlXKxQayA7iCMh_$#kW-I)?tsfJTTXXze?Gn-CKv9j7x_W zHAzacAF{2;z^WKy;la3Z&6Dhms}*uz4+zcMhaz=eK+woHepo4&oA)xfpxxpLM};ir zrDm*BxcTK^LfQiQ!ZfxsqrJg)fl;6Mq?<_AsixL-t?FU2Vjxp@-eXFjaRh}aX2z80 S=1+q8cKeOjJBNSmtBjvLQHhWM literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/cb/49ad76147f5f9439cbd6133708b76142660660 b/tests/resources/merge-recursive/.gitted/objects/cb/49ad76147f5f9439cbd6133708b76142660660 new file mode 100644 index 0000000000000000000000000000000000000000..849668c8b64d036d37466e7d3036b4c2dd30ec16 GIT binary patch literal 641 zcmV-{0)G8?0ZmiOlG88{G*}7&o7UAV;)~F^zij^rXxL`FLe3*bUM+um*dmrna-c+ z^>{fw?I;h4nPPA;2(=}XOxF7yPT0sCW9W;g*i++eJJQVa%!%e$LdV^XZ0IO2Q7?$~ zc}I)O!*-H3Xd~XWEPBJU4KfM1zhrY1U1lG%37uXSpOCCPzgbQ3O^*tS-{42)K# z%7JE3bRkEbw zRTIH!Wj|J|n)cjM!Rx za7!Idgpv_E1~%Vsz9zfi0GVrQx7h6Jr`ibB6klA#JGN)2En_TRT|vf!0`PvTN;=r7r%4&&kaU#*@ua zj0-#JT@oZ|N7a6-20TMkg6z~wG!E9lmw_iZQ`4ZHm%sX5FaxwK$T8t{XoGQgt*fCE zCDZE9%y4i|uljwm-Ho^t46aJmOht)oB5P*#ok7~xrx^UYr(*z=P5JJvzKZ*%B6zQ+ bx!1qGn?z$M?WjH>DS&AsCGX82&R2r-HC8|q literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/d0/dd5d9083bda65ec99aa8b9b64a5a278771b70a b/tests/resources/merge-recursive/.gitted/objects/d0/dd5d9083bda65ec99aa8b9b64a5a278771b70a new file mode 100644 index 0000000000000000000000000000000000000000..b0d951c9e75d5555fc1c0b95e1b8d44bbee483e4 GIT binary patch literal 620 zcmV-y0+aoC0Zmi8uGBCPrS?}0eON(3fwrOm2?>cSA)uZllZ_R}&h^-Y@b#Q=c7ZaE z=gfJz52>d&uiw3W@%_X5&-C@nx2KD9PqmPbB@xq>3Y9sF&~xQnl+r{y7s=iII7OeL z(tr_NIfRZ<6sKECajLeVNabd_p@7evq~? z2uGTEy;2ZRE7T_+NQ?03!_lVZRI^@57r)|yOT)klW?*y}Rf)7cRAHV;XCH0(PhoKW zAJ$kkG#665Nxo9yMJQn$IP{Md2%S3G(lkx&|1Arvke?v&a0;X_QuZpKVK_`TADS_@ zltvnG9Wbl^bvgiYMxbyXa5^L`%_tj{+fAt#gcNBP zOGHa%s4cTshef4kkg-`FN7A$k4Rb;~BW;{D$Z@rt^7%_s-H<8u2aN)8qMg&?v&C@2 z8&bQElU5tE3B~DXNU``>eY_Fc)TSyanl;bW10>4cdSR{%i$rjAy9G1UJO<=v zej#nBztG2&k=rmc`anmjwDQsV#5AVg@HzWUz*0QkATAaet2uI;<2eJ-mB{$^>6Pc(-P~jm`_LwVAe=2FWnzp G-iBs$mNeu5 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/de/a7215f259b2cced87d1bda6c72f8b4ce37a2ff b/tests/resources/merge-recursive/.gitted/objects/de/a7215f259b2cced87d1bda6c72f8b4ce37a2ff new file mode 100644 index 0000000000000000000000000000000000000000..55c1983a8cee9611837f6ae359504e403078d219 GIT binary patch literal 357 zcmV-r0h<1J0Yy?xPs1<_<(yw(?h`iz5~rQGATcra1KiYIqh?7+9H#wyUeW@mrq1*G zurv5L(Bt#d-Trvkf9zjRM>@Wr4)?}<@**_Fn#prM3k@~cSqjC8xFpVeu4PBXW==v* zDL5I0NTxD3=ZgKp{7+VNlKDCVPUT?hR2cg8tJQY)*ff`Fhu89L3O^L z=+_N|zp7KA5+~g?P%wwn+hK#xIo5NtRh)dws#`QO@&USLM1D+ZN7vcenJ%>`4MNCh z5MgPfXwVe(r4{kt@!+&*SmZxcpFqR5fno&aZyOu;%p<7L;o0GYmGop-Q4L7ebc)~- z4ln^{J(kK@OsUi4tdpSrMkChOg09+KbMkl$AghX%^?_cTU$(T8zxykw>B0N}=djOq D3bL=J literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/e2/93bfdddb81a853bbb16b8b58e68626f30841a4 b/tests/resources/merge-recursive/.gitted/objects/e2/93bfdddb81a853bbb16b8b58e68626f30841a4 new file mode 100644 index 0000000000000000000000000000000000000000..fab55fea641a6f1468010aec61395fccd7374c4b GIT binary patch literal 207 zcmV;=05Jb}0V^p=O;s>5GG{O}FfcPQQAjK05AV|0V^p=O;s>5GG{O}FfcPQQAjKBRoFqh2M5$J? z4c>DLzM8_#{O%cTrij)!H9pqnDqGAcS8?QA^pOI(sAWlSbL|5j>U$a$p4Ps-_8o5Y zNI%t`eic9Ny7cW9EVBrQXc5kajaiQLI5+j5nB`H&v%)tGPJg{{g3CTTicf{M(4xzxK`?T zz0m&a<$&4a;X;?!({4xKuG`b)OotbG-(Gg76{RjPlXu3uNOevW2W{;NC#>S=y=${2 z-%@3D-P6e9$bm+mUBk_av}-6$UIwDJX+@Js-EtBZXceugIm(1(?Wohk2EP)SM3py| zVq)DGJD07_=MXm(doy4_`MTB-%)n?Cs_bY4MdOl}eNC}5PN09X2Iv1_g;haQ*1H>r z4JF+}DAs{P|5$<0qN7~u+qQha1=f+tw2(Nf2qfE3Fp)t+a5UYFEymouZ>YvNUt-VXeW#euH-^*6UiIv?>MTts4gxImL_Kq!2{KPM$4fSh! z@d3HjokkyM_L&Afmp*A~{BQUi%*bFo=;Wg^ZbhvL5lQM^wBM@%&(IVXSK=ia2W#L< z#{--xX;914U;W0Z4q7JU81Ooz!I+)P)zFEON%co&IJl;F`9A38PTWK+&O%iUS%@qm zOJ?PrLE6$M@9ey$tpk(}>EW%sipNbk;=QWsQUCI80`)G}z4(Nr049x$X|4VMzm1CR DzwlOd literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/f5/1658077d85f2264fa179b4d0848268cb3475c3 b/tests/resources/merge-recursive/.gitted/objects/f5/1658077d85f2264fa179b4d0848268cb3475c3 new file mode 100644 index 0000000000000000000000000000000000000000..3b4eb97e97d52f89e379338afcb19b587f261683 GIT binary patch literal 355 zcmV-p0i6DL0Yy@~P6IIzr1n=VeME;qN|lO|h>#E1^X=uVb8N?6C(7S5_64Z?nw`h4 z2OkG|eSdq}9rnAg-N*4jhtK2w*_dx$gr-U~E<2*bJ(fL(So$ovP zbpzo`bt+Wiq?-l`CRN`ppK;8wo|>)VJ)Dn`~DdUk$!q?LT_zo4cU^8<7L&-Q!` BuvGv6 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/fa/567f568ed72157c0c617438d077695b99d9aac b/tests/resources/merge-recursive/.gitted/objects/fa/567f568ed72157c0c617438d077695b99d9aac new file mode 100644 index 0000000000000000000000000000000000000000..ad5a3cf4f2289302c712888568f61f6afd43fa1a GIT binary patch literal 662 zcmV;H0%`qt0Zo*_a?~&oL^*we5nZCWAp06)- zd7!t`_555>9uhOf;9?MJmP|5P?<=gZkvYcDEuLaWwYSYkGtV<8n&T2$ZY#2(rMyPn zAlB!KR+oo;CGDe)c-OG#4$n5wV5cMg%H%TD(Rq^0wsn3hr-ryBIg*TS!UhwY#tM`{ z(WX*4&4&H{>c`a{~xQW$~5C+=s6uJ+Yv@_9CPTODhS$rluKjRmG6CG zD@?9~#mxvN`IeFsh76r!sdv7B>0@lE!FG(9+^?Mg#HoO6YtQcsMgd0yrJaXG=uI01 zfKgusA~bF6#{x=^a^DNpY%@HstcgfY7H;$4#NeX5B#6|30E2cRj(5<&8}1ME5EF8128%w>78jcAR{CVAjlaP;xtXDO zvN?)zp`y+uL6UY<@3(4z8JZHLQkG~O(16Rp6UdY_sN?moe;3REFDr6Pcpchc?A^-M z@QIRX^=D=fJkXndpKN;*?gR%nm1?F%h3qCvX62p1+TN!a{C1#Iz$lyYovpr#`%R1B wy_))7|MG4UjbUj<<%Fa#OdBZ~|2wWInJ!uw>4&_5L|{tXfY8DG0Xe~qQL@xg)c^nh literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/fd/8b5fe88cda995e70a22ed98701e65b843e05ec b/tests/resources/merge-recursive/.gitted/objects/fd/8b5fe88cda995e70a22ed98701e65b843e05ec new file mode 100644 index 0000000000000000000000000000000000000000..b6f14634e403147301851fbcdffc67b275b3bd7c GIT binary patch literal 165 zcmV;W09yZe0i}=44FVw$g*{UR4QPNJU`UMdvK`m}FhkbEieWLv?nPq<-ri60<-J_j z_1dKYx9g2r!eqgK56G5vGMWf1BI#^`P7ye1A0kdD?y>Q$OP_rzXgPQ+nlxr*ohx1$ zGC6tgTnZTpiinTC)Fx+o#zyk8)OD*jdE}9P)S17<&mD4IPf`O|3+N`4dj(2~k&dyQ T|HO!y#^w6j21&dDYs63!76MG; literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/fe/f01f3104c8047d05e8572e521c454f8fd4b8db b/tests/resources/merge-recursive/.gitted/objects/fe/f01f3104c8047d05e8572e521c454f8fd4b8db new file mode 100644 index 0000000000000000000000000000000000000000..715b6a8657cb82115e844624d7b8153d1d17b9f3 GIT binary patch literal 207 zcmV;=05Jb}0V^p=O;s>5GG{O}FfcPQQAjKnBG<2*eK(fL(So$ovP zbpzpRbt+Wiq?-l`CRN`pUvSK^o|~=WB!phksfhaE=JlVLJ)Dn`~DdU1Yvrj>l_zo4eA`2mp_&;vFX BuR#C+ literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchA-1 b/tests/resources/merge-recursive/.gitted/refs/heads/branchA-1 new file mode 100644 index 0000000000000000000000000000000000000000..b55325c3efd276f01c0c53e28b713337e5139d9c GIT binary patch literal 41 ucmV~$$q@h`2n4Xd)$F2xl*2LhUxJD5r~%pMinJPnv0#=^HbNKq*5(-WL literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchA-2 b/tests/resources/merge-recursive/.gitted/refs/heads/branchA-2 new file mode 100644 index 0000000000000000000000000000000000000000..d35574340651df1d5d1ea6c08a9bab1a72292b8b GIT binary patch literal 41 vcmV~$NdW*L2n4{tX%JbCI3U0+|D2m`>sX~YR)oFULZf_KC&rC1juaso;N$P8a{-fd)1J;w+AL<`se literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchB-2 b/tests/resources/merge-recursive/.gitted/refs/heads/branchB-2 new file mode 100644 index 0000000000000000000000000000000000000000..d5cfb2762cabe96e94c4ed71118badde1c95a0cd GIT binary patch literal 41 ucmV~$!4Uu;2m`Rc(@^0k>(m4GAHjszQCPffw+Sj6?WyQujAJMh6z2ow%L?fL literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/asparagus.txt b/tests/resources/merge-recursive/asparagus.txt new file mode 100644 index 0000000000000000000000000000000000000000..f51658077d85f2264fa179b4d0848268cb3475c3 GIT binary patch literal 587 zcmYLHOLD^?4Bc}Ib)V@4vdXH z(wKnfFoN&ZZdN?glT|W`=9oIFDEp;!SOQUp#n4tWxh(W_IulcJVx?Ib*v0_b-DC_7 z=w_j&O)N=Dk~?8xuSdhqW+1L1phDpca6hXx8JRo^YI zIObSy%~o;pkWIH}X5<5O%ZU8w(t)0{voo!=C=Ei$Xb@p(t!U5`_1G?P?s#xo6fE)| zs&}AaTSL(T^EZv1d*%_;sPOEt!$^8EjHm`AYdS^n2nXnZvmQg`ET+_Ha@I*u|DqA& fYe6^dt~q&p29Q<7$a+Ip=a)UL*~#u literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/beef.txt b/tests/resources/merge-recursive/beef.txt new file mode 100644 index 0000000000000000000000000000000000000000..68f6182f4c85d39e1309d97c7e456156dc9c0096 GIT binary patch literal 1372 zcmZux!LHLV5WM><_QoZzAHcgIJq}zz;vvqPWRqBRY~ytr%GWb%_X#1mv~p|j&dkp2 zhnJU+^!4+%FBj)t`6^U5q0Psc6rYq98by|YrlaDp5QosNEJ1W@zu1Ey>(iK`4DQ_g zw9$TO#Y3v77>Q55lf>$ag!@3LvQ56;4E?j8}!gvla0Tp~D zAY#g?4y3vGcnw17CdK|jchVj3T;(yyljfA-as;E0(-CKxX$(AFDND{$hE}(p$u1~| z`i#CsP%!!w)fp}IziGJHgi^kSG_P-&|)#-4{#a9+Mv5=BW7oFw!-%v zP$4Y@)F4(D2X= zg^*60(ateSc~6kQ@tbM>v2%o19!2z6+2F!KNQy7;j$V-|v4~(+zPe^7G(q|v#sCK( zsTMta?-IbWg)F7367qDXnag$Pc5KB_harv)!Y10Mfq=jp7y<=fEB-=cp|;=QWJTJM z(A7G;?F_gs$i;oFg&T9PorPVq{yXA?>!+Z>>1$gA5BqgXp zl)d2F@V1SDzL*9U(1EDO<{xn7xx>#=;i4E literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/bouilli.txt b/tests/resources/merge-recursive/bouilli.txt new file mode 100644 index 0000000000000000000000000000000000000000..4b7c5650008b2e747fe1809eeb5a1dde0e80850a GIT binary patch literal 1092 zcmYk5U5?u@420ix3Le0l19abt0__3|v_N;!XW6E0!HVcgR9xS_Lpl2c1OcK@!*7Pv z@1L)~=+D#35BmD^_38Qf>EhgrUzv1aN@3ulwE3(gQ#;Zn3@i0Hl$G0I&pdVHd#Oqs z<^|WFC}9nj|-QLEB74>h?%i!wBm5pC2?H z5NajGUzv7)bR-F<_b!siCt9T1ZAqLv6nmvZDufQV_!~S0Tm{XR8J0K!ahVf?yz%*q@#zm^@){YAh@B235V# zd(vfvJDJXmPw|r&y$+76#Secx&$M%lu4k{DIs}NGG~t)!1`V_@hTWH?QK@Wp7ct~J zblGx9Yh*HbhkElfd{qu1EIC5uWy8Yvvy*o*9A$W-Ljl-{*^E!`a&in=ugH z4yQ{kUmhM>rk+ZjrZ5CfN`I?Q8uV!X-lk-HH=bF2ANhUYAt4d$!Z;eEg^9VN;Gt~T zs;NfP$k>b>*_2nZdFFDS~^jr)hcPt3-R{ e9o9Bu**`CHo3z$;vxxw{7`=)w_G;UjT-<*kZ-7$( literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/gravy.txt b/tests/resources/merge-recursive/gravy.txt new file mode 100644 index 0000000000000000000000000000000000000000..c4e6cca3ec6ae0148ed231f97257df8c311e015f GIT binary patch literal 390 zcmX9)L2kn^47>Xkd_da|?6gyl8&+(Y(Y^3lH<7BTm(g|Y>S3~CB2#zXb19%0K_TVJNQEB$B$#iH-*~-C_yiai$1`1g+}r15kD{bR+?Mf56N8>)Vgt z@cQ!S*V(zhz9sNwf~k5cAREI+_f;Bj1m2rqZ6{c}fFxXi3v47w9~JSt(`{ZGPxo&w z#HB$IYY&%2ZiE-Ps!(a zf+j<+HKfXYRuj+&Z+LPQrB}6*5Hfvqnt+P%c&{vn8MUfdhXHdMD{2m3evRBc$Q5V@ zUlCf5kpf|nyu+mPr;(f_3RgS`8~61{C~~i^t*lAJo(D(PuOo_CO^pC5g#@9ZMPS}d z^p5#DijDq3!Odl_9&nx;Tu^h?6=2Ta33-UP!9t~rrs|_^V&L3$QJI07tW_mdrYW;}#xl-A QH$PDeJZzXqThZBl0*7D{sQ>@~ literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/veal.txt b/tests/resources/merge-recursive/veal.txt new file mode 100644 index 0000000000000000000000000000000000000000..94d2c01087f48213bd157222d54edfefd77c9bba GIT binary patch literal 1095 zcmYjQ%dXTg4Bh7|%)ZPI%<3*cLPFw72w1zV+eS^3-Z-I@uje?O0hUeUz8k@@0@$Bg?ucDnD$htELnu!D(9kJgY*Be#;T#Ykm4-)Muk_QgmK`| zKUN@g>1a#SG`0V87FHoYLE`BYNMWSxRY1dVm}VcEF>^{I4Y&@N&HuU_068O2xDWEa z*{JZ*f$0<=5q$GW5yqIVW+FJ964qvvjmkVL^@5Nh9b$=S$qcn+@#?Us)C@8<%i~Cz zHlbljh-ajovj#cumQ%idX{tLirT(N*AWpP%T70$`E_g#~_i@r{V>Y2U9StcKAFGcu zp-pY7;w0GY!s;wWY;8Swqz)%yEr=Zhm+uc>GaooW=9ZdmFr7F0G&%cdHbON;6c$CB zWGHBc9wOlJ^r>0%Ry{zX9IY4T%CJfVM|W5-L(OAAe&!d_hWZT{TYMH literal 0 HcmV?d00001 From 75dee59c94d39b308529d45dfb993b25d2e9a5f0 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 26 Oct 2015 10:37:58 -0400 Subject: [PATCH 03/17] merge: build virtual base of multiple merge bases When the commits to merge have multiple common ancestors, build a "virtual" base tree by merging the common ancestors. --- src/merge.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 123 insertions(+), 10 deletions(-) diff --git a/src/merge.c b/src/merge.c index d7b23e2c8..05ca3d0ec 100644 --- a/src/merge.c +++ b/src/merge.c @@ -27,6 +27,7 @@ #include "config.h" #include "oidarray.h" #include "annotated_commit.h" +#include "commit.h" #include "git2/types.h" #include "git2/repository.h" @@ -1922,6 +1923,117 @@ done: return error; } +#define INSERT_VIRTUAL_BASE_PARENT(commit, parent_id) \ + do { \ + id = git_array_alloc(commit->parent_ids); \ + GITERR_CHECK_ALLOC(id); \ + git_oid_cpy(id, parent_id); \ + } while(0) + +static int build_virtual_base( + git_commit **out, + git_repository *repo, + const git_commit *one, + bool one_is_virtual, + const git_oid *two_id) +{ + git_commit *two = NULL, *result; + git_index *index = NULL; + git_oid tree_id, *id; + int error; + + /* TODO: propagate merge options */ + if ((error = git_commit_lookup(&two, repo, two_id)) < 0 || + (error = git_merge_commits(&index, repo, one, two, NULL)) < 0) + goto done; + + if ((error = git_index_write_tree_to(&tree_id, index, repo)) < 0) + goto done; + + if ((result = git__calloc(1, sizeof(git_commit))) == NULL) + goto done; + + result->object.repo = repo; + + /* if the initial commit we were given is virtual, we are octopus + * merging - that virtual base's parents should actually be the + * parents that we use for our new virtual commit. otherwise, it + * is an actual parent. + */ + if (one_is_virtual) { + size_t i, cnt = git_commit_parentcount(one); + + for (i = 0; i < cnt; i++) + INSERT_VIRTUAL_BASE_PARENT(result, git_commit_parent_id(one, i)); + } else { + INSERT_VIRTUAL_BASE_PARENT(result, git_commit_id(one)); + } + + INSERT_VIRTUAL_BASE_PARENT(result, two_id); + + git_oid_cpy(&result->tree_id, &tree_id); + + *out = result; + +done: + git_index_free(index); + git_commit_free(two); + return error; +} + +#undef INSERT_VIRTUAL_BASE_PARENT + +static int compute_base_tree( + git_tree **out, + git_repository *repo, + const git_commit *our_commit, + const git_commit *their_commit, + bool recursive) +{ + git_commit_list *base_list; + git_revwalk *walk; + git_commit *base = NULL; + bool base_virtual = false; + int error = 0; + + *out = NULL; + + if ((error = merge_bases(&base_list, &walk, repo, + git_commit_id(our_commit), git_commit_id(their_commit))) < 0) + return error; + + if (error == GIT_ENOTFOUND) { + giterr_clear(); + error = 0; + goto done; + } + + if ((error = git_commit_lookup(&base, repo, &base_list->item->oid)) < 0) + goto done; + + while (recursive && base_list->next) { + git_commit *new_base; + + base_list = base_list->next; + + if ((error = build_virtual_base(&new_base, repo, base, base_virtual, + &base_list->item->oid)) < 0) + goto done; + + git_commit_free(base); + base = new_base; + base_virtual = true; + } + + error = git_commit_tree(out, base); + +done: + git_commit_free(base); + git_commit_list_free(&base_list); + git_revwalk_free(walk); + + return error; +} int git_merge_commits( git_index **out, @@ -1930,18 +2042,20 @@ int git_merge_commits( const git_commit *their_commit, const git_merge_options *opts) { - git_oid ancestor_oid; - git_commit *ancestor_commit = NULL; git_tree *our_tree = NULL, *their_tree = NULL, *ancestor_tree = NULL; + bool recursive; int error = 0; - if ((error = git_merge_base(&ancestor_oid, repo, git_commit_id(our_commit), git_commit_id(their_commit))) < 0 && - error == GIT_ENOTFOUND) - giterr_clear(); - else if (error < 0 || - (error = git_commit_lookup(&ancestor_commit, repo, &ancestor_oid)) < 0 || - (error = git_commit_tree(&ancestor_tree, ancestor_commit)) < 0) - goto done; + recursive = !opts || (opts->flags & GIT_MERGE_NO_RECURSIVE) == 0; + + if ((error = compute_base_tree(&ancestor_tree, repo, + our_commit, their_commit, recursive)) < 0) { + + if (error == GIT_ENOTFOUND) + giterr_clear(); + else + goto done; + } if ((error = git_commit_tree(&our_tree, our_commit)) < 0 || (error = git_commit_tree(&their_tree, their_commit)) < 0 || @@ -1949,7 +2063,6 @@ int git_merge_commits( goto done; done: - git_commit_free(ancestor_commit); git_tree_free(our_tree); git_tree_free(their_tree); git_tree_free(ancestor_tree); From cdb6c1c83dd6f0d30b798a7f62d4f3849a1f11a1 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 26 Oct 2015 17:14:28 -0400 Subject: [PATCH 04/17] merge: add a second-level recursive merge --- tests/merge/trees/recursive.c | 50 +++++++++++++++++- .../0f/a6ead2731b9d138afe38c336c9727ea05027a7 | Bin 0 -> 206 bytes .../41/71bb8d40e9fc830d79b757dc06ec6c14548b78 | Bin 0 -> 207 bytes .../4e/70a6b06fc62481f80fbb74327849e7170eebff | Bin 0 -> 207 bytes .../68/a2e1ee61a23a4728fe6b35580fbbbf729df370 | Bin 0 -> 665 bytes .../75/c653822173a8e5795153ec3773dfe44bb9bb63 | Bin 0 -> 206 bytes .../81/5b5a1c80ca749d705c7aa0cb294a00cbedd340 | Bin 0 -> 170 bytes .../89/8d12687fb35be271c27c795a6b32c8b51da79e | Bin 0 -> 663 bytes .../ad/2ace9e15f66b3d1138922e6ffdc3ea3f967fa6 | Bin 0 -> 170 bytes .../c0/bd078a61d2cc22c52ca5ce04abdcdc5cc1829e | Bin 0 -> 207 bytes .../.gitted/refs/heads/branchC-1 | Bin 0 -> 41 bytes .../.gitted/refs/heads/branchC-2 | Bin 0 -> 41 bytes 12 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 tests/resources/merge-recursive/.gitted/objects/0f/a6ead2731b9d138afe38c336c9727ea05027a7 create mode 100644 tests/resources/merge-recursive/.gitted/objects/41/71bb8d40e9fc830d79b757dc06ec6c14548b78 create mode 100644 tests/resources/merge-recursive/.gitted/objects/4e/70a6b06fc62481f80fbb74327849e7170eebff create mode 100644 tests/resources/merge-recursive/.gitted/objects/68/a2e1ee61a23a4728fe6b35580fbbbf729df370 create mode 100644 tests/resources/merge-recursive/.gitted/objects/75/c653822173a8e5795153ec3773dfe44bb9bb63 create mode 100644 tests/resources/merge-recursive/.gitted/objects/81/5b5a1c80ca749d705c7aa0cb294a00cbedd340 create mode 100644 tests/resources/merge-recursive/.gitted/objects/89/8d12687fb35be271c27c795a6b32c8b51da79e create mode 100644 tests/resources/merge-recursive/.gitted/objects/ad/2ace9e15f66b3d1138922e6ffdc3ea3f967fa6 create mode 100644 tests/resources/merge-recursive/.gitted/objects/c0/bd078a61d2cc22c52ca5ce04abdcdc5cc1829e create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchC-1 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchC-2 diff --git a/tests/merge/trees/recursive.c b/tests/merge/trees/recursive.c index 1d3586162..a7358e7e3 100644 --- a/tests/merge/trees/recursive.c +++ b/tests/merge/trees/recursive.c @@ -88,8 +88,6 @@ void test_merge_trees_recursive__two_norecursive(void) git_index *index; git_merge_options opts = GIT_MERGE_OPTIONS_INIT; - opts.flags |= GIT_MERGE_NO_RECURSIVE; - struct merge_index_entry merge_index_entries[] = { { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, @@ -101,6 +99,8 @@ void test_merge_trees_recursive__two_norecursive(void) { 0100644, "4e21d2d63357bde5027d1625f5ec6b430cdeb143", 3, "veal.txt" }, }; + opts.flags |= GIT_MERGE_NO_RECURSIVE; + cl_git_pass(merge_commits_from_branches(&index, repo, "branchB-1", "branchB-2", &opts)); cl_assert(merge_test_index(index, merge_index_entries, 8)); @@ -108,3 +108,49 @@ void test_merge_trees_recursive__two_norecursive(void) git_index_free(index); } +void test_merge_trees_recursive__three(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "15faa0c9991f2d65686e844651faa2ff9827887b", 0, "veal.txt" }, + }; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchC-1", "branchC-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 6)); + + git_index_free(index); +} + +void test_merge_trees_recursive__three_norecursive(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "b2a81ead9e722af0099fccfb478cea88eea749a2", 1, "veal.txt" }, + { 0100644, "898d12687fb35be271c27c795a6b32c8b51da79e", 2, "veal.txt" }, + { 0100644, "68a2e1ee61a23a4728fe6b35580fbbbf729df370", 3, "veal.txt" }, + }; + + opts.flags |= GIT_MERGE_NO_RECURSIVE; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchC-1", "branchC-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 8)); + + git_index_free(index); +} + diff --git a/tests/resources/merge-recursive/.gitted/objects/0f/a6ead2731b9d138afe38c336c9727ea05027a7 b/tests/resources/merge-recursive/.gitted/objects/0f/a6ead2731b9d138afe38c336c9727ea05027a7 new file mode 100644 index 0000000000000000000000000000000000000000..b06362dd8762c3f120e98a65923f5bce9fcf5441 GIT binary patch literal 206 zcmV;<05Sh~0i}<-N(4a=MUCexD%)tKYpePNBEn*5<_}bN)i@i>w6rbz`;M<%FuN}f z+}hUlGJrhYjBW;u5lczR&hlInIgPnQAGNw*HB@BJsl+tBO1Eu*5Steavq>rHh`avk0-)}GnQG&8Al05GG{O}FfcPQQAjKKV#Ms+PV JoB-JMTjB{mWX1ph literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/4e/70a6b06fc62481f80fbb74327849e7170eebff b/tests/resources/merge-recursive/.gitted/objects/4e/70a6b06fc62481f80fbb74327849e7170eebff new file mode 100644 index 0000000000000000000000000000000000000000..1dfcec50bbd97451a545c4c11b1be3e1d637d061 GIT binary patch literal 207 zcmV;=05Jb}0V^p=O;s>5GG{O}FfcPQQAjKOO?0vKod_BCz|3M8g6!ELqmCq zdO)ntJ6c@sx0STDHsW2)q9;7tK)oFg_?5|Js-p8GnQi0zTB`auCpnM|Zo~l->)HyG zLD8yGInV@&F65~7mZWz!6@KpptSX{2)${g z05IySK!m21{ZK$@DR-Sv#Wut9!kUQWWZ^dVP7E%}bAlMHwM|13N2a=uh^L{+Ch@!; zG^ey}Nt`F7Ow~#a!yL=bNOnmvZtb;GIggbBSTRiznbt967iJea0{2oiW5sK2Z^dYg zxV6l|HFb~(b4Kha*tlQ0Cc9t(nQLl#gZkXlV{7!IV1#Q5F=N(J%XP+N$ifUAH%B#F7cGo*eO^H#FeR=*=%e`qr0I-=FuYHp literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/75/c653822173a8e5795153ec3773dfe44bb9bb63 b/tests/resources/merge-recursive/.gitted/objects/75/c653822173a8e5795153ec3773dfe44bb9bb63 new file mode 100644 index 0000000000000000000000000000000000000000..1495f70f4bfee18f37f71850b0fcbd5b8b0f723b GIT binary patch literal 206 zcmV;<05Sh~0i}<-N(C_xhOPH0raRS`zn6ib#2=%AalsGcizF-v2)Xr9_NPr6Ei(pe>V80!RfCTPH@>rgVJTM>;2hJ I9~XmgJZE)kP5=M^ literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/81/5b5a1c80ca749d705c7aa0cb294a00cbedd340 b/tests/resources/merge-recursive/.gitted/objects/81/5b5a1c80ca749d705c7aa0cb294a00cbedd340 new file mode 100644 index 0000000000000000000000000000000000000000..12eb0662ae04224d99b15e0e5232c198f22be9d7 GIT binary patch literal 170 zcmV;b09F5Z0i}*h3IZ_@L|x|;eSwjDI_V6E2;vRAK$7WT7MVzlczs9l2JWg}LGeuUTZ}rc(ycKWeq1o zWR}c`G0rhMBf@jsT8GQ>3Vng=t<^_c;lLaHq!WLKU)!fvkDw5(pS4v4lSC=SMmO2P Yf8L1NmXb>fqihOgh4ZAv8v-^`V*1rhTmS$7 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/89/8d12687fb35be271c27c795a6b32c8b51da79e b/tests/resources/merge-recursive/.gitted/objects/89/8d12687fb35be271c27c795a6b32c8b51da79e new file mode 100644 index 0000000000000000000000000000000000000000..2ce4f7f0a4c72bf27a73631283d2ad87f508e7ba GIT binary patch literal 663 zcmV;I0%-ks0Zo)abJH*og*oe2EO(QcmSaviq(f(zrnD(N%l6vVSeA@d#+YBvTO|Q* zjV!I+``%M)A8We1yTAYN{do9Fucx=?oiWdEXL@`(pXfl(r!$?uyd018?d|Y#ex=g` zy&ulUmx?}93@!$tX2~Rz^}eFh)6vKrW9Sx7v7_4CW~7w$5+m)DV{>dy>&j*kEGQSb;Jq z+A7TBKrDy+M8M=&>{UqhN$<3NfQ=spBT28L~1%$Bk1# z^J8%s5_m1WP%6#H0UFJ!!8A*1J@QjtNE_~V^biwrYX*xx&=wb(>{j|@sg1wEIk}mk zc(OT)aiOBlB|(yQRPWbnfEk(+q*9h>9MFKvz!S)nG^peCuYVWJ052z> z)$oauY4vAj5ZuwbexGc6748HFHF~8I==~!Z2;5Wc=Saqhz{hVWc1O1`>fOaRWjh%^z&2iu=paO|$?2 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/ad/2ace9e15f66b3d1138922e6ffdc3ea3f967fa6 b/tests/resources/merge-recursive/.gitted/objects/ad/2ace9e15f66b3d1138922e6ffdc3ea3f967fa6 new file mode 100644 index 0000000000000000000000000000000000000000..8ae3ba5a744f2a3f167491861e15ec70c7ba69f5 GIT binary patch literal 170 zcmV;b09F5Z0i}+?3c@fDL_Oy#@&n3dlQb!a2;$M3Kd{~1Vh?SkM*MxF_y@uqX5PRs zT;_SI7Gv1dRn;;K0x47H1ep;zB2#3AK!dPwWOf;QHFsKdsTM}+lmwG^Lod!}8r5g^ zzT-Y&Qi2GWC>eUzTUqT{UbKq6-pc$ai`{FZA9vJm@k=`{^TE0hV(u|Uuv-WKrqOn` Y>Yp>_Qe+w@raH9?O{c9hZ%Q&#vn`5F+W-In literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/c0/bd078a61d2cc22c52ca5ce04abdcdc5cc1829e b/tests/resources/merge-recursive/.gitted/objects/c0/bd078a61d2cc22c52ca5ce04abdcdc5cc1829e new file mode 100644 index 0000000000000000000000000000000000000000..3dde6c243e93aec666ae3ef6a209106eb9e07e14 GIT binary patch literal 207 zcmV;=05Jb}0V^p=O;s>5GG{O}FfcPQQAjKNiI}Dm+wE8I^5xVyo=( Jc>u|AT#}r9UuXaT literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchC-1 b/tests/resources/merge-recursive/.gitted/refs/heads/branchC-1 new file mode 100644 index 0000000000000000000000000000000000000000..346b039b497e04072fdeb1e843f0547252be167c GIT binary patch literal 41 ucmV~$!4Uu;2m`Rc+W=>kaS+=5M=+`JY9?(9crj*i)18o}gB3~~71js-JqyPG literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchC-2 b/tests/resources/merge-recursive/.gitted/refs/heads/branchC-2 new file mode 100644 index 0000000000000000000000000000000000000000..67f3153f52a2c4fba8fc2cccc44499e448f0b046 GIT binary patch literal 41 ucmcC8G)*#1G)%TINKQ02u}m>HFikd3Of*PNGO{#DGyu}6DJjM#23!E_Pzyf* literal 0 HcmV?d00001 From a200bcf72838488c1550b1709a3f075f722e0244 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 26 Oct 2015 17:25:42 -0400 Subject: [PATCH 05/17] merge: add a third-level recursive merge --- tests/merge/trees/recursive.c | 46 ++++++++++++++++++ .../00/7f1ee2af8e5d99906867c4237510e1790a89b8 | Bin 0 -> 169 bytes .../15/faa0c9991f2d65686e844651faa2ff9827887b | Bin 0 -> 665 bytes .../4d/fc1be85a9d6c9898152444d32b238b4aecf8cc | Bin 0 -> 168 bytes .../50/e4facaafb746cfed89287206274193c1417288 | Bin 0 -> 207 bytes .../5e/8747f5200fac0f945a07daf6163ca9cb1a8da9 | Bin 0 -> 672 bytes .../5f/18576d464946eb2338daeb8b4030019961f505 | Bin 0 -> 208 bytes .../ad/1ea02c2cc4f55c1dff87b80a086206a73885eb | Bin 0 -> 207 bytes .../ca/49d1a8b6116ffeba22667bba265fa5261df7ab | Bin 0 -> 208 bytes .../e1/dcfc3038be54195a59817c89782b261e46cb05 | Bin 0 -> 212 bytes .../f1/b44c04989a3a1c14b036cfadfa328d53a7bc5e | Bin 0 -> 672 bytes .../.gitted/refs/heads/branchD-1 | Bin 0 -> 41 bytes .../.gitted/refs/heads/branchD-2 | Bin 0 -> 41 bytes 13 files changed, 46 insertions(+) create mode 100644 tests/resources/merge-recursive/.gitted/objects/00/7f1ee2af8e5d99906867c4237510e1790a89b8 create mode 100644 tests/resources/merge-recursive/.gitted/objects/15/faa0c9991f2d65686e844651faa2ff9827887b create mode 100644 tests/resources/merge-recursive/.gitted/objects/4d/fc1be85a9d6c9898152444d32b238b4aecf8cc create mode 100644 tests/resources/merge-recursive/.gitted/objects/50/e4facaafb746cfed89287206274193c1417288 create mode 100644 tests/resources/merge-recursive/.gitted/objects/5e/8747f5200fac0f945a07daf6163ca9cb1a8da9 create mode 100644 tests/resources/merge-recursive/.gitted/objects/5f/18576d464946eb2338daeb8b4030019961f505 create mode 100644 tests/resources/merge-recursive/.gitted/objects/ad/1ea02c2cc4f55c1dff87b80a086206a73885eb create mode 100644 tests/resources/merge-recursive/.gitted/objects/ca/49d1a8b6116ffeba22667bba265fa5261df7ab create mode 100644 tests/resources/merge-recursive/.gitted/objects/e1/dcfc3038be54195a59817c89782b261e46cb05 create mode 100644 tests/resources/merge-recursive/.gitted/objects/f1/b44c04989a3a1c14b036cfadfa328d53a7bc5e create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchD-1 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchD-2 diff --git a/tests/merge/trees/recursive.c b/tests/merge/trees/recursive.c index a7358e7e3..cd879677f 100644 --- a/tests/merge/trees/recursive.c +++ b/tests/merge/trees/recursive.c @@ -154,3 +154,49 @@ void test_merge_trees_recursive__three_norecursive(void) git_index_free(index); } +void test_merge_trees_recursive__four(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "d55e5dc038c52f1a36548625bcb666cbc06db9e6", 0, "veal.txt" }, + }; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchD-2", "branchD-1", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 6)); + + git_index_free(index); +} + +void test_merge_trees_recursive__four_norecursive(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "898d12687fb35be271c27c795a6b32c8b51da79e", 1, "veal.txt" }, + { 0100644, "f1b44c04989a3a1c14b036cfadfa328d53a7bc5e", 2, "veal.txt" }, + { 0100644, "5e8747f5200fac0f945a07daf6163ca9cb1a8da9", 3, "veal.txt" }, + }; + + opts.flags |= GIT_MERGE_NO_RECURSIVE; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchD-2", "branchD-1", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 8)); + + git_index_free(index); +} + diff --git a/tests/resources/merge-recursive/.gitted/objects/00/7f1ee2af8e5d99906867c4237510e1790a89b8 b/tests/resources/merge-recursive/.gitted/objects/00/7f1ee2af8e5d99906867c4237510e1790a89b8 new file mode 100644 index 0000000000000000000000000000000000000000..d9399d71c227358546c7b4c9f7a02f01b31fe31a GIT binary patch literal 169 zcmV;a09OBa0i{k!3IZ_@^gOS~2S&1VX8{pGJbLp3SvpJ(naCLN`$q8xLLF+OsMu;P zok@gU--sAyVbSOW8XRZ}QYo7}1si}X&V_SYWaK#A{YGnNBvQ;#ab*J`2!|e>6((9| ztPD~M0v*HX`)6O;#xCjQx5REstBRC0;FmvLd>Jj>|~U}8~$%7#e^ literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/15/faa0c9991f2d65686e844651faa2ff9827887b b/tests/resources/merge-recursive/.gitted/objects/15/faa0c9991f2d65686e844651faa2ff9827887b new file mode 100644 index 0000000000000000000000000000000000000000..54cd6f26ebd11798f73ecd010880bbaa79b46ac1 GIT binary patch literal 665 zcmV;K0%rYq0Zo)abJH*og*oe2EO(QcmSaviq(f(zrnD(N%l6vVSeA@d#+YBvTO|Q* zv7}wS_q|nWA8We1yTAYN{do9Fucx=?oiWdEXL@`(pXfl(r!$?uyd018?d|Y#ex=g` zy&ulUmx?}93@!$tX2~Rz^}eFh)6vKrW9Sx7v7_4CW~70DrJM0F^qlsT?Z^~Sjz08H6$D*;luKjRmHj@k z6(-lg;${S$d`rm*Lx%RT)H`3m^f9*7;5gb$?$?C?#HoO6YtNqwMgd0yrJaXG=uI01 zfKgusA~bF6#{x=Ax$lK)wi%vR)71JD%X%jG6WLGR8b4^WeP@g+`?2LXCjBrgMX3SdZxXG9dS(%~Z#;KtB zu{bmdyq398D$U3N8qKP~G)rnd@>5<&8}4`X5EF8128(&1EiN?Kt<009HvR_Zu1=g^D_t1WDRayobo6It5Zuwb?oYP83U`9SO{JP?Q6U$TCA0F*VC^zbG5Bpqhk#Z#F~8I==~LNlF6$@t$me|db>MGGVSkT;MBOo2 z9i&#f-iQFBAmlR05LD7Sh?tVI-f`s4NN&*1&S~=Oj*Yes0o4)(I&Xw9DUnAhjj?{P z(FwIQW5J?l`0Q(KaEUK$5pHWOkGjEuM*2}F`W8R8549XYD5c$^=4FA2E6&+S$JtJQ W&ai8ZIpu&oj|&6mNw7CPgj3meM@@$S literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/50/e4facaafb746cfed89287206274193c1417288 b/tests/resources/merge-recursive/.gitted/objects/50/e4facaafb746cfed89287206274193c1417288 new file mode 100644 index 0000000000000000000000000000000000000000..b1eaee5572fc754d31eb4fd30360ab4a6d75c181 GIT binary patch literal 207 zcmV;=05Jb}0V^p=O;s>5GG{O}FfcPQQAjKF)01=Xc+ahp+TFAo z@=c>7)Irl)p&vV%A=9|zrCw7UjFZ+sS=;KrwxX(ZQ`Wnl!=92JnLNtThyJO8pv_0Q z)OTIk?*r?|WI9+}RYWJ-QZSJrL;7gyjV)k$?^|kc9Bn4^Ya;-0A|UD7@`r*kf}?`c z&cY(}hLs$^h_3<>npU=B0VSo}_mOJW37!|Wa2He1aGM4b6)s9SK#bJtwx#GNre^Sn zr=?kkXnEaBPGQ@MKF>&+>XllCIgXWz$ppc;wULB5ALhLBmxL>&jyEOKNh1_}tM$r{tqxgllp>Vb(&&O~Pcv zg&8_-oC=yB*`SHzrObs;X-0O?s1^yP$)UB#Pk141xZlwiACOx!Xv_nxKGUSvGEbUX z{~MfxnHh>FoqSZrRn(afk)$5Q`*k$H43pwwB`h(>Km#rVPasp$ppKWn{*6-uye!Bu z;C09ZjxZRW^-m9u_<6quQpwZ=K6i!GA&152D!hgs4{^3OyHH`E_T0z1w1#Up-z4`;| Ggp305AV|0V^p=O;s>5GG{O}FfcPQQAjKsMr4E8`L(}{dV`nm Ki30$}rCe1lgkm%R literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/ad/1ea02c2cc4f55c1dff87b80a086206a73885eb b/tests/resources/merge-recursive/.gitted/objects/ad/1ea02c2cc4f55c1dff87b80a086206a73885eb new file mode 100644 index 0000000000000000000000000000000000000000..99207a9dd65bf2aafc27ac58179a678b7b07084a GIT binary patch literal 207 zcmV;=05Jb}0V^p=O;s>5GG{O}FfcPQQAjK>zkO(%F|N4 JD*?MaTYLMiW3vDN literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/ca/49d1a8b6116ffeba22667bba265fa5261df7ab b/tests/resources/merge-recursive/.gitted/objects/ca/49d1a8b6116ffeba22667bba265fa5261df7ab new file mode 100644 index 0000000000000000000000000000000000000000..1ea596763d7fab7757478d282f14a88fe220af89 GIT binary patch literal 208 zcmV;>05AV|0i}<-P6aUxM5*^H+}-M;IB{MQLP&^`jvw$k4ttB;pb*6G6J9+MmB(l7 zkw)6SUj{huu0~e{ZI$Np z4^~61MVzv$ImF80_dcOtJ);it;0ik=U(7xYx`?E z;6^9?RCoGi{A}0K_FF(ApE6nWa5iMjGU+Tg^q(=yqxNTo?=(35wZaK5$7ry2K4iN; KP0{LLBbw~kpoumm^+sLx0m=Bqli{S9BIXjc z=SZY^u^CCvDWy2nzj-Q_Sh5&jLs(of#?1#-Lal|JkgGYwN4SX+mu@j-s_-C5{ literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/f1/b44c04989a3a1c14b036cfadfa328d53a7bc5e b/tests/resources/merge-recursive/.gitted/objects/f1/b44c04989a3a1c14b036cfadfa328d53a7bc5e new file mode 100644 index 0000000000000000000000000000000000000000..7cbaaeecf596e2fa780fe9255822559fc9527259 GIT binary patch literal 672 zcmV;R0$=@j0Zo)okJB&^#X0*^4A&}DT9CN()I(Rh651}iT{t_*B(dVy!G8$h)APn@ zfm>sH#_#>!xV7~)-Q9is{O;T7_=R52Z_j(Bp5HF?_;fkbk)F>Nx;(s`PW1Kd_;Pur z^F4h(UQRC+eIoCScafT$C{Ehiiq20b6=&~Vmo52@YO9-(W}asbH2dsYZY$ERrL=fC z5VcJeEhY`yN}x0ZW)-bzILZmj+R>n=1AZkkiE3{w#l*Tbb}dzd&mkTtj%LCE<(o!F zD1)N4LO*siL!xoXOTDHz7$>cNvWDjW+ls2vOXf;J!JQr~rD zzYnYF?(akQDtuZ;l2iGZYQ%O48H2#yL$I}3}@ z8&+}vBfbhmXj<8h1(cL>-$$xhCwN|15{W5jxJ`qJ3KyjuAVz9++fwusQ!{wP)6%R% zw7ec9r?72BpJ${@^-3+n9LGw+|D2m`>sX$C5=IH=G+f_H$oRB3k9ek5UGewR+)f)Xb(cw&6xH40Mz literal 0 HcmV?d00001 From 99d9d9a470ca9b693f6dbee05f1cfcd98a5d148d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 26 Oct 2015 17:44:36 -0400 Subject: [PATCH 06/17] merge: improve test names in recursive merge tests --- tests/merge/trees/recursive.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/merge/trees/recursive.c b/tests/merge/trees/recursive.c index cd879677f..bff5d7e39 100644 --- a/tests/merge/trees/recursive.c +++ b/tests/merge/trees/recursive.c @@ -18,7 +18,7 @@ void test_merge_trees_recursive__cleanup(void) cl_git_sandbox_cleanup(); } -void test_merge_trees_recursive__one(void) +void test_merge_trees_recursive__one_base_commit(void) { git_index *index; git_merge_options opts = GIT_MERGE_OPTIONS_INIT; @@ -39,7 +39,7 @@ void test_merge_trees_recursive__one(void) git_index_free(index); } -void test_merge_trees_recursive__one_norecursive(void) +void test_merge_trees_recursive__one_base_commit_norecursive(void) { git_index *index; git_merge_options opts = GIT_MERGE_OPTIONS_INIT; @@ -62,7 +62,7 @@ void test_merge_trees_recursive__one_norecursive(void) git_index_free(index); } -void test_merge_trees_recursive__two(void) +void test_merge_trees_recursive__two_base_commits(void) { git_index *index; git_merge_options opts = GIT_MERGE_OPTIONS_INIT; @@ -83,7 +83,7 @@ void test_merge_trees_recursive__two(void) git_index_free(index); } -void test_merge_trees_recursive__two_norecursive(void) +void test_merge_trees_recursive__two_base_commits_norecursive(void) { git_index *index; git_merge_options opts = GIT_MERGE_OPTIONS_INIT; @@ -108,7 +108,7 @@ void test_merge_trees_recursive__two_norecursive(void) git_index_free(index); } -void test_merge_trees_recursive__three(void) +void test_merge_trees_recursive__two_levels_of_multiple_bases(void) { git_index *index; git_merge_options opts = GIT_MERGE_OPTIONS_INIT; @@ -129,7 +129,7 @@ void test_merge_trees_recursive__three(void) git_index_free(index); } -void test_merge_trees_recursive__three_norecursive(void) +void test_merge_trees_recursive__two_levels_of_multiple_bases_norecursive(void) { git_index *index; git_merge_options opts = GIT_MERGE_OPTIONS_INIT; @@ -154,7 +154,7 @@ void test_merge_trees_recursive__three_norecursive(void) git_index_free(index); } -void test_merge_trees_recursive__four(void) +void test_merge_trees_recursive__three_levels_of_multiple_bases(void) { git_index *index; git_merge_options opts = GIT_MERGE_OPTIONS_INIT; @@ -175,7 +175,7 @@ void test_merge_trees_recursive__four(void) git_index_free(index); } -void test_merge_trees_recursive__four_norecursive(void) +void test_merge_trees_recursive__three_levels_of_multiple_bases_norecursive(void) { git_index *index; git_merge_options opts = GIT_MERGE_OPTIONS_INIT; From fccad82ee8f431e06097b3a1282228b40ae7128f Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 27 Oct 2015 14:23:35 -0500 Subject: [PATCH 07/17] merge: add recursive test with three merge bases --- tests/merge/trees/recursive.c | 46 ++++++++++++++++++ .../06/db153c36829fc656e05cdf5a3bf7183f3c10aa | Bin 0 -> 272 bytes .../0e/8126647ec607f0a14122cec4b15315d790c8ff | Bin 0 -> 208 bytes .../1c/1bdb80c04233d1a9b9755913ee233987be6175 | Bin 0 -> 208 bytes .../1e/8dff96faaaa24f84943d2d9601dde61cb0398a | Bin 0 -> 268 bytes .../43/6ea75c99f527e4b42fddb46abedf7726eb719d | Bin 0 -> 173 bytes .../5a/ba269b3be41fc8db38068d3948c8af543fe609 | Bin 0 -> 208 bytes .../73/b20c8e09fa2726d69ff66969186014165da3c3 | Bin 0 -> 208 bytes .../7e/3056f6765b3044ab09701077dbe1eb5b0e9ad0 | Bin 0 -> 208 bytes .../8a/bda8de114a93f2d3c5a975ee2960f31e24be58 | Bin 0 -> 169 bytes .../96/23368f0fc562d6d840372ae17dc4cc32d51a80 | Bin 0 -> 172 bytes .../9a/e63b4a8ce0f181b2d1d098971733a103226917 | Bin 0 -> 240 bytes .../9b/258ad4c39f40c24f66bf1faf48eb6202d59c85 | Bin 0 -> 240 bytes .../9e/12bce04446d097ae1782967a5888c2e2a0d35b | Bin 0 -> 268 bytes .../a2/8c21c90aa36580641b345011869d1a899a6783 | Bin 0 -> 239 bytes .../ad/98bfa4679fb00b89207a0a11b8bbf91a3e4de9 | Bin 0 -> 208 bytes .../bd/97980c22d122509cdd915fd9788d56c8d3ae20 | Bin 0 -> 163 bytes .../ca/224bba0a8a24f1768804fe5f565b1014af7ef2 | Bin 0 -> 170 bytes .../d2/682aaf9594080ce877b5eeee110850fd6e3480 | Bin 0 -> 272 bytes .../d8/dd349b78f19a4ebe3357bacb8138f00bf5ed41 | Bin 0 -> 277 bytes .../d8/e05a90b3c2240d71a20c2502c937d9b7d22777 | Bin 0 -> 272 bytes .../da/b7b53383a1fec46632e60a1d847ce4f9ae14f2 | Bin 0 -> 208 bytes .../e2/d185fa827d58134cea20b9e1df893833c6560e | Bin 0 -> 208 bytes .../e5/0fbbd701458757bdfe9815f58ed717c588d1b5 | Bin 0 -> 268 bytes .../f1/72517a8cf39e009ffff541ee52429b89e418f3 | Bin 0 -> 268 bytes .../.gitted/refs/heads/branchE-1 | Bin 0 -> 41 bytes .../.gitted/refs/heads/branchE-2 | Bin 0 -> 41 bytes .../.gitted/refs/heads/branchE-3 | Bin 0 -> 41 bytes 28 files changed, 46 insertions(+) create mode 100644 tests/resources/merge-recursive/.gitted/objects/06/db153c36829fc656e05cdf5a3bf7183f3c10aa create mode 100644 tests/resources/merge-recursive/.gitted/objects/0e/8126647ec607f0a14122cec4b15315d790c8ff create mode 100644 tests/resources/merge-recursive/.gitted/objects/1c/1bdb80c04233d1a9b9755913ee233987be6175 create mode 100644 tests/resources/merge-recursive/.gitted/objects/1e/8dff96faaaa24f84943d2d9601dde61cb0398a create mode 100644 tests/resources/merge-recursive/.gitted/objects/43/6ea75c99f527e4b42fddb46abedf7726eb719d create mode 100644 tests/resources/merge-recursive/.gitted/objects/5a/ba269b3be41fc8db38068d3948c8af543fe609 create mode 100644 tests/resources/merge-recursive/.gitted/objects/73/b20c8e09fa2726d69ff66969186014165da3c3 create mode 100644 tests/resources/merge-recursive/.gitted/objects/7e/3056f6765b3044ab09701077dbe1eb5b0e9ad0 create mode 100644 tests/resources/merge-recursive/.gitted/objects/8a/bda8de114a93f2d3c5a975ee2960f31e24be58 create mode 100644 tests/resources/merge-recursive/.gitted/objects/96/23368f0fc562d6d840372ae17dc4cc32d51a80 create mode 100644 tests/resources/merge-recursive/.gitted/objects/9a/e63b4a8ce0f181b2d1d098971733a103226917 create mode 100644 tests/resources/merge-recursive/.gitted/objects/9b/258ad4c39f40c24f66bf1faf48eb6202d59c85 create mode 100644 tests/resources/merge-recursive/.gitted/objects/9e/12bce04446d097ae1782967a5888c2e2a0d35b create mode 100644 tests/resources/merge-recursive/.gitted/objects/a2/8c21c90aa36580641b345011869d1a899a6783 create mode 100644 tests/resources/merge-recursive/.gitted/objects/ad/98bfa4679fb00b89207a0a11b8bbf91a3e4de9 create mode 100644 tests/resources/merge-recursive/.gitted/objects/bd/97980c22d122509cdd915fd9788d56c8d3ae20 create mode 100644 tests/resources/merge-recursive/.gitted/objects/ca/224bba0a8a24f1768804fe5f565b1014af7ef2 create mode 100644 tests/resources/merge-recursive/.gitted/objects/d2/682aaf9594080ce877b5eeee110850fd6e3480 create mode 100644 tests/resources/merge-recursive/.gitted/objects/d8/dd349b78f19a4ebe3357bacb8138f00bf5ed41 create mode 100644 tests/resources/merge-recursive/.gitted/objects/d8/e05a90b3c2240d71a20c2502c937d9b7d22777 create mode 100644 tests/resources/merge-recursive/.gitted/objects/da/b7b53383a1fec46632e60a1d847ce4f9ae14f2 create mode 100644 tests/resources/merge-recursive/.gitted/objects/e2/d185fa827d58134cea20b9e1df893833c6560e create mode 100644 tests/resources/merge-recursive/.gitted/objects/e5/0fbbd701458757bdfe9815f58ed717c588d1b5 create mode 100644 tests/resources/merge-recursive/.gitted/objects/f1/72517a8cf39e009ffff541ee52429b89e418f3 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchE-1 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchE-2 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchE-3 diff --git a/tests/merge/trees/recursive.c b/tests/merge/trees/recursive.c index bff5d7e39..46effa5c2 100644 --- a/tests/merge/trees/recursive.c +++ b/tests/merge/trees/recursive.c @@ -200,3 +200,49 @@ void test_merge_trees_recursive__three_levels_of_multiple_bases_norecursive(void git_index_free(index); } +void test_merge_trees_recursive__three_base_commits(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4f7269b07c76d02755d75ccaf05c0b4c36cdc6c", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "a7b066537e6be7109abfe4ff97b675d4e077da20", 0, "veal.txt" }, + }; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchE-1", "branchE-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 6)); + + git_index_free(index); +} + +void test_merge_trees_recursive__three_base_commits_norecursive(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "9e12bce04446d097ae1782967a5888c2e2a0d35b", 1, "gravy.txt" }, + { 0100644, "d8dd349b78f19a4ebe3357bacb8138f00bf5ed41", 2, "gravy.txt" }, + { 0100644, "e50fbbd701458757bdfe9815f58ed717c588d1b5", 3, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "a7b066537e6be7109abfe4ff97b675d4e077da20", 0, "veal.txt" }, + }; + + opts.flags |= GIT_MERGE_NO_RECURSIVE; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchE-1", "branchE-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 8)); + + git_index_free(index); +} + diff --git a/tests/resources/merge-recursive/.gitted/objects/06/db153c36829fc656e05cdf5a3bf7183f3c10aa b/tests/resources/merge-recursive/.gitted/objects/06/db153c36829fc656e05cdf5a3bf7183f3c10aa new file mode 100644 index 0000000000000000000000000000000000000000..85887e0f532f756c021a17fed77a7e867fe9d146 GIT binary patch literal 272 zcmV+r0q_2J0VPnoZo@zf>wI6q4@iOnor+GGiY|R6DUeaNW&42h$vDX|^7qv_n?O<| zr6x&(m)GZ~_uu2+6{oMu_aTILHgFt9!z@eg6w;#=D#}Pq84Yv4->;-2qM_X|${iBj zD-bj8vXn53?JzGJU?W3mVkd{fUF2*EQuI==aiedkEb|U)wDEztKKxvcpXZPBwRTv^ zxa?4)dPzyvO*R*4SruI@+!|M|dXgP*vO@0b0ik;PP-GcK5H#|QA6Clc=DiFqsJD2+ zRw0XdsR5G|u6{X~kk){vFm?6JXm7ApVALeu>nxJBUsCNlE$U%1p(RsyUSmq2t^05AV|0V^p=O;s>5GG{O}FfcPQQAjK*bF-)ZbitUz~A8-NutKB~y;hfT}7>P0RtSS-v4HxGwv-z^wgG{!ialdgVd+ KEd>DYnqMw)Z)Roy literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/1c/1bdb80c04233d1a9b9755913ee233987be6175 b/tests/resources/merge-recursive/.gitted/objects/1c/1bdb80c04233d1a9b9755913ee233987be6175 new file mode 100644 index 0000000000000000000000000000000000000000..a2146496decf282eba468c692c6f7e10bf64d1c0 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKTiU*U#^-LkMR!aGYktDm4!Z8PN+BWhADIj(I$tHqsf<(C--K0g3Jn zh#7aOC9GmctaS%$W+*M} zHA+gd?XtB<&#D+=;oi7$&6DgIS1aVc9uS(h4@K%UgP@Ub{IF6kH}7R|LA%8h_6k|d zOHEj$aP!N-gtP^8g=uJKMtg^C0;4YRNmr4qV@<8=Qq{v`K~JXcyv3A2!vG3n%#1P7 S&7TDG?e-h5cL@L5MT~_s`-Tqy literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/43/6ea75c99f527e4b42fddb46abedf7726eb719d b/tests/resources/merge-recursive/.gitted/objects/43/6ea75c99f527e4b42fddb46abedf7726eb719d new file mode 100644 index 0000000000000000000000000000000000000000..e8825d867a2b797bf5a0039671e9419b80c200cf GIT binary patch literal 173 zcmV;e08;;W0i}*hY6CG4M6=c@bODEMsr3V6yqRTozCgRx!^~nvW-OEIM+v!sp%zuI zpeSkEwsz|Ree^@sf@X9vQc{VKW?&?APE_cQ!DFbYfaG~L4?cA7mR%NyQh?dVkRcM@ zJq19_u~g(-3dfYa;a6YUVW;}dN42-5ZO^vbvkv;}uKHK}r%!3y#UfG2CHR!=2?)Rp bI?i@|bH;qNy3VU`U&n=^>Ez50Hyu$ygu7Sn literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/5a/ba269b3be41fc8db38068d3948c8af543fe609 b/tests/resources/merge-recursive/.gitted/objects/5a/ba269b3be41fc8db38068d3948c8af543fe609 new file mode 100644 index 0000000000000000000000000000000000000000..85bc8f569e855cbf01f67de58f490d51f7e8b5f8 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKP}<4`%GqoWfxRYer0h< zY7xZ7_43CZ>Tj;SFV484ZsWk8T$lY^VAlR8|EF&&z4D;^ KmI45u^05AV|0V^p=O;s>5GG{O}FfcPQQAjKTj;SFV484ZsWk8T$lY^VAlR8|EF&&z4D;^ KmI443F<*?<6J%rn literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/7e/3056f6765b3044ab09701077dbe1eb5b0e9ad0 b/tests/resources/merge-recursive/.gitted/objects/7e/3056f6765b3044ab09701077dbe1eb5b0e9ad0 new file mode 100644 index 0000000000000000000000000000000000000000..c4b8355186272c1eb916727bae0a16c6ad75a545 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKgOR@qzp6TSus({L12z z)FOzD>*bF-)ZbitUz~A8-NutKB~y;hfT}7>P0RtSS-v4HxGwv-z^wgG{!ialdgVd+ KEd>AsJzr5;MP&d0 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/8a/bda8de114a93f2d3c5a975ee2960f31e24be58 b/tests/resources/merge-recursive/.gitted/objects/8a/bda8de114a93f2d3c5a975ee2960f31e24be58 new file mode 100644 index 0000000000000000000000000000000000000000..a03624d8162248d98931d06f6a3f8e82907f58c1 GIT binary patch literal 169 zcmV;a09OBa0i{km3IZ_{w9YAVftCF80wOkB+IfNO%L|(#8(AY>-zeTdm|{N6FxYA> zohxe&eJA3ik_4M0D4#4yZIGf8OCXst1PxlFvrZ7Z$DOv$J^CesrQjjUQAJ^$%U-CY zaPi)`B_Je|S$y`j?R-wJxF>#FTYa>RpJ=!rcA;J=1) zb=ykk%D|yFBA!BY(P-^;keLvy)rzbLGI?-Fkmo=WvSRnpXz$#ii`g5RozF5!kHT1+ zolr?(bk5p1qfd}oc=ok6zNA-ZiQm?`J?hR+H0Z}&=v(~K5$ks562SP`NCSKlAOst9 aobB}I47=7;a>3BcxG=O#ioF5MBU3vdf>!DP literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/9a/e63b4a8ce0f181b2d1d098971733a103226917 b/tests/resources/merge-recursive/.gitted/objects/9a/e63b4a8ce0f181b2d1d098971733a103226917 new file mode 100644 index 0000000000000000000000000000000000000000..0cbd00d539ac5fd660de5c73b1558663e690bc6f GIT binary patch literal 240 zcmVVPQ*YAg{gCj>9$&Adwya|2+?dw#|1oN4@;2*WrMgr0Tws_-Fx5r z5=9_JG4{E}-YbvAk3Q$=HMg>KzTx%E9=*e7$S6zMHLNytMp%EDpWsqhj znEQ^IEtkd?)d_xlDHLPj4!z|f9nB7SV z^oUNWdgejjw)3)vlfCO|;px0gmt_ujzSGb2;9tYF-L_@A513MB$;dGrAps0K-Jh}f qKhF%0zCL@XtIqB0mvHz_rz0JL&i2>iA-v4nay3s!96kWmDSDv#$acp7 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/9b/258ad4c39f40c24f66bf1faf48eb6202d59c85 b/tests/resources/merge-recursive/.gitted/objects/9b/258ad4c39f40c24f66bf1faf48eb6202d59c85 new file mode 100644 index 0000000000000000000000000000000000000000..305e1f3e92c78d686d7e067ced299cfdb8a3b3ee GIT binary patch literal 240 zcmV_5Q>b2+>?g#|wDZUhaxyQ3&Go2|q`D5}p0c zc%*Ud^L*Z1On9@cW=@o;G>LiQRsaey!XzNx7b>N(mtawihgVr`*&InxAvN!#aA>HZ zCgCZWA!lg88^&UZF8-oCF+oLCkC=d~D*M!SOr$AS(jbO#@pHxyGBs#5Wz?(`AxtRd zC#|v8fSSAz4D!C6`s$AQA*;IQQ=i}Z;_hvyU(=&~3%}cK?el~4F(%@KF}njqfMKWm qGdBBY%TiU*U#^-QwV1^aGYktDm4!Z8PN+BWhADIj(I#DH_{o=(C--K0g3Jn zh#7aOC9GlxtaS%$W+*M}FLD0xIepo4&oA)xfpxxpLdxb3K zr6w#=xcTK^LfQhl!ZfrqqrJm6fl-(EsH;fUv8L8_sp?^}peIvz-eO9iVE~0OX2zK4 S=1+q8cKeOjdk+8Yk&Keol8Ar+ literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/a2/8c21c90aa36580641b345011869d1a899a6783 b/tests/resources/merge-recursive/.gitted/objects/a2/8c21c90aa36580641b345011869d1a899a6783 new file mode 100644 index 0000000000000000000000000000000000000000..91ffb4b88e6e674b9ac108f9833d90c2b6fa0d9c GIT binary patch literal 239 zcmV_5Q>b2+>?g#|wDZUhaxyQ3&Go34d3gL}!09 z9%)?rJfAlg6W(mAnGS9jD8S=BwC`ux@xcW*oWnjY<2_}y-6pC6o$F%c(3?+y?FhMn%u p*zBJ%!;`Hq=6=%Lcx~nJ?s9T%>(QN;t-G?yQcuSN4xbL0i(#MRb<_X= literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/ad/98bfa4679fb00b89207a0a11b8bbf91a3e4de9 b/tests/resources/merge-recursive/.gitted/objects/ad/98bfa4679fb00b89207a0a11b8bbf91a3e4de9 new file mode 100644 index 0000000000000000000000000000000000000000..457f9da1f1bc3fc5daa3c7f492f9fb2685f6700c GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKTj;SFV484ZsWk8T$lY^VAlR8|EF&&z4D;^ KmI44|zFlT3oMPwz literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/bd/97980c22d122509cdd915fd9788d56c8d3ae20 b/tests/resources/merge-recursive/.gitted/objects/bd/97980c22d122509cdd915fd9788d56c8d3ae20 new file mode 100644 index 0000000000000000000000000000000000000000..71295e07145cb9dbc13de764cd77335bdc1c0983 GIT binary patch literal 163 zcmV;U09^lg0i{pL4FVw)^-L8sFy_O+2NGjU%yeJ_ET4=A27?&e7ncsay(M`|tfgE# zm&)#XBjRQb5~3w=*-Ilaq01T3p%WHCD1kcpInM0n8*QDNXhOD{oUvIXVIye7Y(OR% zgE5G~MVnM+{?XUk_>!K!C4O0Jxz~*!XsB;=qL1-o`&i473#GJm8l2=4C;&FpF}Bm6 RG3@+3J^GhPuov*HPsMvROWptg literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/ca/224bba0a8a24f1768804fe5f565b1014af7ef2 b/tests/resources/merge-recursive/.gitted/objects/ca/224bba0a8a24f1768804fe5f565b1014af7ef2 new file mode 100644 index 0000000000000000000000000000000000000000..0dd861f2c43e7f10a1ccbaf4ad794e9b7bac5091 GIT binary patch literal 170 zcmV;b09F5Z0i}*j3c@fHgk9$pxj^N;{5Bxsrb~BT;3avbU9^!H@%l#b2Er_6zJXy< z*|xPwWzC^gX6adjb+hx%Mh(VLgx~?e`y3fL+6WvdgSb=Wy~#lAbTl+3h8ahUDr1H) z29I8ALeNUNfL_qEEv3pSzo=$;Tgvt*yF78HA9vwz@k_^4wzEWI>=>-JP7YuIM5q01 Y<3DG_wd8eP6ScKp=$Zx;Z>2v`!Lnvk6951J literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/d2/682aaf9594080ce877b5eeee110850fd6e3480 b/tests/resources/merge-recursive/.gitted/objects/d2/682aaf9594080ce877b5eeee110850fd6e3480 new file mode 100644 index 0000000000000000000000000000000000000000..c79a3bb0f929cebff178786097b6685093bcaaa6 GIT binary patch literal 272 zcmV+r0q_2J0VPnoZo@zf>wI6q?nzLfQ_(3?(50^=1v1LE93OB#87DbL{=PbA6G)1r z)Ff%}`u6g4_}%|qaQr%dKZkH&1IO!Nm}JhKLVC19MHz`Hqhap1+l6#MG_)&5xkI9R z1!Bfs<`O2c4W@YoY+xvj?Bum@7de}P6ulIz+~8X(^R&SdZFpd=4?pMq=jr2gsT~$F zE*sRSUQ&`}l}$xjRz(*Jx5kyLo@6^5t&sbAK&ak66q&CB2paju4=d$z^IirQ)LT4Z zt&qjM)D@!?u6{X~kk){vFm?6JXz#E^VALeu>Lil2pHuBR&gx+@q9s#zUSdk1t^5lYGkOc6D6x7#hG1H7SGHHs|) z-HYHO?lLDgiES~>t6&2|Y2AlPuv(6uVj)v<6NEgha;-54_C6Ynq=+=5Y+RHA5qHbmbnah zpxlxhR)i>)p?Zvxxa37=LRt#y#MG8Ey}iR0fl(cJr;|w3ZVrWYoHduph=xpa^5R1P bwJpeXJ~FyMxBMhn-Y&n%cpLW*MV5+%UnhpR literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/d8/e05a90b3c2240d71a20c2502c937d9b7d22777 b/tests/resources/merge-recursive/.gitted/objects/d8/e05a90b3c2240d71a20c2502c937d9b7d22777 new file mode 100644 index 0000000000000000000000000000000000000000..b157ba17c290d5451ce52c7be2dc01fa691a2806 GIT binary patch literal 272 zcmV+r0q_2J0VPnoZo@zf>wI6q>`76eQ_(3?(50^=1v1LE93OB#87DbL{=PbA6G)1r z)Ff%}`u6g4_}%|qaQr%dZ$db*f#Y>BOfu(AAw625qKw3p(J=SB-9kDb8rl`3+#%7u z0x{z*a|x5!7Sp@}HZYV%cJf-di=0hCie3s!$HasxbhoAHQ^Yn4L)D8<7 zmn~{kFDc2g%BCVMtD=jATjR=APqJqmt&sbAK&ak66q&CB2paju4=d$z^IirQ)LT4Z zt&qjM)D@!?u6{X~kk){vFm?6JXz#E^VALeu=_Hc1pHuBR&gx+@q9s#zUSdk1t^05AV|0V^p=O;s>5GG{O}FfcPQQAjK$0B<%-a9t|MYF8S00q# KQUCxBQe1Jq@?@z1 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/e2/d185fa827d58134cea20b9e1df893833c6560e b/tests/resources/merge-recursive/.gitted/objects/e2/d185fa827d58134cea20b9e1df893833c6560e new file mode 100644 index 0000000000000000000000000000000000000000..fc80c08515319eca869719cabe8f50ddee61f8f9 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjK*bF-)ZbitUz~A8-NutKB~y;hfT}7>P0RtSS-v4HxGwv-z^wgG{!ialdgVd+ KEd>C}tX{rBZ(}Y1 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/e5/0fbbd701458757bdfe9815f58ed717c588d1b5 b/tests/resources/merge-recursive/.gitted/objects/e5/0fbbd701458757bdfe9815f58ed717c588d1b5 new file mode 100644 index 0000000000000000000000000000000000000000..96467c1066d719f545dd1762c1fdd254e3262d27 GIT binary patch literal 268 zcmV+n0rUQN0VPl|Zp1JQ>+Dys``w{Hr=nA*qDz58uR}*AQ4#}=6Xcs}o>GoqnCFvTiU*U#^-=Mc_p;5f~ORcam-GNKnM%1BHZ9rJiRZlp7!q2Dpe0}|aE z5Hs#lOIXDYSnCeh%urg`$*J%VIh%qMqZI7i>{}{zJz$GAKQPyaze?Gn-CKu^jLQKn zYLt{@+huE!o>ei#!o6|hnkU%_S1aVc9uS(h4@K%UgP@Ub{IF6kH}7R|LA%8h_6k|d zOHEj$aP!N-gtP^8g=uJKMtg^C0;4YRQCE?yV@<8=Qq{v`K~JXcyv3A2!vG3n%#1P7 S&7TDG?e-h5cMAX7UyPDbtcA4z literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchE-1 b/tests/resources/merge-recursive/.gitted/refs/heads/branchE-1 new file mode 100644 index 0000000000000000000000000000000000000000..b8d011e2d58d7a0b6fe2f91ba3e44d03ce95df09 GIT binary patch literal 41 ucmV~$!4Uu;2m`Rc(?Ab|b&5y#AHn1ih#4B22zlLZ3vDWIj++NnE1VDTEDId~ literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchE-2 b/tests/resources/merge-recursive/.gitted/refs/heads/branchE-2 new file mode 100644 index 0000000000000000000000000000000000000000..5e1e1acd9a317fed388ba990f28596ae35a2b4e4 GIT binary patch literal 41 ucmV~$!4Uu;2m`Rc+lWYyaln@SM= Date: Tue, 27 Oct 2015 14:24:51 -0500 Subject: [PATCH 08/17] merge: compute octopus merge bases --- src/merge.c | 191 +++++++++++++++++++++++++++------------------------- 1 file changed, 101 insertions(+), 90 deletions(-) diff --git a/src/merge.c b/src/merge.c index 05ca3d0ec..0a837b5f4 100644 --- a/src/merge.c +++ b/src/merge.c @@ -1923,83 +1923,41 @@ done: return error; } -#define INSERT_VIRTUAL_BASE_PARENT(commit, parent_id) \ - do { \ - id = git_array_alloc(commit->parent_ids); \ - GITERR_CHECK_ALLOC(id); \ - git_oid_cpy(id, parent_id); \ +static int merge_trees_with_heads( + git_index **out, + git_repository *repo, + const git_tree *ours, + const git_tree *theirs, + const git_oid heads[], + size_t heads_len, + const git_merge_options *opts); + +#define INSERT_ID(_ar, _id) do { \ + git_oid *_alloced = git_array_alloc(_ar); \ + GITERR_CHECK_ALLOC(_alloced); \ + git_oid_cpy(_alloced, _id); \ } while(0) -static int build_virtual_base( - git_commit **out, - git_repository *repo, - const git_commit *one, - bool one_is_virtual, - const git_oid *two_id) -{ - git_commit *two = NULL, *result; - git_index *index = NULL; - git_oid tree_id, *id; - int error; - - /* TODO: propagate merge options */ - if ((error = git_commit_lookup(&two, repo, two_id)) < 0 || - (error = git_merge_commits(&index, repo, one, two, NULL)) < 0) - goto done; - - if ((error = git_index_write_tree_to(&tree_id, index, repo)) < 0) - goto done; - - if ((result = git__calloc(1, sizeof(git_commit))) == NULL) - goto done; - - result->object.repo = repo; - - /* if the initial commit we were given is virtual, we are octopus - * merging - that virtual base's parents should actually be the - * parents that we use for our new virtual commit. otherwise, it - * is an actual parent. - */ - if (one_is_virtual) { - size_t i, cnt = git_commit_parentcount(one); - - for (i = 0; i < cnt; i++) - INSERT_VIRTUAL_BASE_PARENT(result, git_commit_parent_id(one, i)); - } else { - INSERT_VIRTUAL_BASE_PARENT(result, git_commit_id(one)); - } - - INSERT_VIRTUAL_BASE_PARENT(result, two_id); - - git_oid_cpy(&result->tree_id, &tree_id); - - *out = result; - -done: - git_index_free(index); - git_commit_free(two); - return error; -} - -#undef INSERT_VIRTUAL_BASE_PARENT - -static int compute_base_tree( +static int compute_base( git_tree **out, git_repository *repo, - const git_commit *our_commit, - const git_commit *their_commit, - bool recursive) + const git_oid heads[], + size_t heads_len, + const git_merge_options *opts) { - git_commit_list *base_list; - git_revwalk *walk; - git_commit *base = NULL; - bool base_virtual = false; + git_commit_list *base_list = NULL; + git_revwalk *walk = NULL; + git_commit *base_commit = NULL, *next_commit = NULL; + git_tree *base_tree = NULL, *next_tree = NULL; + git_array_t(git_oid) base_ids = GIT_ARRAY_INIT; + git_index *index = NULL; + bool recursive = !opts || (opts->flags & GIT_MERGE_NO_RECURSIVE) == 0; int error = 0; *out = NULL; - if ((error = merge_bases(&base_list, &walk, repo, - git_commit_id(our_commit), git_commit_id(their_commit))) < 0) + if ((error = merge_bases_many(&base_list, &walk, repo, + heads_len, heads)) < 0) return error; if (error == GIT_ENOTFOUND) { @@ -2008,29 +1966,88 @@ static int compute_base_tree( goto done; } - if ((error = git_commit_lookup(&base, repo, &base_list->item->oid)) < 0) + if ((error = git_commit_lookup(&base_commit, repo, + &base_list->item->oid)) < 0 || + (error = git_commit_tree(&base_tree, base_commit)) < 0) goto done; + INSERT_ID(base_ids, git_commit_id(base_commit)); + while (recursive && base_list->next) { - git_commit *new_base; + git_tree *new_tree; + git_oid new_tree_id; base_list = base_list->next; - if ((error = build_virtual_base(&new_base, repo, base, base_virtual, - &base_list->item->oid)) < 0) + if ((error = git_commit_lookup(&next_commit, repo, + &base_list->item->oid)) < 0 || + (error = git_commit_tree(&next_tree, next_commit)) < 0) goto done; - git_commit_free(base); - base = new_base; - base_virtual = true; + INSERT_ID(base_ids, git_commit_id(next_commit)); + + if ((error = merge_trees_with_heads(&index, repo, base_tree, + next_tree, base_ids.ptr, base_ids.size, opts)) < 0) + goto done; + + /* TODO: conflicts!! */ + + if ((error = git_index_write_tree_to(&new_tree_id, index, repo)) < 0 || + (error = git_tree_lookup(&new_tree, repo, &new_tree_id)) < 0) + goto done; + + git_index_free(index); + index = NULL; + + git_tree_free(next_tree); + next_tree = NULL; + + git_commit_free(next_commit); + next_commit = NULL; + + git_tree_free(base_tree); + base_tree = new_tree; } - error = git_commit_tree(out, base); + *out = base_tree; + base_tree = NULL; done: - git_commit_free(base); + git_index_free(index); + git_tree_free(next_tree); + git_tree_free(base_tree); + git_commit_free(next_commit); + git_commit_free(base_commit); git_commit_list_free(&base_list); git_revwalk_free(walk); + git_array_clear(base_ids); + + return error; +} + +static int merge_trees_with_heads( + git_index **out, + git_repository *repo, + const git_tree *ours, + const git_tree *theirs, + const git_oid heads[], + size_t heads_len, + const git_merge_options *opts) +{ + git_tree *ancestor = NULL; + int error = 0; + + if ((error = compute_base(&ancestor, repo, heads, heads_len, opts)) < 0) { + if (error == GIT_ENOTFOUND) + giterr_clear(); + else + goto done; + } + + error = git_merge_trees(out, repo, ancestor, ours, theirs, opts); + +done: + git_tree_free(ancestor); return error; } @@ -2042,30 +2059,24 @@ int git_merge_commits( const git_commit *their_commit, const git_merge_options *opts) { - git_tree *our_tree = NULL, *their_tree = NULL, *ancestor_tree = NULL; - bool recursive; + git_tree *our_tree = NULL, *their_tree = NULL; + git_oid heads[2]; int error = 0; - recursive = !opts || (opts->flags & GIT_MERGE_NO_RECURSIVE) == 0; + *out = NULL; - if ((error = compute_base_tree(&ancestor_tree, repo, - our_commit, their_commit, recursive)) < 0) { - - if (error == GIT_ENOTFOUND) - giterr_clear(); - else - goto done; - } + git_oid_cpy(&heads[0], git_commit_id(our_commit)); + git_oid_cpy(&heads[1], git_commit_id(their_commit)); if ((error = git_commit_tree(&our_tree, our_commit)) < 0 || (error = git_commit_tree(&their_tree, their_commit)) < 0 || - (error = git_merge_trees(out, repo, ancestor_tree, our_tree, their_tree, opts)) < 0) + (error = merge_trees_with_heads(out, repo, our_tree, their_tree, + heads, 2, opts)) < 0) goto done; done: git_tree_free(our_tree); git_tree_free(their_tree); - git_tree_free(ancestor_tree); return error; } From b1eef912cffb9e3ce9792b6aee816c1a45c85fb0 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 27 Oct 2015 18:00:30 -0500 Subject: [PATCH 09/17] merge: add recursive test with conflicting contents --- tests/merge/trees/recursive.c | 23 ++++++++++++++++++ .../21/950d5e4e4d1a871b4dfcf72ecb6b9c162c434e | Bin 0 -> 670 bytes .../38/55170cef875708da06ab9ad7fc6a73b531cda1 | Bin 0 -> 664 bytes .../5b/8e1e56cb99e8b99ac22eec8aebf6422ecd08c0 | Bin 0 -> 208 bytes .../78/3d6539dde96b8873c5b5da3e79cc14cd64830b | Bin 0 -> 176 bytes .../ca/7d316d6d9af99d2481e980d68b77e572d80fe7 | Bin 0 -> 207 bytes .../ef/1783444b61a8671beea4ce1f4d0202677dfbfb | Bin 0 -> 174 bytes .../.gitted/refs/heads/branchF-1 | Bin 0 -> 41 bytes .../.gitted/refs/heads/branchF-2 | Bin 0 -> 41 bytes 9 files changed, 23 insertions(+) create mode 100644 tests/resources/merge-recursive/.gitted/objects/21/950d5e4e4d1a871b4dfcf72ecb6b9c162c434e create mode 100644 tests/resources/merge-recursive/.gitted/objects/38/55170cef875708da06ab9ad7fc6a73b531cda1 create mode 100644 tests/resources/merge-recursive/.gitted/objects/5b/8e1e56cb99e8b99ac22eec8aebf6422ecd08c0 create mode 100644 tests/resources/merge-recursive/.gitted/objects/78/3d6539dde96b8873c5b5da3e79cc14cd64830b create mode 100644 tests/resources/merge-recursive/.gitted/objects/ca/7d316d6d9af99d2481e980d68b77e572d80fe7 create mode 100644 tests/resources/merge-recursive/.gitted/objects/ef/1783444b61a8671beea4ce1f4d0202677dfbfb create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchF-1 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchF-2 diff --git a/tests/merge/trees/recursive.c b/tests/merge/trees/recursive.c index 46effa5c2..abca01727 100644 --- a/tests/merge/trees/recursive.c +++ b/tests/merge/trees/recursive.c @@ -246,3 +246,26 @@ void test_merge_trees_recursive__three_base_commits_norecursive(void) git_index_free(index); } +void test_merge_trees_recursive__conflict(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "fa567f568ed72157c0c617438d077695b99d9aac", 1, "veal.txt" }, + { 0100644, "21950d5e4e4d1a871b4dfcf72ecb6b9c162c434e", 2, "veal.txt" }, + { 0100644, "3855170cef875708da06ab9ad7fc6a73b531cda1", 3, "veal.txt" }, + }; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchF-1", "branchF-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 8)); + + git_index_free(index); +} + diff --git a/tests/resources/merge-recursive/.gitted/objects/21/950d5e4e4d1a871b4dfcf72ecb6b9c162c434e b/tests/resources/merge-recursive/.gitted/objects/21/950d5e4e4d1a871b4dfcf72ecb6b9c162c434e new file mode 100644 index 0000000000000000000000000000000000000000..a87732611a38ea041d580d75e7e8b5a865babf96 GIT binary patch literal 670 zcmV;P0%84l0Zo*_Zrd;rM0@5}><738f&#txBtjIaa;d87*LRk( z+ukgRT+X~1y7IB2hlfv}KYTwOztZdZ?XoxK@^+=C=j)k{bU9z?`sL+xqHk} z)CFRF-qGT6zr9J@Xd~X$EV{z84b9_Ib1Zev7cgCn4b@nVF{Asn5r8-qkZtApW5FokXrQ$9un4_r zr2sJMt3ZUNmHkja=~nJKp^9yW=Y=&9$;rZP?wuGMl;;F7y4N-hNgSE#J|domCY!|b zdeEHG_DSMAA!VvoY8d8Nc1E&Gig6pSlgfI$DS#Ez6p?8iLv~?yp(AiFyJo!cy0^Dt zG)A0SdT>h}B*L5#J2q_GZ(NgI@B*1@YI=hD+|yHQ^r2vcYYH)=YpLZrqZzU=L&u#{ zLGxpF7!r6Xy-+IkzyTV~qQTU2YCQ5&UPv46_w*POa;tlbKF}Ix8tq#8WT}b2!8y5! zp?I`8ig95_txJL=?V#Ro)c`XzCCE-$qH#b2E~`6+lS~pTjvYJ>A^dv2aa!Qk z*z@>aZslV|4-X$dz59MTexaB1>t%1u<@HKWU$196(&c=m>*wdwiN3uapRX@;ex$eK z_4K@>+$Uy=!Nnj{&zVBZlw%|rt@k_Ju#qXo(9WJ>OO?0vKod_BCz|3M8g6!ELqmCq zS|HZv9W5^R+ezA181b%V(F)HtP;bWrer0l*s^~mPX4^Qwmaaa|Ne(1~8&P0lU0VS{ zAX*hN2buuYg&eitlJqX<=$~wX`Twzss!TIJhK|#LvK>Ge?U+OVPyx`!qb!YWTkgBW zR+wB1imMS!@(m>?3>Z4cQs;aTri-zm8s!)>x?h_D0H*-5tvr7yG75AwK-zjx1m3h# zfH2CdhzLw8`=JP>t=x4&726EX3#%iNlLgz{J26<4=L9g?Ynz57j!bnQVNXMoP2zby zs84CTk~mNBl&X~)2050Uk?fMnxQ*9Ir5-0mV3lc#@U)I0yD+=ZAs~Q(t{Ep@dwVNJ zZN%1+gPZG6BFq`KqhZtirfaeb4&b@ErW=&!o}OBxA4Nv6E@4E_TCOvaAqz8b+;u9_ z{Fohv1YSxmRF!(*0E}i)W9m6I9{#Cba2xFR^cWL-t9y$)&>CkN?OO6=sfoX#b8-^{ z@n~}tK^~{ZW0Y)t_Rf#PGOiPQZoKSt_YbPS`g{_yh4edM@68|Lp^zqDFGSh^ literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/5b/8e1e56cb99e8b99ac22eec8aebf6422ecd08c0 b/tests/resources/merge-recursive/.gitted/objects/5b/8e1e56cb99e8b99ac22eec8aebf6422ecd08c0 new file mode 100644 index 0000000000000000000000000000000000000000..c3e6d31ca217790364fa5f70e6111377525bf55b GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjK-wLp;;n{f K7XkpfJzPUFfMJ;c literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/78/3d6539dde96b8873c5b5da3e79cc14cd64830b b/tests/resources/merge-recursive/.gitted/objects/78/3d6539dde96b8873c5b5da3e79cc14cd64830b new file mode 100644 index 0000000000000000000000000000000000000000..e2f34d6bb2585aa9fc7a1df8d940733bedae26d4 GIT binary patch literal 176 zcmV;h08jsT0i};?3c@fDg#DdU>;)=$G%pYlL{H!aHrb6W*hXr^>s!Se_;2PL7-n*v zrm=x`a?=)O$mq!^M~)(v7)kd*aSW1NNZzycnu09s#T^%(8=&dgqH={XC6dNibjBc3 z3R?Lbi=l)zkicgf>H;Tv;X-g3>h!2H?0BUgb>MICbK6{}J*d97F*qX?bka&GR=SRD e{AZ0g*16oq+{XC|OzZvE*akRvTD$=tv{mv^x>e2q literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/ca/7d316d6d9af99d2481e980d68b77e572d80fe7 b/tests/resources/merge-recursive/.gitted/objects/ca/7d316d6d9af99d2481e980d68b77e572d80fe7 new file mode 100644 index 0000000000000000000000000000000000000000..0733fa232bf68c48a5dc822e57159816e07198d7 GIT binary patch literal 207 zcmV;=05Jb}0V^p=O;s>5GG{O}FfcPQQAjKl?)z_%qA{hM7=u zo+~ITH+5x(e)Npo+b|9T`vw%0Vh)~oOx83WqVz$EJFUD_a7v@cgky?YvTs)#!vHlq1CcTW~iCg`=cb(PU!0T^BEF=GZ8V*u6gMN(&VL literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchF-2 b/tests/resources/merge-recursive/.gitted/refs/heads/branchF-2 new file mode 100644 index 0000000000000000000000000000000000000000..abe2ea947d13454d75b588ed856abbb37615881f GIT binary patch literal 41 ucmV~$!4Uv31O&i;s&R6Ib_n_}A-l8ixFpMvVUC(fzQM9ZMa{jpw$2CY@C#W0 literal 0 HcmV?d00001 From 3f2bb387a43185991d7e077fa5e6c0bb467f2abc Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 28 Oct 2015 11:00:55 -0400 Subject: [PATCH 10/17] merge: octopus merge common ancestors when >2 When there are more than two common ancestors, continue merging the virtual base with the additional common ancestors, effectively octopus merging a new virtual base. --- src/annotated_commit.c | 21 +++ src/annotated_commit.h | 3 + src/merge.c | 286 ++++++++++++++++++++++++----------------- 3 files changed, 190 insertions(+), 120 deletions(-) diff --git a/src/annotated_commit.c b/src/annotated_commit.c index 3f2d2ed17..036e601c1 100644 --- a/src/annotated_commit.c +++ b/src/annotated_commit.c @@ -7,6 +7,7 @@ #include "common.h" #include "annotated_commit.h" +#include "refs.h" #include "git2/commit.h" #include "git2/refs.h" @@ -75,6 +76,26 @@ int git_annotated_commit_from_ref( return error; } +int git_annotated_commit_from_head( + git_annotated_commit **out, + git_repository *repo) +{ + git_reference *head; + int error; + + assert(out && repo); + + *out = NULL; + + if ((error = git_reference_lookup(&head, repo, GIT_HEAD_FILE)) < 0) + return -1; + + error = git_annotated_commit_from_ref(out, repo, head); + + git_reference_free(head); + return error; +} + int git_annotated_commit_lookup( git_annotated_commit **out, git_repository *repo, diff --git a/src/annotated_commit.h b/src/annotated_commit.h index e873184ae..37e3d9951 100644 --- a/src/annotated_commit.h +++ b/src/annotated_commit.h @@ -19,4 +19,7 @@ struct git_annotated_commit { char id_str[GIT_OID_HEXSZ+1]; }; +extern int git_annotated_commit_from_head(git_annotated_commit **out, + git_repository *repo); + #endif diff --git a/src/merge.c b/src/merge.c index 0a837b5f4..ce6f4a6ff 100644 --- a/src/merge.c +++ b/src/merge.c @@ -28,6 +28,7 @@ #include "oidarray.h" #include "annotated_commit.h" #include "commit.h" +#include "oidarray.h" #include "git2/types.h" #include "git2/repository.h" @@ -1925,6 +1926,7 @@ done: static int merge_trees_with_heads( git_index **out, + git_commit **base_commit_out, git_repository *repo, const git_tree *ours, const git_tree *theirs, @@ -1938,24 +1940,62 @@ static int merge_trees_with_heads( git_oid_cpy(_alloced, _id); \ } while(0) -static int compute_base( +static int create_virtual_base( git_tree **out, git_repository *repo, + git_tree *base_tree, + git_array_oid_t base_ids, + git_oid *next_commit_id, + const git_merge_options *opts) +{ + git_commit *next_commit = NULL, *intermediate_base = NULL; + git_tree *next_tree = NULL; + git_index *index = NULL; + git_oid new_tree_id; + int error; + + if ((error = git_commit_lookup(&next_commit, repo, next_commit_id)) < 0 || + (error = git_commit_tree(&next_tree, next_commit)) < 0) + goto done; + + INSERT_ID(base_ids, git_commit_id(next_commit)); + + if ((error = merge_trees_with_heads(&index, &intermediate_base, repo, + base_tree, next_tree, base_ids.ptr, base_ids.size, opts)) < 0) + goto done; + + /* TODO: conflicts!! */ + + if ((error = git_index_write_tree_to(&new_tree_id, index, repo)) < 0) + goto done; + + error = git_tree_lookup(out, repo, &new_tree_id); + +done: + git_index_free(index); + git_tree_free(next_tree); + git_commit_free(intermediate_base); + git_commit_free(next_commit); + + return error; +} + +static int compute_base( + git_tree **tree_out, + git_commit **commit_out, + git_repository *repo, const git_oid heads[], size_t heads_len, const git_merge_options *opts) { - git_commit_list *base_list = NULL; + git_commit_list *base_list = NULL, *base_iter; git_revwalk *walk = NULL; - git_commit *base_commit = NULL, *next_commit = NULL; + git_commit *base_commit = NULL; git_tree *base_tree = NULL, *next_tree = NULL; - git_array_t(git_oid) base_ids = GIT_ARRAY_INIT; - git_index *index = NULL; + git_array_oid_t base_ids = GIT_ARRAY_INIT; bool recursive = !opts || (opts->flags & GIT_MERGE_NO_RECURSIVE) == 0; int error = 0; - *out = NULL; - if ((error = merge_bases_many(&base_list, &walk, repo, heads_len, heads)) < 0) return error; @@ -1966,58 +2006,40 @@ static int compute_base( goto done; } + base_iter = base_list; + if ((error = git_commit_lookup(&base_commit, repo, - &base_list->item->oid)) < 0 || + &base_iter->item->oid)) < 0 || (error = git_commit_tree(&base_tree, base_commit)) < 0) goto done; INSERT_ID(base_ids, git_commit_id(base_commit)); - while (recursive && base_list->next) { - git_tree *new_tree; - git_oid new_tree_id; + while (recursive && base_iter->next) { + base_iter = base_iter->next; - base_list = base_list->next; - - if ((error = git_commit_lookup(&next_commit, repo, - &base_list->item->oid)) < 0 || - (error = git_commit_tree(&next_tree, next_commit)) < 0) + if ((error = create_virtual_base(&next_tree, repo, base_tree, + base_ids, &base_iter->item->oid, opts)) < 0) goto done; - INSERT_ID(base_ids, git_commit_id(next_commit)); - - if ((error = merge_trees_with_heads(&index, repo, base_tree, - next_tree, base_ids.ptr, base_ids.size, opts)) < 0) - goto done; - - /* TODO: conflicts!! */ - - if ((error = git_index_write_tree_to(&new_tree_id, index, repo)) < 0 || - (error = git_tree_lookup(&new_tree, repo, &new_tree_id)) < 0) - goto done; - - git_index_free(index); - index = NULL; - - git_tree_free(next_tree); - next_tree = NULL; - - git_commit_free(next_commit); - next_commit = NULL; - git_tree_free(base_tree); - base_tree = new_tree; + base_tree = next_tree; + next_tree = NULL; + + git_commit_free(base_commit); + base_commit = NULL; } - *out = base_tree; - base_tree = NULL; + *tree_out = base_tree; + *commit_out = base_commit; done: - git_index_free(index); + if (error < 0) { + git_tree_free(base_tree); + git_commit_free(base_commit); + } + git_tree_free(next_tree); - git_tree_free(base_tree); - git_commit_free(next_commit); - git_commit_free(base_commit); git_commit_list_free(&base_list); git_revwalk_free(walk); git_array_clear(base_ids); @@ -2025,35 +2047,52 @@ done: return error; } +#undef INSERT_ID + static int merge_trees_with_heads( git_index **out, + git_commit **base_out, git_repository *repo, - const git_tree *ours, - const git_tree *theirs, + const git_tree *our_tree, + const git_tree *their_tree, const git_oid heads[], size_t heads_len, const git_merge_options *opts) { - git_tree *ancestor = NULL; + git_commit *ancestor_commit = NULL; + git_tree *ancestor_tree = NULL; int error = 0; - if ((error = compute_base(&ancestor, repo, heads, heads_len, opts)) < 0) { + *out = NULL; + *base_out = NULL; + + if ((error = compute_base(&ancestor_tree, &ancestor_commit, repo, + heads, heads_len, opts)) < 0) { + if (error == GIT_ENOTFOUND) giterr_clear(); else goto done; } - error = git_merge_trees(out, repo, ancestor, ours, theirs, opts); + if ((error = git_merge_trees(out, + repo, ancestor_tree, our_tree, their_tree, opts)) < 0) + goto done; + + *base_out = ancestor_commit; done: - git_tree_free(ancestor); + if (error < 0) + git_commit_free(ancestor_commit); + + git_tree_free(ancestor_tree); return error; } -int git_merge_commits( +static int merge_commits( git_index **out, + git_commit **base_out, git_repository *repo, const git_commit *our_commit, const git_commit *their_commit, @@ -2070,8 +2109,8 @@ int git_merge_commits( if ((error = git_commit_tree(&our_tree, our_commit)) < 0 || (error = git_commit_tree(&their_tree, their_commit)) < 0 || - (error = merge_trees_with_heads(out, repo, our_tree, their_tree, - heads, 2, opts)) < 0) + (error = merge_trees_with_heads(out, base_out, repo, + our_tree, their_tree, heads, 2, opts)) < 0) goto done; done: @@ -2081,6 +2120,23 @@ done: return error; } +int git_merge_commits( + git_index **out, + git_repository *repo, + const git_commit *our_commit, + const git_commit *their_commit, + const git_merge_options *opts) +{ + git_commit *base_commit = NULL; + int error; + + error = merge_commits(out, &base_commit, repo, + our_commit, their_commit, opts); + + git_commit_free(base_commit); + return error; +} + /* Merge setup / cleanup */ static int write_merge_head( @@ -2511,49 +2567,51 @@ const char *merge_their_label(const char *branchname) } static int merge_normalize_checkout_opts( + git_checkout_options *out, git_repository *repo, - git_checkout_options *checkout_opts, const git_checkout_options *given_checkout_opts, - const git_annotated_commit *ancestor_head, + unsigned int checkout_strategy, + git_commit *ancestor_commit, const git_annotated_commit *our_head, - size_t their_heads_len, - const git_annotated_commit **their_heads) + const git_annotated_commit **their_heads, + size_t their_heads_len) { + git_checkout_options default_checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; int error = 0; GIT_UNUSED(repo); if (given_checkout_opts != NULL) - memcpy(checkout_opts, given_checkout_opts, sizeof(git_checkout_options)); - else { - git_checkout_options default_checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; - default_checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + memcpy(out, given_checkout_opts, sizeof(git_checkout_options)); + else + memcpy(out, &default_checkout_opts, sizeof(git_checkout_options)); - memcpy(checkout_opts, &default_checkout_opts, sizeof(git_checkout_options)); - } + out->checkout_strategy = checkout_strategy; - /* TODO: for multiple ancestors in merge-recursive, this is "merged common ancestors" */ - if (!checkout_opts->ancestor_label) { - if (ancestor_head && ancestor_head->commit) - checkout_opts->ancestor_label = git_commit_summary(ancestor_head->commit); + /* TODO: disambiguate between merged common ancestors and no common + * ancestor (although git.git does not!) + */ + if (!out->ancestor_label) { + if (ancestor_commit) + out->ancestor_label = git_commit_summary(ancestor_commit); else - checkout_opts->ancestor_label = "ancestor"; + out->ancestor_label = "merged common ancestors"; } - if (!checkout_opts->our_label) { + if (!out->our_label) { if (our_head && our_head->ref_name) - checkout_opts->our_label = our_head->ref_name; + out->our_label = our_head->ref_name; else - checkout_opts->our_label = "ours"; + out->our_label = "ours"; } - if (!checkout_opts->their_label) { + if (!out->their_label) { if (their_heads_len == 1 && their_heads[0]->ref_name) - checkout_opts->their_label = merge_their_label(their_heads[0]->ref_name); + out->their_label = merge_their_label(their_heads[0]->ref_name); else if (their_heads_len == 1) - checkout_opts->their_label = their_heads[0]->id_str; + out->their_label = their_heads[0]->id_str; else - checkout_opts->their_label = "theirs"; + out->their_label = "theirs"; } return error; @@ -2906,11 +2964,11 @@ int git_merge( { git_reference *our_ref = NULL; git_checkout_options checkout_opts; - git_annotated_commit *ancestor_head = NULL, *our_head = NULL; - git_tree *ancestor_tree = NULL, *our_tree = NULL, **their_trees = NULL; + git_annotated_commit *our_head = NULL; + git_commit *base_commit = NULL; git_index *index = NULL; git_indexwriter indexwriter = GIT_INDEXWRITER_INIT; - size_t i; + unsigned int checkout_strategy; int error = 0; assert(repo && their_heads); @@ -2920,61 +2978,49 @@ int git_merge( return -1; } - their_trees = git__calloc(their_heads_len, sizeof(git_tree *)); - GITERR_CHECK_ALLOC(their_trees); + if ((error = git_repository__ensure_not_bare(repo, "merge")) < 0) + goto done; - if ((error = merge_heads(&ancestor_head, &our_head, repo, their_heads, their_heads_len)) < 0 || - (error = merge_normalize_checkout_opts(repo, &checkout_opts, given_checkout_opts, - ancestor_head, our_head, their_heads_len, their_heads)) < 0 || - (error = git_indexwriter_init_for_operation(&indexwriter, repo, &checkout_opts.checkout_strategy)) < 0) - goto on_error; + checkout_strategy = given_checkout_opts ? + given_checkout_opts->checkout_strategy : + GIT_CHECKOUT_SAFE; - /* Write the merge files to the repository. */ - if ((error = git_merge__setup(repo, our_head, their_heads, their_heads_len)) < 0) - goto on_error; + if ((error = git_indexwriter_init_for_operation(&indexwriter, repo, + &checkout_strategy)) < 0) + goto done; - if (ancestor_head != NULL && - (error = git_commit_tree(&ancestor_tree, ancestor_head->commit)) < 0) - goto on_error; + /* Write the merge setup files to the repository. */ + if ((error = git_annotated_commit_from_head(&our_head, repo)) < 0 || + (error = git_merge__setup(repo, our_head, their_heads, + their_heads_len)) < 0) + goto done; - if ((error = git_commit_tree(&our_tree, our_head->commit)) < 0) - goto on_error; + /* TODO: octopus */ - for (i = 0; i < their_heads_len; i++) { - if ((error = git_commit_tree(&their_trees[i], their_heads[i]->commit)) < 0) - goto on_error; - } - - /* TODO: recursive, octopus, etc... */ - - if ((error = git_merge_trees(&index, repo, ancestor_tree, our_tree, their_trees[0], merge_opts)) < 0 || + if ((error = merge_commits(&index, &base_commit, repo, + our_head->commit, their_heads[0]->commit, merge_opts)) < 0 || (error = git_merge__check_result(repo, index)) < 0 || - (error = git_merge__append_conflicts_to_merge_msg(repo, index)) < 0 || - (error = git_checkout_index(repo, index, &checkout_opts)) < 0 || - (error = git_indexwriter_commit(&indexwriter)) < 0) - goto on_error; + (error = git_merge__append_conflicts_to_merge_msg(repo, index)) < 0) + goto done; - goto done; + /* check out the merge results */ -on_error: - merge_state_cleanup(repo); + if ((error = merge_normalize_checkout_opts(&checkout_opts, repo, + given_checkout_opts, checkout_strategy, + base_commit, our_head, their_heads, their_heads_len)) < 0 || + (error = git_checkout_index(repo, index, &checkout_opts)) < 0) + goto done; + + error = git_indexwriter_commit(&indexwriter); done: + if (error < 0) + merge_state_cleanup(repo); + git_indexwriter_cleanup(&indexwriter); - git_index_free(index); - - git_tree_free(ancestor_tree); - git_tree_free(our_tree); - - for (i = 0; i < their_heads_len; i++) - git_tree_free(their_trees[i]); - - git__free(their_trees); - git_annotated_commit_free(our_head); - git_annotated_commit_free(ancestor_head); - + git_commit_free(base_commit); git_reference_free(our_ref); return error; From 7730fe8e9cda1e160bff1e78dfa2a898799d4365 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 9 Nov 2015 13:01:48 -0500 Subject: [PATCH 11/17] merge: merge annotated commits instead of regular commits --- src/annotated_commit.c | 42 ++++-- src/annotated_commit.h | 2 + src/merge.c | 325 +++++++++++++++++++---------------------- 3 files changed, 181 insertions(+), 188 deletions(-) diff --git a/src/annotated_commit.c b/src/annotated_commit.c index 036e601c1..3998a1af1 100644 --- a/src/annotated_commit.c +++ b/src/annotated_commit.c @@ -8,6 +8,7 @@ #include "common.h" #include "annotated_commit.h" #include "refs.h" +#include "cache.h" #include "git2/commit.h" #include "git2/refs.h" @@ -23,14 +24,17 @@ static int annotated_commit_init( const char *remote_url) { git_annotated_commit *annotated_commit; + git_commit *commit = NULL; int error = 0; assert(out && id); *out = NULL; - annotated_commit = git__calloc(1, sizeof(git_annotated_commit)); - GITERR_CHECK_ALLOC(annotated_commit); + if ((error = git_commit_lookup(&commit, repo, id)) < 0 || + (error = git_annotated_commit_from_commit(&annotated_commit, + commit)) < 0) + goto done; if (ref_name) { annotated_commit->ref_name = git__strdup(ref_name); @@ -42,15 +46,10 @@ static int annotated_commit_init( GITERR_CHECK_ALLOC(annotated_commit->remote_url); } - git_oid_fmt(annotated_commit->id_str, id); - annotated_commit->id_str[GIT_OID_HEXSZ] = '\0'; - - if ((error = git_commit_lookup(&annotated_commit->commit, repo, id)) < 0) { - git_annotated_commit_free(annotated_commit); - return error; - } - *out = annotated_commit; + +done: + git_commit_free(commit); return error; } @@ -96,6 +95,29 @@ int git_annotated_commit_from_head( return error; } +int git_annotated_commit_from_commit( + git_annotated_commit **out, + git_commit *commit) +{ + git_annotated_commit *annotated_commit; + + assert(out && commit); + + *out = NULL; + + annotated_commit = git__calloc(1, sizeof(git_annotated_commit)); + GITERR_CHECK_ALLOC(annotated_commit); + + git_cached_obj_incref(commit); + annotated_commit->commit = commit; + + git_oid_fmt(annotated_commit->id_str, git_commit_id(commit)); + annotated_commit->id_str[GIT_OID_HEXSZ] = '\0'; + + *out = annotated_commit; + return 0; +} + int git_annotated_commit_lookup( git_annotated_commit **out, git_repository *repo, diff --git a/src/annotated_commit.h b/src/annotated_commit.h index 37e3d9951..9a041176e 100644 --- a/src/annotated_commit.h +++ b/src/annotated_commit.h @@ -21,5 +21,7 @@ struct git_annotated_commit { extern int git_annotated_commit_from_head(git_annotated_commit **out, git_repository *repo); +extern int git_annotated_commit_from_commit(git_annotated_commit **out, + git_commit *commit); #endif diff --git a/src/merge.c b/src/merge.c index ce6f4a6ff..59ac8e1ed 100644 --- a/src/merge.c +++ b/src/merge.c @@ -1924,202 +1924,166 @@ done: return error; } -static int merge_trees_with_heads( - git_index **out, - git_commit **base_commit_out, +static int merge_annotated_commits( + git_index **index_out, + git_annotated_commit **base_out, git_repository *repo, - const git_tree *ours, - const git_tree *theirs, - const git_oid heads[], - size_t heads_len, + const git_annotated_commit *our_commit, + const git_annotated_commit *their_commit, + size_t recursion_level, const git_merge_options *opts); -#define INSERT_ID(_ar, _id) do { \ - git_oid *_alloced = git_array_alloc(_ar); \ - GITERR_CHECK_ALLOC(_alloced); \ - git_oid_cpy(_alloced, _id); \ - } while(0) - static int create_virtual_base( - git_tree **out, + git_annotated_commit **out, git_repository *repo, - git_tree *base_tree, - git_array_oid_t base_ids, - git_oid *next_commit_id, - const git_merge_options *opts) + const git_annotated_commit *one, + const git_annotated_commit *two, + size_t recursion_level) { - git_commit *next_commit = NULL, *intermediate_base = NULL; - git_tree *next_tree = NULL; git_index *index = NULL; - git_oid new_tree_id; + git_tree *tree = NULL; + git_commit *commit = NULL; + git_oid id, tree_id; + const git_commit *parents[2]; + git_signature *signature = NULL; int error; - if ((error = git_commit_lookup(&next_commit, repo, next_commit_id)) < 0 || - (error = git_commit_tree(&next_tree, next_commit)) < 0) + parents[0] = one->commit; + parents[1] = two->commit; + + if ((error = merge_annotated_commits(&index, NULL, repo, one, two, + recursion_level + 1, NULL)) < 0 || + (error = git_index_write_tree_to(&tree_id, index, repo)) < 0 || + (error = git_tree_lookup(&tree, repo, &tree_id)) < 0 || + (error = git_signature_now(&signature, "Virtual", "virtual")) < 0 || + (error = git_commit_create(&id, repo, NULL, signature, signature, + NULL, "virtual merged tree", tree, 2, parents)) < 0 || + (error = git_commit_lookup(&commit, repo, &id)) < 0) goto done; - INSERT_ID(base_ids, git_commit_id(next_commit)); - - if ((error = merge_trees_with_heads(&index, &intermediate_base, repo, - base_tree, next_tree, base_ids.ptr, base_ids.size, opts)) < 0) - goto done; - - /* TODO: conflicts!! */ - - if ((error = git_index_write_tree_to(&new_tree_id, index, repo)) < 0) - goto done; - - error = git_tree_lookup(out, repo, &new_tree_id); + error = git_annotated_commit_from_commit(out, commit); done: + git_commit_free(commit); + git_tree_free(tree); git_index_free(index); - git_tree_free(next_tree); - git_commit_free(intermediate_base); - git_commit_free(next_commit); + git_signature_free(signature); return error; } +GIT_INLINE(int) insert_head_ids( + git_array_oid_t *ids, + const git_annotated_commit *annotated_commit) +{ + git_oid *id = git_array_alloc(*ids); + GITERR_CHECK_ALLOC(id); + + git_oid_cpy(id, git_commit_id(annotated_commit->commit)); + return 0; +} + static int compute_base( - git_tree **tree_out, - git_commit **commit_out, + git_annotated_commit **out, git_repository *repo, - const git_oid heads[], - size_t heads_len, - const git_merge_options *opts) + const git_annotated_commit *one, + const git_annotated_commit *two, + bool recurse, + size_t recursion_level) { - git_commit_list *base_list = NULL, *base_iter; - git_revwalk *walk = NULL; - git_commit *base_commit = NULL; - git_tree *base_tree = NULL, *next_tree = NULL; - git_array_oid_t base_ids = GIT_ARRAY_INIT; - bool recursive = !opts || (opts->flags & GIT_MERGE_NO_RECURSIVE) == 0; - int error = 0; - - if ((error = merge_bases_many(&base_list, &walk, repo, - heads_len, heads)) < 0) - return error; - - if (error == GIT_ENOTFOUND) { - giterr_clear(); - error = 0; - goto done; - } - - base_iter = base_list; - - if ((error = git_commit_lookup(&base_commit, repo, - &base_iter->item->oid)) < 0 || - (error = git_commit_tree(&base_tree, base_commit)) < 0) - goto done; - - INSERT_ID(base_ids, git_commit_id(base_commit)); - - while (recursive && base_iter->next) { - base_iter = base_iter->next; - - if ((error = create_virtual_base(&next_tree, repo, base_tree, - base_ids, &base_iter->item->oid, opts)) < 0) - goto done; - - git_tree_free(base_tree); - base_tree = next_tree; - next_tree = NULL; - - git_commit_free(base_commit); - base_commit = NULL; - } - - *tree_out = base_tree; - *commit_out = base_commit; - -done: - if (error < 0) { - git_tree_free(base_tree); - git_commit_free(base_commit); - } - - git_tree_free(next_tree); - git_commit_list_free(&base_list); - git_revwalk_free(walk); - git_array_clear(base_ids); - - return error; -} - -#undef INSERT_ID - -static int merge_trees_with_heads( - git_index **out, - git_commit **base_out, - git_repository *repo, - const git_tree *our_tree, - const git_tree *their_tree, - const git_oid heads[], - size_t heads_len, - const git_merge_options *opts) -{ - git_commit *ancestor_commit = NULL; - git_tree *ancestor_tree = NULL; - int error = 0; - - *out = NULL; - *base_out = NULL; - - if ((error = compute_base(&ancestor_tree, &ancestor_commit, repo, - heads, heads_len, opts)) < 0) { - - if (error == GIT_ENOTFOUND) - giterr_clear(); - else - goto done; - } - - if ((error = git_merge_trees(out, - repo, ancestor_tree, our_tree, their_tree, opts)) < 0) - goto done; - - *base_out = ancestor_commit; - -done: - if (error < 0) - git_commit_free(ancestor_commit); - - git_tree_free(ancestor_tree); - - return error; -} - -static int merge_commits( - git_index **out, - git_commit **base_out, - git_repository *repo, - const git_commit *our_commit, - const git_commit *their_commit, - const git_merge_options *opts) -{ - git_tree *our_tree = NULL, *their_tree = NULL; - git_oid heads[2]; - int error = 0; + git_array_oid_t head_ids = GIT_ARRAY_INIT; + git_oidarray bases = {0}; + git_annotated_commit *base = NULL, *other = NULL, *new_base = NULL; + size_t i; + int error; *out = NULL; - git_oid_cpy(&heads[0], git_commit_id(our_commit)); - git_oid_cpy(&heads[1], git_commit_id(their_commit)); - - if ((error = git_commit_tree(&our_tree, our_commit)) < 0 || - (error = git_commit_tree(&their_tree, their_commit)) < 0 || - (error = merge_trees_with_heads(out, base_out, repo, - our_tree, their_tree, heads, 2, opts)) < 0) + if ((error = insert_head_ids(&head_ids, one)) < 0 || + (error = insert_head_ids(&head_ids, two)) < 0) goto done; + if ((error = git_merge_bases_many(&bases, repo, + head_ids.size, head_ids.ptr)) < 0 || + (error = git_annotated_commit_lookup(&base, repo, &bases.ids[0])) < 0 || + !recurse) + goto done; + + for (i = 1; i < bases.count; i++) { + recursion_level++; + + if ((error = git_annotated_commit_lookup(&other, repo, + &bases.ids[i])) < 0 || + (error = create_virtual_base(&new_base, repo, base, other, + recursion_level)) < 0) + goto done; + + git_annotated_commit_free(base); + git_annotated_commit_free(other); + + base = new_base; + new_base = NULL; + other = NULL; + } + done: + if (error == 0) + *out = base; + else + git_annotated_commit_free(base); + + git_annotated_commit_free(other); + git_annotated_commit_free(new_base); + git_oidarray_free(&bases); + git_array_clear(head_ids); + return error; +} + +static int merge_annotated_commits( + git_index **index_out, + git_annotated_commit **base_out, + git_repository *repo, + const git_annotated_commit *our_commit, + const git_annotated_commit *their_commit, + size_t recursion_level, + const git_merge_options *opts) +{ + git_annotated_commit *base = NULL; + git_tree *base_tree = NULL, *our_tree = NULL, *their_tree = NULL; + bool recurse = !opts || !(opts->flags & GIT_MERGE_NO_RECURSIVE); + int error; + + if ((error = compute_base(&base, repo, our_commit, their_commit, + recurse, recursion_level)) < 0) { + + if (error != GIT_ENOTFOUND) + goto done; + + giterr_clear(); + } else if ((error = git_commit_tree(&base_tree, base->commit)) < 0) { + goto done; + } + + if ((error = git_commit_tree(&our_tree, our_commit->commit)) < 0 || + (error = git_commit_tree(&their_tree, their_commit->commit)) < 0 || + (error = git_merge_trees(index_out, repo, base_tree, our_tree, + their_tree, opts)) < 0) + goto done; + + if (base_out) { + *base_out = base; + base = NULL; + } + +done: + git_annotated_commit_free(base); git_tree_free(our_tree); git_tree_free(their_tree); - + git_tree_free(base_tree); return error; } + int git_merge_commits( git_index **out, git_repository *repo, @@ -2127,13 +2091,19 @@ int git_merge_commits( const git_commit *their_commit, const git_merge_options *opts) { - git_commit *base_commit = NULL; - int error; + git_annotated_commit *ours = NULL, *theirs = NULL, *base = NULL; + int error = 0; - error = merge_commits(out, &base_commit, repo, - our_commit, their_commit, opts); + if ((error = git_annotated_commit_from_commit(&ours, (git_commit *)our_commit)) < 0 || + (error = git_annotated_commit_from_commit(&theirs, (git_commit *)their_commit)) < 0) + goto done; - git_commit_free(base_commit); + error = merge_annotated_commits(out, &base, repo, ours, theirs, 0, opts); + +done: + git_annotated_commit_free(ours); + git_annotated_commit_free(theirs); + git_annotated_commit_free(base); return error; } @@ -2571,7 +2541,7 @@ static int merge_normalize_checkout_opts( git_repository *repo, const git_checkout_options *given_checkout_opts, unsigned int checkout_strategy, - git_commit *ancestor_commit, + git_annotated_commit *ancestor, const git_annotated_commit *our_head, const git_annotated_commit **their_heads, size_t their_heads_len) @@ -2592,8 +2562,8 @@ static int merge_normalize_checkout_opts( * ancestor (although git.git does not!) */ if (!out->ancestor_label) { - if (ancestor_commit) - out->ancestor_label = git_commit_summary(ancestor_commit); + if (ancestor) + out->ancestor_label = git_commit_summary(ancestor->commit); else out->ancestor_label = "merged common ancestors"; } @@ -2964,8 +2934,7 @@ int git_merge( { git_reference *our_ref = NULL; git_checkout_options checkout_opts; - git_annotated_commit *our_head = NULL; - git_commit *base_commit = NULL; + git_annotated_commit *our_head = NULL, *base = NULL; git_index *index = NULL; git_indexwriter indexwriter = GIT_INDEXWRITER_INIT; unsigned int checkout_strategy; @@ -2997,8 +2966,8 @@ int git_merge( /* TODO: octopus */ - if ((error = merge_commits(&index, &base_commit, repo, - our_head->commit, their_heads[0]->commit, merge_opts)) < 0 || + if ((error = merge_annotated_commits(&index, &base, repo, our_head, + their_heads[0], 0, merge_opts)) < 0 || (error = git_merge__check_result(repo, index)) < 0 || (error = git_merge__append_conflicts_to_merge_msg(repo, index)) < 0) goto done; @@ -3007,7 +2976,7 @@ int git_merge( if ((error = merge_normalize_checkout_opts(&checkout_opts, repo, given_checkout_opts, checkout_strategy, - base_commit, our_head, their_heads, their_heads_len)) < 0 || + base, our_head, their_heads, their_heads_len)) < 0 || (error = git_checkout_index(repo, index, &checkout_opts)) < 0) goto done; @@ -3020,7 +2989,7 @@ done: git_indexwriter_cleanup(&indexwriter); git_index_free(index); git_annotated_commit_free(our_head); - git_commit_free(base_commit); + git_annotated_commit_free(base); git_reference_free(our_ref); return error; From 76ade3a0b87e279935eba54be2485105396edb7f Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 10 Nov 2015 21:21:26 -0800 Subject: [PATCH 12/17] merge: use annotated commits for recursion Use annotated commits to act as our virtual bases, instead of regular commits, to avoid polluting the odb with virtual base commits and trees. Instead, build an annotated commit with an index and pointers to the commits that it was merged from. --- src/annotated_commit.c | 26 ++++--- src/annotated_commit.h | 22 +++++- src/merge.c | 154 ++++++++++++++++++++++++----------------- 3 files changed, 128 insertions(+), 74 deletions(-) diff --git a/src/annotated_commit.c b/src/annotated_commit.c index 3998a1af1..e53b95dee 100644 --- a/src/annotated_commit.c +++ b/src/annotated_commit.c @@ -15,6 +15,8 @@ #include "git2/repository.h" #include "git2/annotated_commit.h" #include "git2/revparse.h" +#include "git2/tree.h" +#include "git2/index.h" static int annotated_commit_init( git_annotated_commit **out, @@ -108,6 +110,8 @@ int git_annotated_commit_from_commit( annotated_commit = git__calloc(1, sizeof(git_annotated_commit)); GITERR_CHECK_ALLOC(annotated_commit); + annotated_commit->type = GIT_ANNOTATED_COMMIT_REAL; + git_cached_obj_incref(commit); annotated_commit->commit = commit; @@ -179,14 +183,20 @@ void git_annotated_commit_free(git_annotated_commit *annotated_commit) if (annotated_commit == NULL) return; - if (annotated_commit->commit != NULL) - git_commit_free(annotated_commit->commit); - - if (annotated_commit->ref_name != NULL) - git__free(annotated_commit->ref_name); - - if (annotated_commit->remote_url != NULL) - git__free(annotated_commit->remote_url); + switch (annotated_commit->type) { + case GIT_ANNOTATED_COMMIT_REAL: + git_commit_free(annotated_commit->commit); + git_tree_free(annotated_commit->tree); + git__free(annotated_commit->ref_name); + git__free(annotated_commit->remote_url); + break; + case GIT_ANNOTATED_COMMIT_VIRTUAL: + git_index_free(annotated_commit->index); + git_array_clear(annotated_commit->parents); + break; + default: + abort(); + } git__free(annotated_commit); } diff --git a/src/annotated_commit.h b/src/annotated_commit.h index 9a041176e..cbb88fd22 100644 --- a/src/annotated_commit.h +++ b/src/annotated_commit.h @@ -7,11 +7,31 @@ #ifndef INCLUDE_annotated_commit_h__ #define INCLUDE_annotated_commit_h__ +#include "oidarray.h" + #include "git2/oid.h" -/** Internal structure for merge inputs */ +typedef enum { + GIT_ANNOTATED_COMMIT_REAL = 1, + GIT_ANNOTATED_COMMIT_VIRTUAL = 2, +} git_annotated_commit_t; + +/** + * Internal structure for merge inputs. An annotated commit is generally + * "real" and backed by an actual commit in the repository, but merge will + * internally create "virtual" commits that are in-memory intermediate + * commits backed by an index. + */ struct git_annotated_commit { + git_annotated_commit_t type; + + /* real commit */ git_commit *commit; + git_tree *tree; + + /* virtual commit structure */ + git_index *index; + git_array_oid_t parents; char *ref_name; char *remote_url; diff --git a/src/merge.c b/src/merge.c index 59ac8e1ed..64c8f1116 100644 --- a/src/merge.c +++ b/src/merge.c @@ -1928,58 +1928,59 @@ static int merge_annotated_commits( git_index **index_out, git_annotated_commit **base_out, git_repository *repo, - const git_annotated_commit *our_commit, - const git_annotated_commit *their_commit, + git_annotated_commit *our_commit, + git_annotated_commit *their_commit, size_t recursion_level, const git_merge_options *opts); -static int create_virtual_base( - git_annotated_commit **out, - git_repository *repo, - const git_annotated_commit *one, - const git_annotated_commit *two, - size_t recursion_level) -{ - git_index *index = NULL; - git_tree *tree = NULL; - git_commit *commit = NULL; - git_oid id, tree_id; - const git_commit *parents[2]; - git_signature *signature = NULL; - int error; - - parents[0] = one->commit; - parents[1] = two->commit; - - if ((error = merge_annotated_commits(&index, NULL, repo, one, two, - recursion_level + 1, NULL)) < 0 || - (error = git_index_write_tree_to(&tree_id, index, repo)) < 0 || - (error = git_tree_lookup(&tree, repo, &tree_id)) < 0 || - (error = git_signature_now(&signature, "Virtual", "virtual")) < 0 || - (error = git_commit_create(&id, repo, NULL, signature, signature, - NULL, "virtual merged tree", tree, 2, parents)) < 0 || - (error = git_commit_lookup(&commit, repo, &id)) < 0) - goto done; - - error = git_annotated_commit_from_commit(out, commit); - -done: - git_commit_free(commit); - git_tree_free(tree); - git_index_free(index); - git_signature_free(signature); - - return error; -} - GIT_INLINE(int) insert_head_ids( git_array_oid_t *ids, const git_annotated_commit *annotated_commit) { - git_oid *id = git_array_alloc(*ids); - GITERR_CHECK_ALLOC(id); + git_oid *id; + size_t i; - git_oid_cpy(id, git_commit_id(annotated_commit->commit)); + if (annotated_commit->type == GIT_ANNOTATED_COMMIT_REAL) { + id = git_array_alloc(*ids); + GITERR_CHECK_ALLOC(id); + + git_oid_cpy(id, git_commit_id(annotated_commit->commit)); + } else { + for (i = 0; i < annotated_commit->parents.size; i++) { + id = git_array_alloc(*ids); + GITERR_CHECK_ALLOC(id); + + git_oid_cpy(id, &annotated_commit->parents.ptr[i]); + } + } + + return 0; +} + +static int create_virtual_base( + git_annotated_commit **out, + git_repository *repo, + git_annotated_commit *one, + git_annotated_commit *two, + size_t recursion_level) +{ + git_annotated_commit *result = NULL; + git_index *index = NULL; + + result = git__calloc(1, sizeof(git_annotated_commit)); + GITERR_CHECK_ALLOC(result); + + if ((merge_annotated_commits(&index, NULL, repo, one, two, + recursion_level + 1, NULL)) < 0) + return -1; + + result->type = GIT_ANNOTATED_COMMIT_VIRTUAL; + result->index = index; + + insert_head_ids(&result->parents, one); + insert_head_ids(&result->parents, two); + + *out = result; return 0; } @@ -2039,35 +2040,59 @@ done: return error; } +static int iterator_for_annotated_commit( + git_iterator **out, + git_annotated_commit *commit) +{ + git_iterator_options opts = GIT_ITERATOR_OPTIONS_INIT; + int error; + + opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE; + + if (commit == NULL) { + error = git_iterator_for_nothing(out, &opts); + } else if (commit->type == GIT_ANNOTATED_COMMIT_VIRTUAL) { + error = git_iterator_for_index(out, commit->index, &opts); + } else { + if (!commit->tree && + (error = git_commit_tree(&commit->tree, commit->commit)) < 0) + goto done; + + error = git_iterator_for_tree(out, commit->tree, &opts); + } + +done: + return error; +} + static int merge_annotated_commits( git_index **index_out, git_annotated_commit **base_out, git_repository *repo, - const git_annotated_commit *our_commit, - const git_annotated_commit *their_commit, + git_annotated_commit *ours, + git_annotated_commit *theirs, size_t recursion_level, const git_merge_options *opts) { git_annotated_commit *base = NULL; - git_tree *base_tree = NULL, *our_tree = NULL, *their_tree = NULL; + git_iterator *base_iter = NULL, *our_iter = NULL, *their_iter = NULL; bool recurse = !opts || !(opts->flags & GIT_MERGE_NO_RECURSIVE); int error; - if ((error = compute_base(&base, repo, our_commit, their_commit, - recurse, recursion_level)) < 0) { + if ((error = compute_base(&base, repo, ours, theirs, recurse, + recursion_level)) < 0) { if (error != GIT_ENOTFOUND) goto done; giterr_clear(); - } else if ((error = git_commit_tree(&base_tree, base->commit)) < 0) { - goto done; - } + } - if ((error = git_commit_tree(&our_tree, our_commit->commit)) < 0 || - (error = git_commit_tree(&their_tree, their_commit->commit)) < 0 || - (error = git_merge_trees(index_out, repo, base_tree, our_tree, - their_tree, opts)) < 0) + if ((error = iterator_for_annotated_commit(&base_iter, base)) < 0 || + (error = iterator_for_annotated_commit(&our_iter, ours)) < 0 || + (error = iterator_for_annotated_commit(&their_iter, theirs)) < 0 || + (error = git_merge__iterators(index_out, repo, base_iter, our_iter, + their_iter, opts)) < 0) goto done; if (base_out) { @@ -2077,9 +2102,9 @@ static int merge_annotated_commits( done: git_annotated_commit_free(base); - git_tree_free(our_tree); - git_tree_free(their_tree); - git_tree_free(base_tree); + git_iterator_free(base_iter); + git_iterator_free(our_iter); + git_iterator_free(their_iter); return error; } @@ -2558,14 +2583,13 @@ static int merge_normalize_checkout_opts( out->checkout_strategy = checkout_strategy; - /* TODO: disambiguate between merged common ancestors and no common - * ancestor (although git.git does not!) - */ if (!out->ancestor_label) { - if (ancestor) + if (ancestor && ancestor->type == GIT_ANNOTATED_COMMIT_REAL) out->ancestor_label = git_commit_summary(ancestor->commit); - else + else if (ancestor) out->ancestor_label = "merged common ancestors"; + else + out->ancestor_label = "empty base"; } if (!out->our_label) { @@ -2967,7 +2991,7 @@ int git_merge( /* TODO: octopus */ if ((error = merge_annotated_commits(&index, &base, repo, our_head, - their_heads[0], 0, merge_opts)) < 0 || + (git_annotated_commit *)their_heads[0], 0, merge_opts)) < 0 || (error = git_merge__check_result(repo, index)) < 0 || (error = git_merge__append_conflicts_to_merge_msg(repo, index)) < 0) goto done; From dcde5720424961f526e8c070b7d99191d7ef75c1 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 9 Nov 2015 08:23:27 -0500 Subject: [PATCH 13/17] merge tests: move expected data into own file --- tests/merge/conflict_data.h | 42 ++++++++++++++++++++++++++++++++++ tests/merge/files.c | 1 + tests/merge/merge_helpers.h | 43 ----------------------------------- tests/merge/trees/automerge.c | 3 ++- tests/merge/trees/commits.c | 1 + tests/merge/workdir/simple.c | 1 + 6 files changed, 47 insertions(+), 44 deletions(-) create mode 100644 tests/merge/conflict_data.h diff --git a/tests/merge/conflict_data.h b/tests/merge/conflict_data.h new file mode 100644 index 000000000..173892d95 --- /dev/null +++ b/tests/merge/conflict_data.h @@ -0,0 +1,42 @@ +#define AUTOMERGEABLE_MERGED_FILE \ + "this file is changed in master\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is changed in branch\n" + +#define AUTOMERGEABLE_MERGED_FILE_CRLF \ + "this file is changed in master\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is changed in branch\r\n" + +#define CONFLICTING_MERGE_FILE \ + "<<<<<<< HEAD\n" \ + "this file is changed in master and branch\n" \ + "=======\n" \ + "this file is changed in branch and master\n" \ + ">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n" + +#define CONFLICTING_DIFF3_FILE \ + "<<<<<<< HEAD\n" \ + "this file is changed in master and branch\n" \ + "||||||| initial\n" \ + "this file is a conflict\n" \ + "=======\n" \ + "this file is changed in branch and master\n" \ + ">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n" + +#define CONFLICTING_UNION_FILE \ + "this file is changed in master and branch\n" \ + "this file is changed in branch and master\n" + diff --git a/tests/merge/files.c b/tests/merge/files.c index 2d55df2b2..daa73fada 100644 --- a/tests/merge/files.c +++ b/tests/merge/files.c @@ -4,6 +4,7 @@ #include "buffer.h" #include "merge.h" #include "merge_helpers.h" +#include "conflict_data.h" #include "refs.h" #include "fileops.h" #include "diff_xdiff.h" diff --git a/tests/merge/merge_helpers.h b/tests/merge/merge_helpers.h index 554c24b7c..e407c7d13 100644 --- a/tests/merge/merge_helpers.h +++ b/tests/merge/merge_helpers.h @@ -4,49 +4,6 @@ #include "merge.h" #include "git2/merge.h" -#define AUTOMERGEABLE_MERGED_FILE \ - "this file is changed in master\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is changed in branch\n" - -#define AUTOMERGEABLE_MERGED_FILE_CRLF \ - "this file is changed in master\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is changed in branch\r\n" - -#define CONFLICTING_MERGE_FILE \ - "<<<<<<< HEAD\n" \ - "this file is changed in master and branch\n" \ - "=======\n" \ - "this file is changed in branch and master\n" \ - ">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n" - -#define CONFLICTING_DIFF3_FILE \ - "<<<<<<< HEAD\n" \ - "this file is changed in master and branch\n" \ - "||||||| initial\n" \ - "this file is a conflict\n" \ - "=======\n" \ - "this file is changed in branch and master\n" \ - ">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n" - -#define CONFLICTING_UNION_FILE \ - "this file is changed in master and branch\n" \ - "this file is changed in branch and master\n" - - struct merge_index_entry { uint16_t mode; char oid_str[GIT_OID_HEXSZ+1]; diff --git a/tests/merge/trees/automerge.c b/tests/merge/trees/automerge.c index c18881d7c..67f2cf786 100644 --- a/tests/merge/trees/automerge.c +++ b/tests/merge/trees/automerge.c @@ -3,8 +3,9 @@ #include "git2/merge.h" #include "buffer.h" #include "merge.h" -#include "../merge_helpers.h" #include "fileops.h" +#include "../merge_helpers.h" +#include "../conflict_data.h" static git_repository *repo; diff --git a/tests/merge/trees/commits.c b/tests/merge/trees/commits.c index dd1e383ac..786a77a8b 100644 --- a/tests/merge/trees/commits.c +++ b/tests/merge/trees/commits.c @@ -3,6 +3,7 @@ #include "git2/merge.h" #include "merge.h" #include "../merge_helpers.h" +#include "../conflict_data.h" static git_repository *repo; diff --git a/tests/merge/workdir/simple.c b/tests/merge/workdir/simple.c index abc0777f7..3cdd15b5a 100644 --- a/tests/merge/workdir/simple.c +++ b/tests/merge/workdir/simple.c @@ -4,6 +4,7 @@ #include "buffer.h" #include "merge.h" #include "../merge_helpers.h" +#include "../conflict_data.h" #include "refs.h" #include "fileops.h" From 651bfd699c8eaa8ca36de0d0d992a1832d71df8f Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 9 Nov 2015 08:24:47 -0500 Subject: [PATCH 14/17] recursive: test conflict output during recursive merge --- tests/merge/conflict_data.h | 30 +++++++++++++++++++ tests/merge/workdir/recursive.c | 51 +++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 tests/merge/workdir/recursive.c diff --git a/tests/merge/conflict_data.h b/tests/merge/conflict_data.h index 173892d95..b6c51332f 100644 --- a/tests/merge/conflict_data.h +++ b/tests/merge/conflict_data.h @@ -40,3 +40,33 @@ "this file is changed in master and branch\n" \ "this file is changed in branch and master\n" +#define CONFLICTING_RECURSIVE_F1_TO_F2 \ + "VEAL SOUP.\n" \ + "\n" \ + "<<<<<<< HEAD\n" \ + "PUT INTO A POT THREE QUARTS OF WATER, three onions cut small, ONE\n" \ + "=======\n" \ + "PUT INTO A POT THREE QUARTS OF WATER, three onions cut not too small, one\n" \ + ">>>>>>> branchF-2\n" \ + "spoonful of black pepper pounded, and two of salt, with two or three\n" \ + "slices of lean ham; let it boil steadily two hours; skim it\n" \ + "occasionally, then put into it a shin of veal, let it boil two hours\n" \ + "longer; take out the slices of ham, and skim off the grease if any\n" \ + "should rise, take a gill of good cream, mix with it two table-spoonsful\n" \ + "of flour very nicely, and the yelks of two eggs beaten well, strain this\n" \ + "mixture, and add some chopped parsley; pour some soup on by degrees,\n" \ + "stir it well, and pour it into the pot, continuing to stir until it has\n" \ + "boiled two or three minutes to take off the raw taste of the eggs. If\n" \ + "the cream be not perfectly sweet, and the eggs quite new, the thickening\n" \ + "will curdle in the soup. For a change you may put a dozen ripe tomatos\n" \ + "in, first taking off their skins, by letting them stand a few minutes in\n" \ + "hot water, when they may be easily peeled. When made in this way you\n" \ + "must thicken it with the flour only. Any part of the veal may be used,\n" \ + "but the shin or knuckle is the nicest.\n" \ + "\n" \ + "<<<<<<< HEAD\n" \ + "This certainly is a mighty fine recipe.\n" \ + "=======\n" \ + "This is a mighty fine recipe!\n" \ + ">>>>>>> branchF-2\n" + diff --git a/tests/merge/workdir/recursive.c b/tests/merge/workdir/recursive.c new file mode 100644 index 000000000..a7326009a --- /dev/null +++ b/tests/merge/workdir/recursive.c @@ -0,0 +1,51 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "../conflict_data.h" + +static git_repository *repo; + +#define TEST_REPO_PATH "merge-recursive" + +void test_merge_workdir_recursive__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); +} + +void test_merge_workdir_recursive__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_merge_workdir_recursive__writes_conflict_with_virtual_base(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + git_buf conflicting_buf = GIT_BUF_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "fa567f568ed72157c0c617438d077695b99d9aac", 1, "veal.txt" }, + { 0100644, "21950d5e4e4d1a871b4dfcf72ecb6b9c162c434e", 2, "veal.txt" }, + { 0100644, "3855170cef875708da06ab9ad7fc6a73b531cda1", 3, "veal.txt" }, + }; + + + cl_git_pass(merge_branches(repo, GIT_REFS_HEADS_DIR "branchF-1", GIT_REFS_HEADS_DIR "branchF-2", &opts, NULL)); + + cl_git_pass(git_repository_index(&index, repo)); + cl_assert(merge_test_index(index, merge_index_entries, 8)); + + cl_git_pass(git_futils_readbuffer(&conflicting_buf, "merge-recursive/veal.txt")); + + cl_assert_equal_s(CONFLICTING_RECURSIVE_F1_TO_F2, conflicting_buf.ptr); + + git_index_free(index); + git_buf_free(&conflicting_buf); +} From 34a51428a121800509c2bea94137a17802e37982 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 9 Nov 2015 11:55:26 -0500 Subject: [PATCH 15/17] merge tests: add complex recursive example --- tests/merge/trees/recursive.c | 28 ++++++++++++++++++ tests/resources/merge-recursive/.gitted/HEAD | Bin 26 -> 26 bytes tests/resources/merge-recursive/.gitted/index | Bin 632 -> 619 bytes .../34/8f16ffaeb73f319a75cec5b16a0a47d2d5e27c | Bin 0 -> 208 bytes .../48/3065df53c0f4a02cdc6b2910b05d388fc17ffb | Bin 0 -> 165 bytes .../c4/83ca4bb087174af5cb51d7caa9c09fe4a28ccb | Bin 0 -> 241 bytes .../d7/1c24b3b113fd1d1909998c5bfe33b86a65ee03 | Bin 0 -> 240 bytes .../.gitted/refs/heads/branchG-1 | Bin 0 -> 41 bytes .../.gitted/refs/heads/branchG-2 | Bin 0 -> 41 bytes tests/resources/merge-recursive/asparagus.txt | Bin 587 -> 587 bytes tests/resources/merge-recursive/oyster.txt | Bin 774 -> 774 bytes tests/resources/merge-recursive/veal.txt | Bin 1095 -> 1122 bytes 12 files changed, 28 insertions(+) create mode 100644 tests/resources/merge-recursive/.gitted/objects/34/8f16ffaeb73f319a75cec5b16a0a47d2d5e27c create mode 100644 tests/resources/merge-recursive/.gitted/objects/48/3065df53c0f4a02cdc6b2910b05d388fc17ffb create mode 100644 tests/resources/merge-recursive/.gitted/objects/c4/83ca4bb087174af5cb51d7caa9c09fe4a28ccb create mode 100644 tests/resources/merge-recursive/.gitted/objects/d7/1c24b3b113fd1d1909998c5bfe33b86a65ee03 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchG-1 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchG-2 diff --git a/tests/merge/trees/recursive.c b/tests/merge/trees/recursive.c index abca01727..1e5f61391 100644 --- a/tests/merge/trees/recursive.c +++ b/tests/merge/trees/recursive.c @@ -269,3 +269,31 @@ void test_merge_trees_recursive__conflict(void) git_index_free(index); } +/* + * Branch G-1 and G-2 have three common ancestors (815b5a1, ad2ace9, 483065d). + * The merge-base of the first two has two common ancestors (723181f, a34e5a1) + * which themselves have two common ancestors (8f35f30, 3a3f5a6), which + * finally has a common ancestor of 7c7bf85. This virtual merge base will + * be computed and merged with 483065d which also has a common ancestor of + * 7c7bf85. + */ +void test_merge_trees_recursive__oh_so_many_levels_of_recursion(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "7c7e08f9559d9e1551b91e1cf68f1d0066109add", 0, "oyster.txt" }, + { 0100644, "898d12687fb35be271c27c795a6b32c8b51da79e", 0, "veal.txt" }, + }; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchG-1", "branchG-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 6)); + + git_index_free(index); +} diff --git a/tests/resources/merge-recursive/.gitted/HEAD b/tests/resources/merge-recursive/.gitted/HEAD index 77e35742d01dcf26e0594d689548d3ae37549fca..d7cef11aa7942cf4664096bcca2b11b0ba1a99cc 100644 GIT binary patch delta 9 Qcmb1=njpsFu4}{v00>+Gj{pDw delta 9 Qcmb1=njpsFq-)3p00>3_i2wiq diff --git a/tests/resources/merge-recursive/.gitted/index b/tests/resources/merge-recursive/.gitted/index index 1e47851a50c3550bd04e7e1a481346d39b101267..571cfd02f85a253dd729b3b672b3e63e78ca19a3 100644 GIT binary patch literal 619 zcmZ?q402{*U|<4bwlIfXu0WarMl%A%8S|FSW?*Ps!oa}z6(}VF6!QMRIWN#Y{(e{X zihxCoPU%@%M;dAwcoT~Y5{nYkON;eNDoQ}cfXuN$rlICdMm3K$CgYogzEA7rdBU7G zYwBDR!|u#sn8v`7l$x3bF$#w{Q&7!eaq+GR3t;HhE2)3jFz^;7QRxSqar2Nv% zoSaO!t8lt&Dyn&mZAYG+S^OsJfk@va!=FXr_j?TG7~>f@(~A8O z=gpcr*Tk?pa~P&Ea3rOsra_FtVa_~Mb68xwYr+B;y7fxxA2!T;9VL5@uc4KTfjcR` zG&3hB6YeUU?wXHk9%I{)XJ;0_$$B8tcggT)QTY8HLpjEH2F~=N#Ij1TX*k@q0M#63 zwv6@i#~tc#uDvhLxT0?3$(WKUM`ti_ diff --git a/tests/resources/merge-recursive/.gitted/objects/34/8f16ffaeb73f319a75cec5b16a0a47d2d5e27c b/tests/resources/merge-recursive/.gitted/objects/34/8f16ffaeb73f319a75cec5b16a0a47d2d5e27c new file mode 100644 index 0000000000000000000000000000000000000000..bd1b1f69a9e070fd93f6859f9f5d8b6c29335b6d GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKvzPwlJ zvRs>X5O!@9(J**$fRV(D&CW7|Ct_P%v^jxfi!sqa>Yi4)HH`)HL|!7&WZ6!+}F-QxJp?Lz! z!m-+dP$5W rj6?q!GrZ{jrl#(+@~mew{-VbTM?l)gY-kImz{;W8NI*V`lb|l~@J_p~haqvqTGWOXV@0tR zb8$|4g)k~%D={^SSHI5)F-Qx@&^&=-;aFXeZiZsDUhJU`oD7g20Ig zxMzC2ql%!1fj*CU+s(6l(Jtn7-jiR4N?g94-HV<$n%Q{06@hCOaK4? delta 21 ccmZo;Yh&Z_j|>iR4N?g94-L@U$n%Q{06_)@SpWb4 diff --git a/tests/resources/merge-recursive/veal.txt b/tests/resources/merge-recursive/veal.txt index 94d2c01087f48213bd157222d54edfefd77c9bba..898d12687fb35be271c27c795a6b32c8b51da79e 100644 GIT binary patch delta 120 zcmX@k@rc7S%+=9HA=p1OK#z+nAT&h5(=Wtd!BHW=KSUwKBgoZNAu!Z2C?r_H-%TOh zF~l`UN5NPjKQA*suUH|uv_zpeH!&wiN5S9Eb)xTCM(fSej5^HnTp<~m#R@=_sF0hP Wo>5Y%kd~R3s!)`goLP{n$OQm3OC#+7 delta 92 zcmaFFah$_9%+=9HA=p1OK#_|pptM9GGp{6HAyJ_qzeJ%VqbN01p|CWusH9jSKTV-L pu_U!f2P&MOmzkeetdI=UQk Date: Fri, 20 Nov 2015 17:33:49 -0500 Subject: [PATCH 16/17] merge: handle conflicts in recursive base building When building a recursive merge base, allow conflicts to occur. Use the file (with conflict markers) as the common ancestor. The user has already seen and dealt with this conflict by virtue of having a criss-cross merge. If they resolved this conflict identically in both branches, then there will be no conflict in the result. This is the best case scenario. If they did not resolve the conflict identically in the two branches, then we will generate a new conflict. If the user is simply using standard conflict output then the results will be fairly sensible. But if the user is using a mergetool or using diff3 output, then the common ancestor will be a conflict file (itself with diff3 output, haha!). This is quite terrible, but it matches git's behavior. --- src/merge.c | 67 ++++++++++----- tests/merge/conflict_data.h | 31 +++++++ tests/merge/trees/recursive.c | 80 ++++++++++++++++++ tests/merge/workdir/recursive.c | 35 +++++++- .../15/311229e70fa62653f73dde1d4deef1a8e47a11 | Bin 0 -> 710 bytes .../37/185b25a204309bf74817da1a607518f13ca3ed | Bin 0 -> 715 bytes .../37/a5054a9f9b4628e3924c5cb8f2147c6e2a3efc | Bin 0 -> 630 bytes .../42/44d13e2bbc38510320443bbb003f3967d12436 | Bin 0 -> 207 bytes .../4f/4e85a0ab8515e34302721fbcec06fa9d9c1a9a | Bin 0 -> 631 bytes .../56/07a8c4601a737daadd1f470bde3142aff57026 | Bin 0 -> 206 bytes .../63/e8773becdea9c3699c95a5740be5baa8be8d69 | Bin 0 -> 207 bytes .../6c/778edd0e4cf394f5a3df8b96db516024cc1bb8 | Bin 0 -> 636 bytes .../6e/f31d35a3f5abc1e24f4f9afa5cb2016f03fa2d | Bin 0 -> 174 bytes .../7a/9277e0c5ec75339f011c176d0c20e513c4de1c | Bin 0 -> 202 bytes .../88/8588a782ad433fbf0cc526e07cfe6f4a6b60b3 | Bin 0 -> 208 bytes .../98/1c79eb38518d3821e73bb159dc413bb42d6614 | Bin 0 -> 208 bytes .../a0/2d4fd126e0cc8fb46ee48cf38bad36d44f2dbc | Bin 0 -> 649 bytes .../aa/9e263294fd2f6f6fd9ceab23ca8ce3ea2ce707 | Bin 0 -> 175 bytes .../b9/1ef5ffa8612616c8e76051901caafd723f0e2c | Bin 0 -> 712 bytes .../ca/fa936d25f0b397432a27201f6b3284c47df8be | Bin 0 -> 712 bytes .../d6/04c75019c282144bdbbf3fd3462ba74b240efc | Bin 0 -> 620 bytes .../db/203155a789fb749aa3c14e93eea2c744a9c6c7 | Bin 0 -> 204 bytes .../e1/512550f09d980214e46e6d3f5a2b20c3d75755 | Bin 0 -> 208 bytes .../f7/929c5a67a4bdc98247fb4b5098675723932a64 | Bin 0 -> 207 bytes .../.gitted/refs/heads/branchH-1 | Bin 0 -> 41 bytes .../.gitted/refs/heads/branchH-2 | Bin 0 -> 41 bytes .../.gitted/refs/heads/branchI-1 | Bin 0 -> 41 bytes .../.gitted/refs/heads/branchI-2 | Bin 0 -> 41 bytes 28 files changed, 193 insertions(+), 20 deletions(-) create mode 100644 tests/resources/merge-recursive/.gitted/objects/15/311229e70fa62653f73dde1d4deef1a8e47a11 create mode 100644 tests/resources/merge-recursive/.gitted/objects/37/185b25a204309bf74817da1a607518f13ca3ed create mode 100644 tests/resources/merge-recursive/.gitted/objects/37/a5054a9f9b4628e3924c5cb8f2147c6e2a3efc create mode 100644 tests/resources/merge-recursive/.gitted/objects/42/44d13e2bbc38510320443bbb003f3967d12436 create mode 100644 tests/resources/merge-recursive/.gitted/objects/4f/4e85a0ab8515e34302721fbcec06fa9d9c1a9a create mode 100644 tests/resources/merge-recursive/.gitted/objects/56/07a8c4601a737daadd1f470bde3142aff57026 create mode 100644 tests/resources/merge-recursive/.gitted/objects/63/e8773becdea9c3699c95a5740be5baa8be8d69 create mode 100644 tests/resources/merge-recursive/.gitted/objects/6c/778edd0e4cf394f5a3df8b96db516024cc1bb8 create mode 100644 tests/resources/merge-recursive/.gitted/objects/6e/f31d35a3f5abc1e24f4f9afa5cb2016f03fa2d create mode 100644 tests/resources/merge-recursive/.gitted/objects/7a/9277e0c5ec75339f011c176d0c20e513c4de1c create mode 100644 tests/resources/merge-recursive/.gitted/objects/88/8588a782ad433fbf0cc526e07cfe6f4a6b60b3 create mode 100644 tests/resources/merge-recursive/.gitted/objects/98/1c79eb38518d3821e73bb159dc413bb42d6614 create mode 100644 tests/resources/merge-recursive/.gitted/objects/a0/2d4fd126e0cc8fb46ee48cf38bad36d44f2dbc create mode 100644 tests/resources/merge-recursive/.gitted/objects/aa/9e263294fd2f6f6fd9ceab23ca8ce3ea2ce707 create mode 100644 tests/resources/merge-recursive/.gitted/objects/b9/1ef5ffa8612616c8e76051901caafd723f0e2c create mode 100644 tests/resources/merge-recursive/.gitted/objects/ca/fa936d25f0b397432a27201f6b3284c47df8be create mode 100644 tests/resources/merge-recursive/.gitted/objects/d6/04c75019c282144bdbbf3fd3462ba74b240efc create mode 100644 tests/resources/merge-recursive/.gitted/objects/db/203155a789fb749aa3c14e93eea2c744a9c6c7 create mode 100644 tests/resources/merge-recursive/.gitted/objects/e1/512550f09d980214e46e6d3f5a2b20c3d75755 create mode 100644 tests/resources/merge-recursive/.gitted/objects/f7/929c5a67a4bdc98247fb4b5098675723932a64 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchH-1 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchH-2 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchI-1 create mode 100644 tests/resources/merge-recursive/.gitted/refs/heads/branchI-2 diff --git a/src/merge.c b/src/merge.c index 64c8f1116..f05e45c9f 100644 --- a/src/merge.c +++ b/src/merge.c @@ -49,6 +49,19 @@ #define GIT_MERGE_INDEX_ENTRY_EXISTS(X) ((X).mode != 0) #define GIT_MERGE_INDEX_ENTRY_ISFILE(X) S_ISREG((X).mode) + +/** Internal merge flags. */ +enum { + /** The merge is for a virtual base in a recursive merge. */ + GIT_MERGE__VIRTUAL_BASE = (1 << 31), +}; + +enum { + /** Accept the conflict file, staging it as the merge result. */ + GIT_MERGE_FILE_FAVOR__CONFLICTED = 4, +}; + + typedef enum { TREE_IDX_ANCESTOR = 0, TREE_IDX_OURS = 1, @@ -801,11 +814,9 @@ static int merge_conflict_resolve_automerge( int *resolved, git_merge_diff_list *diff_list, const git_merge_diff *conflict, - unsigned int merge_file_favor, - unsigned int file_flags) + const git_merge_file_options *file_opts) { const git_index_entry *ancestor = NULL, *ours = NULL, *theirs = NULL; - git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT; git_merge_file_result result = {0}; git_index_entry *index_entry; git_odb *odb = NULL; @@ -852,12 +863,9 @@ static int merge_conflict_resolve_automerge( theirs = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ? &conflict->their_entry : NULL; - opts.favor = merge_file_favor; - opts.flags = file_flags; - if ((error = git_repository_odb(&odb, diff_list->repo)) < 0 || - (error = git_merge_file_from_index(&result, diff_list->repo, ancestor, ours, theirs, &opts)) < 0 || - !result.automergeable || + (error = git_merge_file_from_index(&result, diff_list->repo, ancestor, ours, theirs, file_opts)) < 0 || + (!result.automergeable && !(file_opts->flags & GIT_MERGE_FILE_FAVOR__CONFLICTED)) || (error = git_odb_write(&automerge_oid, odb, result.ptr, result.len, GIT_OBJ_BLOB)) < 0) goto done; @@ -887,8 +895,7 @@ static int merge_conflict_resolve( int *out, git_merge_diff_list *diff_list, const git_merge_diff *conflict, - unsigned int merge_file_favor, - unsigned int file_flags) + const git_merge_file_options *file_opts) { int resolved = 0; int error = 0; @@ -904,8 +911,7 @@ static int merge_conflict_resolve( if (!resolved && (error = merge_conflict_resolve_one_renamed(&resolved, diff_list, conflict)) < 0) goto done; - if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict, - merge_file_favor, file_flags)) < 0) + if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict, file_opts)) < 0) goto done; *out = resolved; @@ -1829,6 +1835,7 @@ int git_merge__iterators( *empty_theirs = NULL; git_merge_diff_list *diff_list; git_merge_options opts; + git_merge_file_options file_opts = GIT_MERGE_FILE_OPTIONS_INIT; git_merge_diff *conflict; git_vector changes; size_t i; @@ -1844,6 +1851,17 @@ int git_merge__iterators( if ((error = merge_normalize_opts(repo, &opts, given_opts)) < 0) return error; + file_opts.favor = opts.file_favor; + file_opts.flags = opts.file_flags; + + /* use the git-inspired labels when virtual base building */ + if (opts.flags & GIT_MERGE__VIRTUAL_BASE) { + file_opts.ancestor_label = "merged common ancestors"; + file_opts.our_label = "Temporary merge branch 1"; + file_opts.their_label = "Temporary merge branch 2"; + file_opts.flags |= GIT_MERGE_FILE_FAVOR__CONFLICTED; + } + diff_list = git_merge_diff_list__alloc(repo); GITERR_CHECK_ALLOC(diff_list); @@ -1862,7 +1880,8 @@ int git_merge__iterators( git_vector_foreach(&changes, i, conflict) { int resolved = 0; - if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.file_favor, opts.file_flags)) < 0) + if ((error = merge_conflict_resolve( + &resolved, diff_list, conflict, &file_opts)) < 0) goto done; if (!resolved) { @@ -1962,16 +1981,27 @@ static int create_virtual_base( git_repository *repo, git_annotated_commit *one, git_annotated_commit *two, + const git_merge_options *opts, size_t recursion_level) { git_annotated_commit *result = NULL; git_index *index = NULL; + git_merge_options virtual_opts = GIT_MERGE_OPTIONS_INIT; result = git__calloc(1, sizeof(git_annotated_commit)); GITERR_CHECK_ALLOC(result); + /* Conflicts in the merge base creation do not propagate to conflicts + * in the result; the conflicted base will act as the common ancestor. + */ + if (opts) + memcpy(&virtual_opts, opts, sizeof(git_merge_options)); + + virtual_opts.flags &= ~GIT_MERGE_FAIL_ON_CONFLICT; + virtual_opts.flags |= GIT_MERGE__VIRTUAL_BASE; + if ((merge_annotated_commits(&index, NULL, repo, one, two, - recursion_level + 1, NULL)) < 0) + recursion_level + 1, &virtual_opts)) < 0) return -1; result->type = GIT_ANNOTATED_COMMIT_VIRTUAL; @@ -1989,7 +2019,7 @@ static int compute_base( git_repository *repo, const git_annotated_commit *one, const git_annotated_commit *two, - bool recurse, + const git_merge_options *opts, size_t recursion_level) { git_array_oid_t head_ids = GIT_ARRAY_INIT; @@ -2007,7 +2037,7 @@ static int compute_base( if ((error = git_merge_bases_many(&bases, repo, head_ids.size, head_ids.ptr)) < 0 || (error = git_annotated_commit_lookup(&base, repo, &bases.ids[0])) < 0 || - !recurse) + (opts && (opts->flags & GIT_MERGE_NO_RECURSIVE))) goto done; for (i = 1; i < bases.count; i++) { @@ -2015,7 +2045,7 @@ static int compute_base( if ((error = git_annotated_commit_lookup(&other, repo, &bases.ids[i])) < 0 || - (error = create_virtual_base(&new_base, repo, base, other, + (error = create_virtual_base(&new_base, repo, base, other, opts, recursion_level)) < 0) goto done; @@ -2076,10 +2106,9 @@ static int merge_annotated_commits( { git_annotated_commit *base = NULL; git_iterator *base_iter = NULL, *our_iter = NULL, *their_iter = NULL; - bool recurse = !opts || !(opts->flags & GIT_MERGE_NO_RECURSIVE); int error; - if ((error = compute_base(&base, repo, ours, theirs, recurse, + if ((error = compute_base(&base, repo, ours, theirs, opts, recursion_level)) < 0) { if (error != GIT_ENOTFOUND) diff --git a/tests/merge/conflict_data.h b/tests/merge/conflict_data.h index b6c51332f..e6394a9e8 100644 --- a/tests/merge/conflict_data.h +++ b/tests/merge/conflict_data.h @@ -70,3 +70,34 @@ "This is a mighty fine recipe!\n" \ ">>>>>>> branchF-2\n" +#define CONFLICTING_RECURSIVE_H1_TO_H2_WITH_DIFF3 \ + "VEAL SOUP.\n" \ + "\n" \ + "<<<<<<< HEAD\n" \ + "put into a pot three quarts of water, three onions cut small, one\n" \ + "||||||| merged common ancestors\n" \ + "<<<<<<< Temporary merge branch 1\n" \ + "Put into a pot three quarts of water, THREE ONIONS CUT SMALL, one\n" \ + "||||||| merged common ancestors\n" \ + "Put into a pot three quarts of water, three onions cut small, one\n" \ + "=======\n" \ + "PUT INTO A POT three quarts of water, three onions cut small, one\n" \ + ">>>>>>> Temporary merge branch 2\n" \ + "=======\n" \ + "Put Into A Pot Three Quarts of Water, Three Onions Cut Small, One\n" \ + ">>>>>>> branchH-2\n" \ + "spoonful of black pepper pounded, and two of salt, with two or three\n" \ + "slices of lean ham; let it boil steadily two hours; skim it\n" \ + "occasionally, then put into it a shin of veal, let it boil two hours\n" \ + "longer; take out the slices of ham, and skim off the grease if any\n" \ + "should rise, take a gill of good cream, mix with it two table-spoonsful\n" \ + "of flour very nicely, and the yelks of two eggs beaten well, strain this\n" \ + "mixture, and add some chopped parsley; pour some soup on by degrees,\n" \ + "stir it well, and pour it into the pot, continuing to stir until it has\n" \ + "boiled two or three minutes to take off the raw taste of the eggs. If\n" \ + "the cream be not perfectly sweet, and the eggs quite new, the thickening\n" \ + "will curdle in the soup. For a change you may put a dozen ripe tomatos\n" \ + "in, first taking off their skins, by letting them stand a few minutes in\n" \ + "hot water, when they may be easily peeled. When made in this way you\n" \ + "must thicken it with the flour only. Any part of the veal may be used,\n" \ + "but the shin or knuckle is the nicest.\n" diff --git a/tests/merge/trees/recursive.c b/tests/merge/trees/recursive.c index 1e5f61391..693c91065 100644 --- a/tests/merge/trees/recursive.c +++ b/tests/merge/trees/recursive.c @@ -297,3 +297,83 @@ void test_merge_trees_recursive__oh_so_many_levels_of_recursion(void) git_index_free(index); } + +/* Branch H-1 and H-2 have two common ancestors (aa9e263, 6ef31d3). The two + * ancestors themselves conflict. + */ +void test_merge_trees_recursive__conflicting_merge_base(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "3a66812fed1e03ea4a6a7ee28d8a57aec1ca6537", 1, "veal.txt" }, + { 0100644, "d604c75019c282144bdbbf3fd3462ba74b240efc", 2, "veal.txt" }, + { 0100644, "37a5054a9f9b4628e3924c5cb8f2147c6e2a3efc", 3, "veal.txt" }, + }; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchH-1", "branchH-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 8)); + + git_index_free(index); +} + +/* Branch H-1 and H-2 have two common ancestors (aa9e263, 6ef31d3). The two + * ancestors themselves conflict. The generated common ancestor file will + * have diff3 style conflicts inside it. + */ +void test_merge_trees_recursive__conflicting_merge_base_with_diff3(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "cd17a91513f3aee9e44114d1ede67932dd41d2fc", 1, "veal.txt" }, + { 0100644, "d604c75019c282144bdbbf3fd3462ba74b240efc", 2, "veal.txt" }, + { 0100644, "37a5054a9f9b4628e3924c5cb8f2147c6e2a3efc", 3, "veal.txt" }, + }; + + opts.file_flags |= GIT_MERGE_FILE_STYLE_DIFF3; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchH-1", "branchH-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 8)); + + git_index_free(index); +} + +/* Branch I-1 and I-2 have two common ancestors (aa9e263, 6ef31d3). The two + * ancestors themselves conflict, but when each was merged, the conflicts were + * resolved identically, thus merging I-1 into I-2 does not conflict. + */ +void test_merge_trees_recursive__conflicting_merge_base_since_resolved(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "a02d4fd126e0cc8fb46ee48cf38bad36d44f2dbc", 0, "veal.txt" }, + }; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchI-1", "branchI-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 6)); + + git_index_free(index); +} diff --git a/tests/merge/workdir/recursive.c b/tests/merge/workdir/recursive.c index a7326009a..795126255 100644 --- a/tests/merge/workdir/recursive.c +++ b/tests/merge/workdir/recursive.c @@ -36,7 +36,6 @@ void test_merge_workdir_recursive__writes_conflict_with_virtual_base(void) { 0100644, "3855170cef875708da06ab9ad7fc6a73b531cda1", 3, "veal.txt" }, }; - cl_git_pass(merge_branches(repo, GIT_REFS_HEADS_DIR "branchF-1", GIT_REFS_HEADS_DIR "branchF-2", &opts, NULL)); cl_git_pass(git_repository_index(&index, repo)); @@ -49,3 +48,37 @@ void test_merge_workdir_recursive__writes_conflict_with_virtual_base(void) git_index_free(index); git_buf_free(&conflicting_buf); } + +void test_merge_workdir_recursive__conflicting_merge_base_with_diff3(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + git_buf conflicting_buf = GIT_BUF_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "cd17a91513f3aee9e44114d1ede67932dd41d2fc", 1, "veal.txt" }, + { 0100644, "d604c75019c282144bdbbf3fd3462ba74b240efc", 2, "veal.txt" }, + { 0100644, "37a5054a9f9b4628e3924c5cb8f2147c6e2a3efc", 3, "veal.txt" }, + }; + + opts.file_flags |= GIT_MERGE_FILE_STYLE_DIFF3; + checkout_opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_DIFF3; + + cl_git_pass(merge_branches(repo, GIT_REFS_HEADS_DIR "branchH-1", GIT_REFS_HEADS_DIR "branchH-2", &opts, &checkout_opts)); + + cl_git_pass(git_repository_index(&index, repo)); + cl_assert(merge_test_index(index, merge_index_entries, 8)); + + cl_git_pass(git_futils_readbuffer(&conflicting_buf, "merge-recursive/veal.txt")); + + cl_assert_equal_s(CONFLICTING_RECURSIVE_H1_TO_H2_WITH_DIFF3, conflicting_buf.ptr); + + git_index_free(index); + git_buf_free(&conflicting_buf); +} diff --git a/tests/resources/merge-recursive/.gitted/objects/15/311229e70fa62653f73dde1d4deef1a8e47a11 b/tests/resources/merge-recursive/.gitted/objects/15/311229e70fa62653f73dde1d4deef1a8e47a11 new file mode 100644 index 0000000000000000000000000000000000000000..8c21bb357b2e5b67ef00d764c0b31886e4b19acb GIT binary patch literal 710 zcmV;%0y+J70i9Iaj?*v@<=I~`A5bcB5fUmORZz4mE!&FSg=Z(3G*%ru>v0G{d^~5I z7I;MXskJ>b=jK#CR`l%o>z7Zy?6x;_w|_XSjd`;yy4r0&n8U+8UEkjCX-kLwJ>@Pj z)8lAU7K$xRHgj5?w_|WI2-RaI>87mz24v6(RP^J8KwOs)mR*$6uMhLRHo4DDm-=zJ087$Z!@b+qZ-_eBAKQvlgko}U&O z1v(laZ9OOgZ<;AU80A$&1g4q&sR*T|d^`$OjCci_ShFNKS+LEW6N5o{OaP;`wrNOW z&s292_B1ruB%bGu`jnOi^KM(lX4?W`EJ5mQSJ&aOj=FlN|}f<^bUuE|c=famI(PEej}x^9jBDKdgJ1v~@< zt>ro+88R^g$3>?i&Ex3MB=A&np{mp;4!~$8HKra@yp4pds6P_Xh1V0CCEy(MB*R~bm_Qg)K0v6%kS0w9qzZ~QX{-|)@a!g+#;RjyK8Fy*hv#=r z3%r2vQ)~O~e*c`kk9&G?adr9Z^LBGf54%tID`Q?Qi>|kucjkV~QX^5F}mze2k zv?&Y4mL{7yRrGlMal576-OcXqf!=<4q=yfi+uMp_VDn>H)N?v;Lv`%?7|4d2CC4QH zIbj(bgNs3^1}N#R_sfLW%QE*Ed~^4>qYd5f9{+~*U!C48i>$rki_4crh8ROTdZoJe zwm#Cp!@vnzjG^JC0*{9B6!n5wpDUVN?v|ajATZ(`xatkhHc)5#HGVrC*M$V!hoTDEFGLL!W?3Rt+~sf=Wo)P|+Kb}IL=QzEZ2A@mh8 z8?pLUkWG?N-rkE!wSPxXS^V85dGF~PUG zv&aL@airePB~O-`_#HYYH!u+QHb*foRMfg8aMB)?`zadG3`q%6sg_6_q=7CS_fV#| zK`l?e_`6^_a5;S_CQUHz&Sf-sB4ir5BwmAWJg2Gv$ntoIu3(4YHd1s)u x20ZmiOuG26OW$mw+4+s@3SfH*d1k#m|T6BTCc9KbA#j%6OCWNo&jMDVGs)~06qwj`R)7qM_6GAf&{vQ)tVR8c~?nW@l_mrG4 zVCWo6qw`gmF~*)clw-`|ejN$`oC3(U_58ZZDA3UW>EJ;Tc+*Y+!YHpQA~5aj=PH!8 z@;C~$43h$Ftd2-d7Hsq6#9&b_31GC>_B}~ln7S##o}N~l#PfbupVIM5Vp%B$YIo`x zrf(;4BOFg z=ziBV*$ofyTwT)*%JW1|gVB#FBUn>FU=g%|yNqPW#ta+}ovJiHio=k=Tg`>4(#;%z z(QIl=S5oicpXvp-!Tv;_VuEkoWRVBjW1+?FHBXlM_!~MWw=xhfHb*foG&Hy*aMI4o z{T>ZyhNJ{(R7)fd(m5GG{O}FfcPQQAjKg*oR}_y-IlIB-C7+5<={A$BEp;heVaG-?`m~s}LV~uvbi@u*}<#pvutJE~`a3Y@uDx25^^|7323uQV^ z^3mF93_Z7rk$s}cFBghjC=}`>MAE{32yt&!lhmvi(m5=+;H2-pLKzh8CY2MdkQh=C ztM{Z+NH+W@duaZ@t*L6=T$FU>e4*lJCP6v+&_7iWbogjPWgOf8Yi6%ZVT8rqDLTc0 za!`g0>*MJfVgqv(8K}o~v{}Nhg8;;tfa1HzZyQDhM+c>2ghlAhJ0*ZIUkxHO?HuO@ z%1ZfqRq7ZaCEC~$(ULvfmMN&ipi(o$SgjuhQdyY#Nf6IKtIryFzgSNB_@z=;WJ=vm z1H&Ba$!Q7MFdpr#Q@f9o2G}sIf=qi!C8QeCmB77KRh&etoxD1W5mVb9+)@XLR10E9 z!NL8;HTw+*$lOx13Fh-m_oK6qh7qnQNx`n=k^6$p(2W^7UO6>1FEyY^;;rq4QR!z+ z(C9V`rmuO3$j^8oZMZ+vXUWK|pFH+~cB!=Zz3r2yL4JdC4l6_P;)|#Y=|p45iX{DP z-fyb`X4sUZCu50?0~&CdcmbJ~293P^^&gU(;N|w%Hrrs_-P>sR#FE+SugoBLrXTiy z@xx7cP!#Sa)h*S8941?4?VZ8eu}_lXex|#GR(Rj9Z0%LNPO6Ic>blqUZ|^44oN7NC RCnSYtwvk%S?hhNSg)?_+K#TwY literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/56/07a8c4601a737daadd1f470bde3142aff57026 b/tests/resources/merge-recursive/.gitted/objects/56/07a8c4601a737daadd1f470bde3142aff57026 new file mode 100644 index 0000000000000000000000000000000000000000..bf3639d054dc4d200f0af55ac962784c6a7b02bc GIT binary patch literal 206 zcmV;<05Sh~0i};kN(C_xgk8@m`T`^A&ObcFjf=N%=LI^Qj`J2Xk-Ui4cLY6w)TZjA zC@AUsew$!Tc$h;Kazcq&i%lL=wTV!pEd_n9;_!5iY6$3-4<33H8C)b1_GXA;D_AG0REMV^jYzvApVdS15xI+2Fbo+>Y6Q^L54L I8zXXJRt8>Zb^rhX literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/63/e8773becdea9c3699c95a5740be5baa8be8d69 b/tests/resources/merge-recursive/.gitted/objects/63/e8773becdea9c3699c95a5740be5baa8be8d69 new file mode 100644 index 0000000000000000000000000000000000000000..6d5c320fe3eafb23ef1b8056324cabfef9ee5260 GIT binary patch literal 207 zcmV;=05Jb}0V^p=O;s>5GG{O}FfcPQQAjKKwxdU$y}81q;%xsW4ST4JU=CT4mqHf5nW&}uWMhMvEC zyS=4{`@4txC;IgAOiy2LPN#-qU?WS6VJKd&x88OWExat8fLB7#eM2_%l-H;i#QNOO z>hidsqepG` z&~jCUc}p_7pv!-<_04~<%BrFnAH$i`k+PkbBF2G3|5$<0uA?rE!%+X96I)?&10-%n zfaH5hP8c*4$I{vPYRoyto;q9y%Qupr*V)mE(HOC{_TZ8_ zoCqZ&b`0#kUwln=#Q`$c)O3UDJkZ@>^rPAc)f7-z6m8%xqZzU?gU8jUYRzkL013R- zUZ^YG!~q=5s=;(6^&a`DUq~D35A-=EMI$Gc^qwc>Sy21v5g+<*}{WVBFp6YUo7CwE7D( z96Znu{Xg6OLfi=kH>GOkqC|F)HM9E8AZ_nc41PP%O#l?$_tjf{71vEg@Lo-Ot$%$t WiKbAxNqs_60MkZFKA1nlLWC2#0zgav literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/6e/f31d35a3f5abc1e24f4f9afa5cb2016f03fa2d b/tests/resources/merge-recursive/.gitted/objects/6e/f31d35a3f5abc1e24f4f9afa5cb2016f03fa2d new file mode 100644 index 0000000000000000000000000000000000000000..e95a5e2dbbd6dc272ecd7ede4fd4f4ea377a0919 GIT binary patch literal 174 zcmV;f08#&V0i};YP6Z(l1zmHBzJR7-Xc`h@-25AO0iYZIBr+HV_4OiW}x^VDMjS1v7*CXUUDjTI?`#^}V= z!W=?LHHvR0f35qNaFd@r1>WwXpW}dMz3d;o_Px$=j<%la=r3Ts=frN?EIcA1n#*28 cm;NJRZgO4y*8Bnc0bS?2LdmC^Un=cTR;<=k5&!@I literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/7a/9277e0c5ec75339f011c176d0c20e513c4de1c b/tests/resources/merge-recursive/.gitted/objects/7a/9277e0c5ec75339f011c176d0c20e513c4de1c new file mode 100644 index 0000000000000000000000000000000000000000..9fb34f7eedd4a615198879a383fff0484b21e1a2 GIT binary patch literal 202 zcmV;*05$)30i{ntPDLRQbNx=i1-^lq0X~T_ZcN;`^8&*#_}+qt;bXkMxX=rjZrY}4 zQ|YZ8)1dWtbEp~uqT)~?XThs?7Qqr>&e>Y5m_jTL2*dWlL(gfLlR`j9R14IwP?9KT zK;f$>DuZaW@i!l|qATbbtLH3EfhyI+mAz!JF4Q%{P&WRYdmrYxeDNseZSU>YPxGM5 z{b5h-kkN0w&U@+Y(Kw=*B2e_^V!gH7a@Vn`|ESnrb-b&|gHPFCE?|yx_CM*iZ!lP4 Eqh?`iumAu6 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/88/8588a782ad433fbf0cc526e07cfe6f4a6b60b3 b/tests/resources/merge-recursive/.gitted/objects/88/8588a782ad433fbf0cc526e07cfe6f4a6b60b3 new file mode 100644 index 0000000000000000000000000000000000000000..44efd3315b4326a3f381c0ce6633451ce0b1ef91 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjK05AV|0V^p=O;s>5GG{O}FfcPQQAjKEU!e(}AAOSGsFAq@=c?o z@lIR2R={INbH=DkUgkB$!8n2b$=X)`!3wK_rmS~8hdm`dGI@*xhyJkwp-o3w>btId z?*r?|WI9M(RRof4DVWHhAvl_PV~a7p_boNJ4w%XO+8h8mA&_)!`E9W=!bb(BorOg3 z4J$bqBf5%-;Iy(Gi%~MleIKc2ouGMP3w1FC4Yg@7QDITa0c2!Ww=G3KF*SonJT1*S zM9b@5athn0=<`h8QN2>j5XZ4nF_|DXZt#Ls?&G8wEH=#^nKs@fr;=&9b zcb|$iKe7RcRS0W8c16-eS26m%ajNX&p z+CITYe3(NOm^m_MVxMbRS1X1h(I-U`(_|s1lCZ4qGY>r`kWev>x)Iw_7Z!{u8KJLU z3Qt+Awwe2$c*=;^aZ!fTfKpXiLH+aN|=q`H= do%)Z2yVdLJx8@Jn4`@2x6-qwU{Q?TRQDDTZQfvSK literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/b9/1ef5ffa8612616c8e76051901caafd723f0e2c b/tests/resources/merge-recursive/.gitted/objects/b9/1ef5ffa8612616c8e76051901caafd723f0e2c new file mode 100644 index 0000000000000000000000000000000000000000..e19652394fafa04eeadf6101eab837e67cb1c51c GIT binary patch literal 712 zcmV;(0yq750gY76j?*v@=Ip1K2MCo|aak3RDk$2OmTko@aCVbPW7V;<9)}Rb!}E>P z0v8ZIwYF#G`*RLH9_Yo@^~-0Ux0^e9*nQfsjCr*zy4h~tnf;i_g&fJ!5Hsa2G1Jp% zQx=LXO*V6?=<(*`c1yea+ui*Gz5Vn^4<9yncNN9J=Et(A=XB(T>e%-&kPS6Uj!FJ= z!ZJ7p7lTj@P|{oPmkFW6{9v{YRSRbbtnOT{yeRq_OJQS&u^q;^Fzm zX@Micr`Gn&e1Fct#{*rxdVTZa%VvE~kK3o+(wH~%qT9{-gV{ap>F!~_r8Vugd&+HM zrsu(?EEF3WZRWH%Z^z(b5UPeu(pm2p6a$-|^P-N^k!z}A*Tq0KR4h3rF*{s$AxE;* z$NWDN-p=bEJMC{jZ#J}jxZ6HF(tFT*{ItHmpRvB17u|4keN|r@>0=Dd;FapZ+v-F; z_dO>d9YW3Z0z7KUW7G>`eO}P$ay##&nTrwcz*TQ}wt-sPt?&z^GaaJyB$;jP{8Xyi zI3!t-oLq+sCRUXds0uYFm6-$e7rjt#Nm>`Q^*6TA`|q}js&q3xh9jpHWqV?ZC`TXq zg9?CV9%X23nsRTMFw(@K3x^O3}%M;_@gQOzL7vM`ceQXA&>+Ns>fP6?#Sgh(!s*^pfr zTsRVPTB-)@c&%-%7_|{oOAgMiLy0hC*p7l(_p`3aj@W?b>Y7eao=duGjQ%Myf;9y^ z1q7|(DkB*(G6Tm&ry|Ys;Ls%SSaPANR3{F=Xht=r8dB}ypXvp-!G1{}V}fs0Ymo<< z;y|69N}ep$@dtEHu4f?bY>r}FSWx4Vz)5>j?&oMgGbAO*LbXKVAPsbBxq~vr4QhD& z&EEyng3I|sF=~QwcPgX76Cu;+_smdmNniE6v-KIc6BJGg)pUabnMoGU$~yzKIZrY8 uX-VsVR`@nuwAEK}nKTIAt2tcaU*1ikQy8j~>IA3IOcN=2X?_9!X2$$2(9 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/d6/04c75019c282144bdbbf3fd3462ba74b240efc b/tests/resources/merge-recursive/.gitted/objects/d6/04c75019c282144bdbbf3fd3462ba74b240efc new file mode 100644 index 0000000000000000000000000000000000000000..059fcfe72f6598e0a631ed1165559606dacc47cc GIT binary patch literal 620 zcmV-y0+aoC0Zmi8uGBCPrS@0M2ZR+A6lkkkfP{nu5(4T;GTB&h>|Bpc2w%?`XZJ!G z$8+Yq+=tZD+c)puz54Ot=`(%%^8M?@xvduRu_R*JQlTh&?eg^8F)30GIqpqq_QWwpd3m^yD#&3l22%-!4J|l z2H{9EuU85JYK8jb18ET+eK^|GoNCr9>Ec&haA_D=!3>NJqbiYJRAHV;XCH0(FJW;0 zAJ$kkG#665Nxo9yMJPcbaOfW^5IS|VrD>Yl|63MTAwNOl;S@+=r0i8d!*G~xJ~U%) zDUCGXI$&1+`*Z;0j6mT&$m?dK!bbno%|?x0_Ng2r1Go zmWYy}M%p-QkmG7O<@1-Ox*=2Q4;lsHL_4R&XN%#4 zH>7qSC#^PS6N=N(kYe$%`gkL>sZCX!1e={%oyCZ)tq1qi;Y6$jv18!${qAe#9S6wV zQnL-F^Fp5{XCKW*sHTX*qG*#01)})ML^+wKfJY9@z_)q@748>`nPwJX^C}M%qJuTFl(fii~9@Y GSca3)DKNPJ literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/db/203155a789fb749aa3c14e93eea2c744a9c6c7 b/tests/resources/merge-recursive/.gitted/objects/db/203155a789fb749aa3c14e93eea2c744a9c6c7 new file mode 100644 index 0000000000000000000000000000000000000000..e9f7fd8fd7656e004a2ba597912eaf83108fe564 GIT binary patch literal 204 zcmV;-05ku10i};kN(C_xgk9$pxxkYoonH`f^T3TeFVN|9JG00{^78Qdjtjkj)TZjA zC@31e?@NOT4{I{(2%J-b%G4MOK`ezzz>vJD94cb2oLemF6DJ=_M;5RR0)hmrWZ8M~ zQcy5Zb;d?9An4j}AF;5D;EI>#B%W%87^?%qObm>UIGLpIzP2&-wSD1i`h6SyHV*y7 zC;f3ReWy8YL)IgW{;aL{sU+uZ))y0uQ71i*E&j)ZdgJ-Qx=uW3d%ak_A8Y(Yr@jFK GTw_|HHDY)G literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/objects/e1/512550f09d980214e46e6d3f5a2b20c3d75755 b/tests/resources/merge-recursive/.gitted/objects/e1/512550f09d980214e46e6d3f5a2b20c3d75755 new file mode 100644 index 0000000000000000000000000000000000000000..a5f506fb30b11082e62870bbc305d849e835ca39 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjK%)+xKmNHQ{M=RY(g;Oq%WDaVd5o)M#@?pNcpbslTxshTrE_?sgguFlNDY>tul#56DR%}YwK_=5AFrt*S6o= z0T(^#k9*xW>FwU?c$T)m06G^_q=*4#v78DTp{`^~qR Jrf(5uVo0VDWGVmv literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchH-1 b/tests/resources/merge-recursive/.gitted/refs/heads/branchH-1 new file mode 100644 index 0000000000000000000000000000000000000000..ffe9f8cf35a13fc79489c4e6ea51fd88579a45ba GIT binary patch literal 41 ucmV~$!4Uu;2m`Rc(@+q5jN=vDe*_cWa&k;LVn)<6K;UVU+ayA}2U;KEJPN=7 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-recursive/.gitted/refs/heads/branchH-2 b/tests/resources/merge-recursive/.gitted/refs/heads/branchH-2 new file mode 100644 index 0000000000000000000000000000000000000000..84ed1a2a91c23935402e15ebcb40c3340dfa3261 GIT binary patch literal 41 ucmV~$K>+|D2m`>sX%vP?oPpRsf_FD%>N2CBcVF?#sMn!AEEYw!tn}}^&6%bwypg#0}fHDRM`3G8VXqe literal 0 HcmV?d00001 From 5b9c63c3f673cbc209e53627be2a0e87c17ccb3c Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 20 Nov 2015 19:01:42 -0500 Subject: [PATCH 17/17] recursive merge: add a recursion limit --- include/git2/merge.h | 8 ++++++++ src/merge.c | 13 ++++++++++--- tests/merge/trees/recursive.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/include/git2/merge.h b/include/git2/merge.h index a272e8be4..af53ead22 100644 --- a/include/git2/merge.h +++ b/include/git2/merge.h @@ -265,6 +265,14 @@ typedef struct { /** Pluggable similarity metric; pass NULL to use internal metric */ git_diff_similarity_metric *metric; + /** + * Maximum number of times to merge common ancestors to build a + * virtual merge base when faced with criss-cross merges. When this + * limit is reached, the next ancestor will simply be used instead of + * attempting to merge it. The default is unlimited. + */ + unsigned int recursion_limit; + /** Flags for handling conflicting content. */ git_merge_file_favor_t file_favor; diff --git a/src/merge.c b/src/merge.c index f05e45c9f..9eb3b0904 100644 --- a/src/merge.c +++ b/src/merge.c @@ -2019,17 +2019,21 @@ static int compute_base( git_repository *repo, const git_annotated_commit *one, const git_annotated_commit *two, - const git_merge_options *opts, + const git_merge_options *given_opts, size_t recursion_level) { git_array_oid_t head_ids = GIT_ARRAY_INIT; git_oidarray bases = {0}; git_annotated_commit *base = NULL, *other = NULL, *new_base = NULL; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; size_t i; int error; *out = NULL; + if (given_opts) + memcpy(&opts, given_opts, sizeof(git_merge_options)); + if ((error = insert_head_ids(&head_ids, one)) < 0 || (error = insert_head_ids(&head_ids, two)) < 0) goto done; @@ -2037,15 +2041,18 @@ static int compute_base( if ((error = git_merge_bases_many(&bases, repo, head_ids.size, head_ids.ptr)) < 0 || (error = git_annotated_commit_lookup(&base, repo, &bases.ids[0])) < 0 || - (opts && (opts->flags & GIT_MERGE_NO_RECURSIVE))) + (opts.flags & GIT_MERGE_NO_RECURSIVE)) goto done; for (i = 1; i < bases.count; i++) { recursion_level++; + if (opts.recursion_limit && recursion_level > opts.recursion_limit) + break; + if ((error = git_annotated_commit_lookup(&other, repo, &bases.ids[i])) < 0 || - (error = create_virtual_base(&new_base, repo, base, other, opts, + (error = create_virtual_base(&new_base, repo, base, other, &opts, recursion_level)) < 0) goto done; diff --git a/tests/merge/trees/recursive.c b/tests/merge/trees/recursive.c index 693c91065..c5b129bf8 100644 --- a/tests/merge/trees/recursive.c +++ b/tests/merge/trees/recursive.c @@ -377,3 +377,34 @@ void test_merge_trees_recursive__conflicting_merge_base_since_resolved(void) git_index_free(index); } + +/* There are multiple levels of criss-cross merges, and multiple recursive + * merges would create a common ancestor that allows the merge to complete + * successfully. Test that we can build a single virtual base, then stop, + * which will produce a conflicting merge. + */ +void test_merge_trees_recursive__recursionlimit(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "ce7e553c6feb6e5f3bd67e3c3be04182fe3094b4", 1, "gravy.txt" }, + { 0100644, "d8dd349b78f19a4ebe3357bacb8138f00bf5ed41", 2, "gravy.txt" }, + { 0100644, "e50fbbd701458757bdfe9815f58ed717c588d1b5", 3, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + { 0100644, "a7b066537e6be7109abfe4ff97b675d4e077da20", 0, "veal.txt" }, + }; + + opts.recursion_limit = 1; + + cl_git_pass(merge_commits_from_branches(&index, repo, "branchE-1", "branchE-2", &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 8)); + + git_index_free(index); +} +