summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <vicent@github.com>2014-01-20 16:26:04 -0800
committerVicent Marti <vicent@github.com>2014-01-20 16:26:04 -0800
commitaf2b969b6f63dafa8c55b88cadbcc7631c2dd30b (patch)
treee55254b0dc5473e95227a189d8b37d1450a7c26a
parente49c98e6efaa444ed73ac3b8318a693801f93184 (diff)
parent0ef19fe14ce5a5f7b5ac90966a56997bf04ea5a9 (diff)
downloadlibgit2-af2b969b6f63dafa8c55b88cadbcc7631c2dd30b.tar.gz
Merge pull request #2061 from ethomson/merge_improvements
Merge improvements
-rw-r--r--include/git2/checkout.h7
-rw-r--r--include/git2/merge.h21
-rw-r--r--src/checkout.c95
-rw-r--r--src/merge.c101
-rw-r--r--src/merge.h2
-rw-r--r--src/merge_file.c16
-rw-r--r--src/merge_file.h23
-rw-r--r--tests/merge/trees/automerge.c4
-rw-r--r--tests/merge/trees/trivial.c119
-rw-r--r--tests/merge/workdir/simple.c227
-rw-r--r--tests/merge/workdir/submodules.c101
-rw-r--r--tests/merge/workdir/trivial.c104
-rw-r--r--tests/resources/merge-resolve/.gitted/config2
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/HEAD1
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/ORIG_HEAD1
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/config15
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/indexbin0 -> 153 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/info/exclude6
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/18/fae1354bba0a5f1e6a531f9988369142c24a9ebin0 -> 54 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/29/7aa6cd028b3336c7802c7a6f49143da4e1602dbin0 -> 161 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/38/6c80dc813b89d719797668f40c1be0a6efa996bin0 -> 32 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/ab/435a147bae6d5906ecfd0916a570c4ab3eeea8bin0 -> 64 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/ad/16e0a7684ea95bf892980a2ee412293ae979ccbin0 -> 64 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/ae/39c77c70cb6bad18bb471912460c4e1ba0f5862
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/c2/0765f6e24e8bbb63a648d0d11d84da63170190bin0 -> 52 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/d3/d806a4bef96889117fd7ebac0e3cb5ec1529323
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/f1/065ff5593604072837fecaad3e2e268cb0147bbin0 -> 64 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/packed-refs3
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/refs/heads/master1
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/refs/remotes/origin/HEAD1
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/0f/3fc5dddc8964b9ac1040d0e957f9eb02d9efb3bin0 -> 47 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/11/aeee27ac45a8402c2fd5b875d66dd844e5df00bin0 -> 51 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/1c/51d885170f57a0c4e8c69ff6363d91a5b51f85bin0 -> 30 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/23/ed141a6ae1e798b2f721afedbe947c119111babin0 -> 30 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/27/4bbe983022fb4c02f8a2bf2ebe8da4fe130054bin0 -> 24 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/2b/fdd7e1b6c6ae993f23dfe8e84a8e06a772fa2abin0 -> 231 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/34/8dcd41e2b467991578e92bedd16971b877ef1ebin0 -> 51 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/42/18670ab81cc219a9f94befb5c5dad90ec52648bin0 -> 47 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/49/fd9edac79d15c8fbfca2d481cbb900beba22a63
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/58/87a5e516c53bd58efb0f02ec6aa031b6fe9ad7bin0 -> 47 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/60/61fe116ecba0800c26113ea1a7dfac2e16eeafbin0 -> 87 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/62/33c6a0670228627f93c01cef32485a30403670bin0 -> 44 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/67/110d77886b2af6309b9212961e72b8583e5fa91
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/6e/3b9eb35214d4e31ed5789afc7d520ac798ce55bin0 -> 51 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/72/cdb057b340205164478565e91eb71647e66891bin0 -> 65 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/7a/f14d9c679baaef35555095f4f5d33e9a569ab9bin0 -> 149 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/7c/04ca611203ed320c5f495b9813054dd23be3be2
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/81/1c70fcb6d5bbd022d04cc31836d30b436f9551bin0 -> 169 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/83/6b8b82b26cab22eaaed8820877c76d6c8bca19bin0 -> 30 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/8b/7cd60d49ce3a1a770ece43b7d29b5cf462a33abin0 -> 82 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/91/f44111cb1cb1358ac6944ad356ca1738813ea1bin0 -> 149 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/96/bca8d4f05cc4c5e33e4389f80a1309e86fe054bin0 -> 149 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/ad/01aebfdf2ac13145efafe3f9fcf798882f1730bin0 -> 158 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/ad/26b598134264fd284292cb233fc0b2f25851dabin0 -> 43 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/ca/ff6b7d44973f53e3e0cf31d0d695188b19aec6bin0 -> 54 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/cc/338e4710c9b257106b8d16d82f86458d5beaf12
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/d3/3cedf513c059e0515653fa2c2e386631387a05bin0 -> 46 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/d7/308cc367b2cc23f710834ec1fd8ffbacf1b4601
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/d8/dec75ff2f8b41d1c5bfef0cd57b7300c834f66bin0 -> 164 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/dd/2ae5ab264e5592aa754235d5ad5eac8f0ecdfdbin0 -> 149 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/e5/060729746ca9888239cba08fdcf4bee907b406bin0 -> 24 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/f2/e1550a0c9e53d5811175864a29536642ae3821bin0 -> 73 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/f6/65b45cde9b568009c6e6b7b568e89cfe717df8bin0 -> 132 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/refs/heads/submodules1
-rw-r--r--tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch1
-rw-r--r--tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch21
-rw-r--r--tests/resources/revert/.gitted/indexbin320 -> 464 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/0a/d19525be6d8cae5e5deb2770fc244b65255057bin0 -> 133 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/13/a6fdfd10bd74b1f258fb58801215985dd2e797bin0 -> 121 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/1b/c915c5cb7185a9438de28a7b1a7dfe8c01ee7fbin0 -> 1169 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/1f/f0c423042b46cb1d617b81efb715defbe8054dbin0 -> 751 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/21/a96a98ed84d45866e1de6e266fd3a61a4ae9dcbin0 -> 19 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/39/9fb3aba3d9d13f7d40a9254ce4402067ef31492
-rw-r--r--tests/resources/revert/.gitted/objects/46/ff0854663aeb2182b9838c8da68e33ac23bc1ebin0 -> 20 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/5c/f1d643f100d8112834e540264546ba2c159976bin0 -> 86 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/6b/ccd0dc58cea5ccff86014f3d64b31bd8c02a37bin0 -> 171 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/71/eb9c2b53dbbf3c45fb28b27c850db4b7fb8011bin0 -> 148 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/87/59ad453cf01cf7daf14e2a668f8218f9a678ebbin0 -> 122 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/9a/95fd974e03c5b93828ceedd28755965b5d5c60bin0 -> 122 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/a8/c86221b400b836010567cc3593db6e96c1a83abin0 -> 24 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/ac/c4d33902092efeb3b714aa0b1007c329e2f2e62
-rw-r--r--tests/resources/revert/.gitted/objects/b6/9d88e177455579896e2be495046e2a51456a9a1
-rw-r--r--tests/resources/revert/.gitted/objects/ca/f99de3a49827117bb66721010eac461b06a80cbin0 -> 33 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/de/03538407ed18914ff05657eeff70425c0f304d2
-rw-r--r--tests/resources/revert/.gitted/objects/e3/4ef1afe54eb526fd92eec66084125f340f1d65bin0 -> 150 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/ea/392a157085bc32daccd59aa1998fe2f5fb9fc0bin0 -> 134 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/ee/c6adcb2f3ceca0cadeccfe01b19382252ece9bbin0 -> 66 bytes
-rw-r--r--tests/resources/revert/.gitted/refs/heads/master2
-rw-r--r--tests/resources/revert/.gitted/refs/heads/two1
-rw-r--r--tests/revert/workdir.c206
90 files changed, 836 insertions, 247 deletions
diff --git a/include/git2/checkout.h b/include/git2/checkout.h
index b94a5e2ff..0faf4ab14 100644
--- a/include/git2/checkout.h
+++ b/include/git2/checkout.h
@@ -152,6 +152,12 @@ typedef enum {
/** Don't overwrite ignored files that exist in the checkout target */
GIT_CHECKOUT_DONT_OVERWRITE_IGNORED = (1u << 19),
+ /** Write normal merge files for conflicts */
+ GIT_CHECKOUT_CONFLICT_STYLE_MERGE = (1u << 20),
+
+ /** Include common ancestor data in diff3 format files for conflicts */
+ GIT_CHECKOUT_CONFLICT_STYLE_DIFF3 = (1u << 21),
+
/**
* THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED
*/
@@ -252,6 +258,7 @@ typedef struct git_checkout_opts {
const char *target_directory; /** alternative checkout path to workdir */
+ const char *ancestor_label; /** the name of the common ancestor side of conflicts */
const char *our_label; /** the name of the "our" side of conflicts */
const char *their_label; /** the name of the "their" side of conflicts */
} git_checkout_opts;
diff --git a/include/git2/merge.h b/include/git2/merge.h
index 8a1dfec2e..ad9b5e2ea 100644
--- a/include/git2/merge.h
+++ b/include/git2/merge.h
@@ -32,14 +32,21 @@ typedef enum {
} git_merge_tree_flag_t;
/**
- * Automerge options for `git_merge_trees_opts`.
+ * Merge file options for `git_merge_trees_opts`.
*/
typedef enum {
- GIT_MERGE_AUTOMERGE_NORMAL = 0,
- GIT_MERGE_AUTOMERGE_NONE = 1,
- GIT_MERGE_AUTOMERGE_FAVOR_OURS = 2,
- GIT_MERGE_AUTOMERGE_FAVOR_THEIRS = 3,
-} git_merge_automerge_flags;
+ /* Produce a conflict in a file when two similar regions are changed. */
+ GIT_MERGE_FILE_FAVOR_NORMAL = 0,
+
+ /* Produce a file containing the "ours" side of conflicting regions. */
+ GIT_MERGE_FILE_FAVOR_OURS = 1,
+
+ /* Produce a file containing the "theirs" side of conflicting regions. */
+ GIT_MERGE_FILE_FAVOR_THEIRS = 2,
+
+ /* Produce a file blending the sides in a union of conflicting regions */
+ GIT_MERGE_FILE_FAVOR_UNION = 3,
+} git_merge_file_favor_t;
typedef struct {
@@ -58,7 +65,7 @@ typedef struct {
git_diff_similarity_metric *metric;
/** Flags for automerging content. */
- git_merge_automerge_flags automerge_flags;
+ git_merge_file_favor_t file_favor;
} git_merge_tree_opts;
#define GIT_MERGE_TREE_OPTS_VERSION 1
diff --git a/src/checkout.c b/src/checkout.c
index e642c975e..cfb0e72ab 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -70,7 +70,9 @@ typedef struct {
int name_collision:1,
directoryfile:1,
- one_to_two:1;
+ one_to_two:1,
+ binary:1,
+ submodule:1;
} checkout_conflictdata;
static int checkout_notify(
@@ -681,6 +683,51 @@ GIT_INLINE(bool) conflict_pathspec_match(
return false;
}
+GIT_INLINE(int) checkout_conflict_detect_submodule(checkout_conflictdata *conflict)
+{
+ conflict->submodule = ((conflict->ancestor && S_ISGITLINK(conflict->ancestor->mode)) ||
+ (conflict->ours && S_ISGITLINK(conflict->ours->mode)) ||
+ (conflict->theirs && S_ISGITLINK(conflict->theirs->mode)));
+ return 0;
+}
+
+GIT_INLINE(int) checkout_conflict_detect_binary(git_repository *repo, checkout_conflictdata *conflict)
+{
+ git_blob *ancestor_blob = NULL, *our_blob = NULL, *their_blob = NULL;
+ int error = 0;
+
+ if (conflict->submodule)
+ return 0;
+
+ if (conflict->ancestor) {
+ if ((error = git_blob_lookup(&ancestor_blob, repo, &conflict->ancestor->oid)) < 0)
+ goto done;
+
+ conflict->binary = git_blob_is_binary(ancestor_blob);
+ }
+
+ if (!conflict->binary && conflict->ours) {
+ if ((error = git_blob_lookup(&our_blob, repo, &conflict->ours->oid)) < 0)
+ goto done;
+
+ conflict->binary = git_blob_is_binary(our_blob);
+ }
+
+ if (!conflict->binary && conflict->theirs) {
+ if ((error = git_blob_lookup(&their_blob, repo, &conflict->theirs->oid)) < 0)
+ goto done;
+
+ conflict->binary = git_blob_is_binary(their_blob);
+ }
+
+done:
+ git_blob_free(ancestor_blob);
+ git_blob_free(our_blob);
+ git_blob_free(their_blob);
+
+ return error;
+}
+
static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, git_vector *pathspec)
{
git_index_conflict_iterator *iterator = NULL;
@@ -705,6 +752,10 @@ static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, g
conflict->ours = ours;
conflict->theirs = theirs;
+ if ((error = checkout_conflict_detect_submodule(conflict)) < 0 ||
+ (error = checkout_conflict_detect_binary(data->repo, conflict)) < 0)
+ goto done;
+
git_vector_insert(&data->conflicts, conflict);
}
@@ -1626,6 +1677,7 @@ static int checkout_write_merge(
{
git_buf our_label = GIT_BUF_INIT, their_label = GIT_BUF_INIT,
path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT;
+ git_merge_file_options merge_file_opts = GIT_MERGE_FILE_OPTIONS_INIT;
git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
ours = GIT_MERGE_FILE_INPUT_INIT,
theirs = GIT_MERGE_FILE_INPUT_INIT;
@@ -1633,6 +1685,9 @@ static int checkout_write_merge(
git_filebuf output = GIT_FILEBUF_INIT;
int error = 0;
+ if (data->opts.checkout_strategy & GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)
+ merge_file_opts.style = GIT_MERGE_FILE_STYLE_DIFF3;
+
if ((conflict->ancestor &&
(error = git_merge_file_input_from_index_entry(
&ancestor, data->repo, conflict->ancestor)) < 0) ||
@@ -1642,7 +1697,7 @@ static int checkout_write_merge(
&theirs, data->repo, conflict->theirs)) < 0)
goto done;
- ancestor.label = NULL;
+ ancestor.label = data->opts.ancestor_label ? data->opts.ancestor_label : "ancestor";
ours.label = data->opts.our_label ? data->opts.our_label : "ours";
theirs.label = data->opts.their_label ? data->opts.their_label : "theirs";
@@ -1662,7 +1717,7 @@ static int checkout_write_merge(
theirs.label = git_buf_cstr(&their_label);
}
- if ((error = git_merge_files(&result, &ancestor, &ours, &theirs, 0)) < 0)
+ if ((error = git_merge_files(&result, &ancestor, &ours, &theirs, &merge_file_opts)) < 0)
goto done;
if (result.path == NULL || result.mode == 0) {
@@ -1705,6 +1760,7 @@ static int checkout_create_conflicts(checkout_data *data)
int error = 0;
git_vector_foreach(&data->conflicts, i, conflict) {
+
/* Both deleted: nothing to do */
if (conflict->ours == NULL && conflict->theirs == NULL)
error = 0;
@@ -1748,7 +1804,15 @@ static int checkout_create_conflicts(checkout_data *data)
else if (S_ISLNK(conflict->theirs->mode))
error = checkout_write_entry(data, conflict, conflict->ours);
- else
+ /* If any side is a gitlink, do nothing. */
+ else if (conflict->submodule)
+ error = 0;
+
+ /* If any side is binary, write the ours side */
+ else if (conflict->binary)
+ error = checkout_write_entry(data, conflict, conflict->ours);
+
+ else if (!error)
error = checkout_write_merge(data, conflict);
if (error)
@@ -1891,6 +1955,29 @@ static int checkout_data_init(
goto cleanup;
}
+ if ((data->opts.checkout_strategy &
+ (GIT_CHECKOUT_CONFLICT_STYLE_MERGE | GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)) == 0) {
+ const char *conflict_style;
+ git_config *cfg = NULL;
+
+ if ((error = git_repository_config__weakptr(&cfg, repo)) < 0 ||
+ (error = git_config_get_string(&conflict_style, cfg, "merge.conflictstyle")) < 0 ||
+ error == GIT_ENOTFOUND)
+ ;
+ else if (error)
+ goto cleanup;
+ else if (strcmp(conflict_style, "merge") == 0)
+ data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_MERGE;
+ else if (strcmp(conflict_style, "diff3") == 0)
+ data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_DIFF3;
+ else {
+ giterr_set(GITERR_CHECKOUT, "unknown style '%s' given for 'merge.conflictstyle'",
+ conflict_style);
+ error = -1;
+ goto cleanup;
+ }
+ }
+
if ((error = git_vector_init(&data->removes, 0, git__strcmp_cb)) < 0 ||
(error = git_vector_init(&data->conflicts, 0, NULL)) < 0 ||
(error = git_pool_init(&data->pool, 1, 0)) < 0 ||
diff --git a/src/merge.c b/src/merge.c
index c0be37dd8..2fb1c5898 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -42,6 +42,7 @@
#include "git2/sys/index.h"
#define GIT_MERGE_INDEX_ENTRY_EXISTS(X) ((X).mode != 0)
+#define GIT_MERGE_INDEX_ENTRY_ISFILE(X) S_ISREG((X).mode)
typedef enum {
TREE_IDX_ANCESTOR = 0,
@@ -447,7 +448,6 @@ static int merge_conflict_resolve_one_removed(
return error;
}
-
static int merge_conflict_resolve_one_renamed(
int *resolved,
git_merge_diff_list *diff_list,
@@ -511,8 +511,9 @@ static int merge_conflict_resolve_automerge(
int *resolved,
git_merge_diff_list *diff_list,
const git_merge_diff *conflict,
- unsigned int automerge_flags)
+ unsigned int merge_file_favor)
{
+ git_merge_file_options merge_file_opts = GIT_MERGE_FILE_OPTIONS_INIT;
git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
ours = GIT_MERGE_FILE_INPUT_INIT,
theirs = GIT_MERGE_FILE_INPUT_INIT;
@@ -526,13 +527,18 @@ static int merge_conflict_resolve_automerge(
*resolved = 0;
- if (automerge_flags == GIT_MERGE_AUTOMERGE_NONE)
- return 0;
+ merge_file_opts.favor = merge_file_favor;
/* Reject D/F conflicts */
if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE)
return 0;
+ /* Reject submodules. */
+ if (S_ISGITLINK(conflict->ancestor_entry.mode) ||
+ S_ISGITLINK(conflict->our_entry.mode) ||
+ S_ISGITLINK(conflict->their_entry.mode))
+ return 0;
+
/* Reject link/file conflicts. */
if ((S_ISLNK(conflict->ancestor_entry.mode) ^ S_ISLNK(conflict->our_entry.mode)) ||
(S_ISLNK(conflict->ancestor_entry.mode) ^ S_ISLNK(conflict->their_entry.mode)))
@@ -548,11 +554,15 @@ static int merge_conflict_resolve_automerge(
strcmp(conflict->ancestor_entry.path, conflict->their_entry.path) != 0)
return 0;
+ /* Reject binary conflicts */
+ if (conflict->binary)
+ return 0;
+
if ((error = git_repository_odb(&odb, diff_list->repo)) < 0 ||
(error = git_merge_file_input_from_index_entry(&ancestor, diff_list->repo, &conflict->ancestor_entry)) < 0 ||
(error = git_merge_file_input_from_index_entry(&ours, diff_list->repo, &conflict->our_entry)) < 0 ||
(error = git_merge_file_input_from_index_entry(&theirs, diff_list->repo, &conflict->their_entry)) < 0 ||
- (error = git_merge_files(&result, &ancestor, &ours, &theirs, automerge_flags)) < 0 ||
+ (error = git_merge_files(&result, &ancestor, &ours, &theirs, &merge_file_opts)) < 0 ||
!result.automergeable ||
(error = git_odb_write(&automerge_oid, odb, result.data, result.len, GIT_OBJ_BLOB)) < 0)
goto done;
@@ -586,7 +596,7 @@ static int merge_conflict_resolve(
int *out,
git_merge_diff_list *diff_list,
const git_merge_diff *conflict,
- unsigned int automerge_flags)
+ unsigned int merge_file_favor)
{
int resolved = 0;
int error = 0;
@@ -596,16 +606,14 @@ static int merge_conflict_resolve(
if ((error = merge_conflict_resolve_trivial(&resolved, diff_list, conflict)) < 0)
goto done;
- if (automerge_flags != GIT_MERGE_AUTOMERGE_NONE) {
- if (!resolved && (error = merge_conflict_resolve_one_removed(&resolved, diff_list, conflict)) < 0)
- goto done;
+ if (!resolved && (error = merge_conflict_resolve_one_removed(&resolved, diff_list, conflict)) < 0)
+ goto done;
- if (!resolved && (error = merge_conflict_resolve_one_renamed(&resolved, diff_list, conflict)) < 0)
- goto done;
+ 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, automerge_flags)) < 0)
- goto done;
- }
+ if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict, merge_file_favor)) < 0)
+ goto done;
*out = resolved;
@@ -1147,6 +1155,44 @@ GIT_INLINE(int) merge_diff_detect_type(
return 0;
}
+GIT_INLINE(int) merge_diff_detect_binary(
+ git_repository *repo,
+ git_merge_diff *conflict)
+{
+ git_blob *ancestor_blob = NULL, *our_blob = NULL, *their_blob = NULL;
+ int error = 0;
+
+ if (GIT_MERGE_INDEX_ENTRY_ISFILE(conflict->ancestor_entry)) {
+ if ((error = git_blob_lookup(&ancestor_blob, repo, &conflict->ancestor_entry.oid)) < 0)
+ goto done;
+
+ conflict->binary = git_blob_is_binary(ancestor_blob);
+ }
+
+ if (!conflict->binary &&
+ GIT_MERGE_INDEX_ENTRY_ISFILE(conflict->our_entry)) {
+ if ((error = git_blob_lookup(&our_blob, repo, &conflict->our_entry.oid)) < 0)
+ goto done;
+
+ conflict->binary = git_blob_is_binary(our_blob);
+ }
+
+ if (!conflict->binary &&
+ GIT_MERGE_INDEX_ENTRY_ISFILE(conflict->their_entry)) {
+ if ((error = git_blob_lookup(&their_blob, repo, &conflict->their_entry.oid)) < 0)
+ goto done;
+
+ conflict->binary = git_blob_is_binary(their_blob);
+ }
+
+done:
+ git_blob_free(ancestor_blob);
+ git_blob_free(our_blob);
+ git_blob_free(their_blob);
+
+ return error;
+}
+
GIT_INLINE(int) index_entry_dup(
git_index_entry *out,
git_pool *pool,
@@ -1218,6 +1264,7 @@ static int merge_diff_list_insert_conflict(
if ((conflict = merge_diff_from_index_entries(diff_list, tree_items)) == NULL ||
merge_diff_detect_type(conflict) < 0 ||
merge_diff_detect_df_conflict(merge_df_data, conflict) < 0 ||
+ merge_diff_detect_binary(diff_list->repo, conflict) < 0 ||
git_vector_insert(&diff_list->conflicts, conflict) < 0)
return -1;
@@ -1589,7 +1636,7 @@ int git_merge_trees(
git_vector_foreach(&changes, i, conflict) {
int resolved = 0;
- if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.automerge_flags)) < 0)
+ if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.file_favor)) < 0)
goto done;
if (!resolved)
@@ -2119,6 +2166,8 @@ static int merge_normalize_opts(
git_repository *repo,
git_merge_opts *opts,
const git_merge_opts *given,
+ const git_merge_head *ancestor_head,
+ const git_merge_head *our_head,
size_t their_heads_len,
const git_merge_head **their_heads)
{
@@ -2138,8 +2187,20 @@ static int merge_normalize_opts(
if (!opts->checkout_opts.checkout_strategy)
opts->checkout_opts.checkout_strategy = default_checkout_strategy;
- if (!opts->checkout_opts.our_label)
- opts->checkout_opts.our_label = "HEAD";
+ /* TODO: for multiple ancestors in merge-recursive, this is "merged common ancestors" */
+ if (!opts->checkout_opts.ancestor_label) {
+ if (ancestor_head && ancestor_head->commit)
+ opts->checkout_opts.ancestor_label = git_commit_summary(ancestor_head->commit);
+ else
+ opts->checkout_opts.ancestor_label = "ancestor";
+ }
+
+ if (!opts->checkout_opts.our_label) {
+ if (our_head && our_head->ref_name)
+ opts->checkout_opts.our_label = our_head->ref_name;
+ else
+ opts->checkout_opts.our_label = "ours";
+ }
if (!opts->checkout_opts.their_label) {
if (their_heads_len == 1 && their_heads[0]->ref_name)
@@ -2434,9 +2495,6 @@ int git_merge(
their_trees = git__calloc(their_heads_len, sizeof(git_tree *));
GITERR_CHECK_ALLOC(their_trees);
- if ((error = merge_normalize_opts(repo, &opts, given_opts, their_heads_len, their_heads)) < 0)
- goto on_error;
-
if ((error = git_repository__ensure_not_bare(repo, "merge")) < 0)
goto on_error;
@@ -2448,6 +2506,9 @@ int git_merge(
error != GIT_ENOTFOUND)
goto on_error;
+ if ((error = merge_normalize_opts(repo, &opts, given_opts, ancestor_head, our_head, their_heads_len, their_heads)) < 0)
+ goto on_error;
+
if (their_heads_len == 1 &&
ancestor_head != NULL &&
(merge_check_uptodate(result, ancestor_head, their_heads[0]) ||
diff --git a/src/merge.h b/src/merge.h
index b240f6c44..dda023528 100644
--- a/src/merge.h
+++ b/src/merge.h
@@ -106,6 +106,8 @@ typedef struct {
git_index_entry their_entry;
git_delta_t their_status;
+
+ int binary:1;
} git_merge_diff;
/** Internal structure for merge inputs */
diff --git a/src/merge_file.c b/src/merge_file.c
index 48fc46e57..9961ef297 100644
--- a/src/merge_file.c
+++ b/src/merge_file.c
@@ -130,7 +130,7 @@ int git_merge_files(
git_merge_file_input *ancestor,
git_merge_file_input *ours,
git_merge_file_input *theirs,
- git_merge_automerge_flags flags)
+ git_merge_file_options *opts)
{
xmparam_t xmparam;
mmbuffer_t mmbuffer;
@@ -152,11 +152,19 @@ int git_merge_files(
out->path = merge_file_best_path(ancestor, ours, theirs);
out->mode = merge_file_best_mode(ancestor, ours, theirs);
- if (flags == GIT_MERGE_AUTOMERGE_FAVOR_OURS)
+ if (opts && opts->favor == GIT_MERGE_FILE_FAVOR_OURS)
xmparam.favor = XDL_MERGE_FAVOR_OURS;
-
- if (flags == GIT_MERGE_AUTOMERGE_FAVOR_THEIRS)
+ else if (opts && opts->favor == GIT_MERGE_FILE_FAVOR_THEIRS)
xmparam.favor = XDL_MERGE_FAVOR_THEIRS;
+ else if (opts && opts->favor == GIT_MERGE_FILE_FAVOR_UNION)
+ xmparam.favor = XDL_MERGE_FAVOR_UNION;
+
+ xmparam.level =
+ (opts && (opts->flags & GIT_MERGE_FILE_SIMPLIFY_ALNUM)) ?
+ XDL_MERGE_ZEALOUS_ALNUM : XDL_MERGE_ZEALOUS;
+
+ if (opts && opts->style == GIT_MERGE_FILE_STYLE_DIFF3)
+ xmparam.style = XDL_MERGE_DIFF3;
if ((xdl_result = xdl_merge(&ancestor->mmfile, &ours->mmfile,
&theirs->mmfile, &xmparam, &mmbuffer)) < 0) {
diff --git a/src/merge_file.h b/src/merge_file.h
index 0af2f0a57..332be490b 100644
--- a/src/merge_file.h
+++ b/src/merge_file.h
@@ -34,6 +34,27 @@ typedef struct {
#define GIT_MERGE_FILE_RESULT_INIT {0}
+typedef enum {
+ /* Condense non-alphanumeric regions for simplified diff file */
+ GIT_MERGE_FILE_SIMPLIFY_ALNUM = (1 << 0),
+} git_merge_file_flags_t;
+
+typedef enum {
+ /* Create standard conflicted merge files */
+ GIT_MERGE_FILE_STYLE_MERGE = 0,
+
+ /* Create diff3-style files */
+ GIT_MERGE_FILE_STYLE_DIFF3 = 1,
+} git_merge_file_style_t;
+
+typedef struct {
+ git_merge_file_favor_t favor;
+ git_merge_file_flags_t flags;
+ git_merge_file_style_t style;
+} git_merge_file_options;
+
+#define GIT_MERGE_FILE_OPTIONS_INIT {0}
+
int git_merge_file_input_from_index_entry(
git_merge_file_input *input,
git_repository *repo,
@@ -49,7 +70,7 @@ int git_merge_files(
git_merge_file_input *ancestor,
git_merge_file_input *ours,
git_merge_file_input *theirs,
- git_merge_automerge_flags flags);
+ git_merge_file_options *opts);
GIT_INLINE(void) git_merge_file_input_free(git_merge_file_input *input)
{
diff --git a/tests/merge/trees/automerge.c b/tests/merge/trees/automerge.c
index 746ce5068..ebc6e271d 100644
--- a/tests/merge/trees/automerge.c
+++ b/tests/merge/trees/automerge.c
@@ -149,7 +149,7 @@ void test_merge_trees_automerge__favor_ours(void)
REMOVED_IN_MASTER_REUC_ENTRY,
};
- opts.automerge_flags = GIT_MERGE_AUTOMERGE_FAVOR_OURS;
+ opts.file_favor = GIT_MERGE_FILE_FAVOR_OURS;
cl_git_pass(merge_trees_from_branches(&index, repo, "master", THEIRS_AUTOMERGE_BRANCH, &opts));
@@ -180,7 +180,7 @@ void test_merge_trees_automerge__favor_theirs(void)
REMOVED_IN_MASTER_REUC_ENTRY,
};
- opts.automerge_flags = GIT_MERGE_AUTOMERGE_FAVOR_THEIRS;
+ opts.file_favor = GIT_MERGE_FILE_FAVOR_THEIRS;
cl_git_pass(merge_trees_from_branches(&index, repo, "master", THEIRS_AUTOMERGE_BRANCH, &opts));
diff --git a/tests/merge/trees/trivial.c b/tests/merge/trees/trivial.c
index bfd5dfed3..2de187bf4 100644
--- a/tests/merge/trees/trivial.c
+++ b/tests/merge/trees/trivial.c
@@ -25,7 +25,7 @@ void test_merge_trees_trivial__cleanup(void)
}
-static int merge_trivial(git_index **index, const char *ours, const char *theirs, bool automerge)
+static int merge_trivial(git_index **index, const char *ours, const char *theirs)
{
git_commit *our_commit, *their_commit, *ancestor_commit;
git_tree *our_tree, *their_tree, *ancestor_tree;
@@ -33,8 +33,6 @@ static int merge_trivial(git_index **index, const char *ours, const char *theirs
git_buf branch_buf = GIT_BUF_INIT;
git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT;
- opts.automerge_flags |= automerge ? 0 : GIT_MERGE_AUTOMERGE_NONE;
-
git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours);
cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr));
cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid));
@@ -86,7 +84,7 @@ void test_merge_trees_trivial__2alt(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-2alt", "trivial-2alt-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-2alt", "trivial-2alt-branch"));
cl_assert(entry = git_index_get_bypath(result, "new-in-branch.txt", 0));
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -101,7 +99,7 @@ void test_merge_trees_trivial__3alt(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-3alt", "trivial-3alt-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-3alt", "trivial-3alt-branch"));
cl_assert(entry = git_index_get_bypath(result, "new-in-3alt.txt", 0));
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -116,7 +114,7 @@ void test_merge_trees_trivial__4(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-4", "trivial-4-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-4", "trivial-4-branch"));
cl_assert((entry = git_index_get_bypath(result, "new-and-different.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -134,7 +132,7 @@ void test_merge_trees_trivial__5alt_1(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-5alt-1", "trivial-5alt-1-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-5alt-1", "trivial-5alt-1-branch"));
cl_assert(entry = git_index_get_bypath(result, "new-and-same.txt", 0));
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -149,7 +147,7 @@ void test_merge_trees_trivial__5alt_2(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-5alt-2", "trivial-5alt-2-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-5alt-2", "trivial-5alt-2-branch"));
cl_assert(entry = git_index_get_bypath(result, "modified-to-same.txt", 0));
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -163,26 +161,9 @@ void test_merge_trees_trivial__6(void)
{
git_index *result;
const git_index_entry *entry;
-
- cl_git_pass(merge_trivial(&result, "trivial-6", "trivial-6-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(result, "removed-in-both.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(result) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount(result) == 1);
- cl_assert(entry = git_index_get_bypath(result, "removed-in-both.txt", 1));
-
- git_index_free(result);
-}
-
-/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */
-void test_merge_trees_trivial__6_automerge(void)
-{
- git_index *result;
- const git_index_entry *entry;
const git_index_reuc_entry *reuc;
- cl_git_pass(merge_trivial(&result, "trivial-6", "trivial-6-branch", 1));
+ cl_git_pass(merge_trivial(&result, "trivial-6", "trivial-6-branch"));
cl_assert((entry = git_index_get_bypath(result, "removed-in-both.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(result) == 1);
@@ -198,27 +179,9 @@ void test_merge_trees_trivial__8(void)
{
git_index *result;
const git_index_entry *entry;
-
- cl_git_pass(merge_trivial(&result, "trivial-8", "trivial-8-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(result, "removed-in-8.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(result) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount(result) == 2);
- cl_assert(entry = git_index_get_bypath(result, "removed-in-8.txt", 1));
- cl_assert(entry = git_index_get_bypath(result, "removed-in-8.txt", 3));
-
- git_index_free(result);
-}
-
-/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */
-void test_merge_trees_trivial__8_automerge(void)
-{
- git_index *result;
- const git_index_entry *entry;
const git_index_reuc_entry *reuc;
- cl_git_pass(merge_trivial(&result, "trivial-8", "trivial-8-branch", 1));
+ cl_git_pass(merge_trivial(&result, "trivial-8", "trivial-8-branch"));
cl_assert((entry = git_index_get_bypath(result, "removed-in-8.txt", 0)) == NULL);
@@ -236,25 +199,7 @@ void test_merge_trees_trivial__7(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-7", "trivial-7-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(result, "removed-in-7.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(result) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount(result) == 2);
- cl_assert(entry = git_index_get_bypath(result, "removed-in-7.txt", 1));
- cl_assert(entry = git_index_get_bypath(result, "removed-in-7.txt", 3));
-
- git_index_free(result);
-}
-
-/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */
-void test_merge_trees_trivial__7_automerge(void)
-{
- git_index *result;
- const git_index_entry *entry;
-
- cl_git_pass(merge_trivial(&result, "trivial-7", "trivial-7-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-7", "trivial-7-branch"));
cl_assert((entry = git_index_get_bypath(result, "removed-in-7.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -271,27 +216,9 @@ void test_merge_trees_trivial__10(void)
{
git_index *result;
const git_index_entry *entry;
-
- cl_git_pass(merge_trivial(&result, "trivial-10", "trivial-10-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(result) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount(result) == 2);
- cl_assert(entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 1));
- cl_assert(entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 2));
-
- git_index_free(result);
-}
-
-/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */
-void test_merge_trees_trivial__10_automerge(void)
-{
- git_index *result;
- const git_index_entry *entry;
const git_index_reuc_entry *reuc;
- cl_git_pass(merge_trivial(&result, "trivial-10", "trivial-10-branch", 1));
+ cl_git_pass(merge_trivial(&result, "trivial-10", "trivial-10-branch"));
cl_assert((entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 0)) == NULL);
@@ -309,25 +236,7 @@ void test_merge_trees_trivial__9(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-9", "trivial-9-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(result) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount(result) == 2);
- cl_assert(entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 1));
- cl_assert(entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 2));
-
- git_index_free(result);
-}
-
-/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */
-void test_merge_trees_trivial__9_automerge(void)
-{
- git_index *result;
- const git_index_entry *entry;
-
- cl_git_pass(merge_trivial(&result, "trivial-9", "trivial-9-branch", 1));
+ cl_git_pass(merge_trivial(&result, "trivial-9", "trivial-9-branch"));
cl_assert((entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -346,7 +255,7 @@ void test_merge_trees_trivial__13(void)
const git_index_entry *entry;
git_oid expected_oid;
- cl_git_pass(merge_trivial(&result, "trivial-13", "trivial-13-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-13", "trivial-13-branch"));
cl_assert(entry = git_index_get_bypath(result, "modified-in-13.txt", 0));
cl_git_pass(git_oid_fromstr(&expected_oid, "1cff9ec6a47a537380dedfdd17c9e76d74259a2b"));
@@ -365,7 +274,7 @@ void test_merge_trees_trivial__14(void)
const git_index_entry *entry;
git_oid expected_oid;
- cl_git_pass(merge_trivial(&result, "trivial-14", "trivial-14-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-14", "trivial-14-branch"));
cl_assert(entry = git_index_get_bypath(result, "modified-in-14-branch.txt", 0));
cl_git_pass(git_oid_fromstr(&expected_oid, "26153a3ff3649b6c2bb652d3f06878c6e0a172f9"));
@@ -383,7 +292,7 @@ void test_merge_trees_trivial__11(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-11", "trivial-11-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-11", "trivial-11-branch"));
cl_assert((entry = git_index_get_bypath(result, "modified-in-both.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(result) == 0);
diff --git a/tests/merge/workdir/simple.c b/tests/merge/workdir/simple.c
index 98dca53ef..6b152cc4d 100644
--- a/tests/merge/workdir/simple.c
+++ b/tests/merge/workdir/simple.c
@@ -93,13 +93,26 @@ static git_index *repo_index;
"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"
+
// Fixture setup and teardown
void test_merge_workdir_simple__initialize(void)
{
@@ -113,7 +126,7 @@ void test_merge_workdir_simple__cleanup(void)
cl_git_sandbox_cleanup();
}
-static git_merge_result *merge_simple_branch(int automerge_flags, int checkout_strategy)
+static git_merge_result *merge_simple_branch(int merge_file_favor, int checkout_strategy)
{
git_oid their_oids[1];
git_merge_head *their_heads[1];
@@ -123,7 +136,7 @@ static git_merge_result *merge_simple_branch(int automerge_flags, int checkout_s
cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_SIMPLE_OID));
cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0]));
- opts.merge_tree_opts.automerge_flags = automerge_flags;
+ opts.merge_tree_opts.file_favor = merge_file_favor;
opts.checkout_opts.checkout_strategy = checkout_strategy;
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts));
@@ -244,6 +257,44 @@ void test_merge_workdir_simple__automerge_crlf(void)
#endif /* GIT_WIN32 */
}
+void test_merge_workdir_simple__mergefile(void)
+{
+ git_merge_result *result;
+ git_buf conflicting_buf = GIT_BUF_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ ADDED_IN_MASTER_INDEX_ENTRY,
+ AUTOMERGEABLE_INDEX_ENTRY,
+ CHANGED_IN_BRANCH_INDEX_ENTRY,
+ CHANGED_IN_MASTER_INDEX_ENTRY,
+
+ { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" },
+ { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" },
+ { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" },
+
+ UNCHANGED_INDEX_ENTRY,
+ };
+
+ struct merge_reuc_entry merge_reuc_entries[] = {
+ AUTOMERGEABLE_REUC_ENTRY,
+ REMOVED_IN_BRANCH_REUC_ENTRY,
+ REMOVED_IN_MASTER_REUC_ENTRY
+ };
+
+ cl_assert(result = merge_simple_branch(0, 0));
+ cl_assert(!git_merge_result_is_fastforward(result));
+
+ cl_git_pass(git_futils_readbuffer(&conflicting_buf,
+ TEST_REPO_PATH "/conflicting.txt"));
+ cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_MERGE_FILE) == 0);
+ git_buf_free(&conflicting_buf);
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
+ cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
+
+ git_merge_result_free(result);
+}
+
void test_merge_workdir_simple__diff3(void)
{
git_merge_result *result;
@@ -268,6 +319,87 @@ void test_merge_workdir_simple__diff3(void)
REMOVED_IN_MASTER_REUC_ENTRY
};
+ cl_assert(result = merge_simple_branch(0, GIT_CHECKOUT_CONFLICT_STYLE_DIFF3));
+ cl_assert(!git_merge_result_is_fastforward(result));
+
+ cl_git_pass(git_futils_readbuffer(&conflicting_buf,
+ TEST_REPO_PATH "/conflicting.txt"));
+ cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_DIFF3_FILE) == 0);
+ git_buf_free(&conflicting_buf);
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
+ cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
+
+ git_merge_result_free(result);
+}
+
+void test_merge_workdir_simple__union(void)
+{
+ git_merge_result *result;
+ git_buf conflicting_buf = GIT_BUF_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ ADDED_IN_MASTER_INDEX_ENTRY,
+ AUTOMERGEABLE_INDEX_ENTRY,
+ CHANGED_IN_BRANCH_INDEX_ENTRY,
+ CHANGED_IN_MASTER_INDEX_ENTRY,
+
+ { 0100644, "72cdb057b340205164478565e91eb71647e66891", 0, "conflicting.txt" },
+
+ UNCHANGED_INDEX_ENTRY,
+ };
+
+ struct merge_reuc_entry merge_reuc_entries[] = {
+ AUTOMERGEABLE_REUC_ENTRY,
+ CONFLICTING_REUC_ENTRY,
+ REMOVED_IN_BRANCH_REUC_ENTRY,
+ REMOVED_IN_MASTER_REUC_ENTRY
+ };
+
+ set_core_autocrlf_to(repo, false);
+
+ cl_assert(result = merge_simple_branch(GIT_MERGE_FILE_FAVOR_UNION, 0));
+ cl_assert(!git_merge_result_is_fastforward(result));
+
+ cl_git_pass(git_futils_readbuffer(&conflicting_buf,
+ TEST_REPO_PATH "/conflicting.txt"));
+ cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_UNION_FILE) == 0);
+ git_buf_free(&conflicting_buf);
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
+ cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4));
+
+ git_merge_result_free(result);
+}
+
+void test_merge_workdir_simple__diff3_from_config(void)
+{
+ git_merge_result *result;
+ git_config *config;
+ git_buf conflicting_buf = GIT_BUF_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ ADDED_IN_MASTER_INDEX_ENTRY,
+ AUTOMERGEABLE_INDEX_ENTRY,
+ CHANGED_IN_BRANCH_INDEX_ENTRY,
+ CHANGED_IN_MASTER_INDEX_ENTRY,
+
+ { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" },
+ { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" },
+ { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" },
+
+ UNCHANGED_INDEX_ENTRY,
+ };
+
+ struct merge_reuc_entry merge_reuc_entries[] = {
+ AUTOMERGEABLE_REUC_ENTRY,
+ REMOVED_IN_BRANCH_REUC_ENTRY,
+ REMOVED_IN_MASTER_REUC_ENTRY
+ };
+
+ cl_git_pass(git_repository_config(&config, repo));
+ cl_git_pass(git_config_set_string(config, "merge.conflictstyle", "diff3"));
+
cl_assert(result = merge_simple_branch(0, 0));
cl_assert(!git_merge_result_is_fastforward(result));
@@ -280,6 +412,50 @@ void test_merge_workdir_simple__diff3(void)
cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
git_merge_result_free(result);
+ git_config_free(config);
+}
+
+void test_merge_workdir_simple__merge_overrides_config(void)
+{
+ git_merge_result *result;
+ git_config *config;
+ git_buf conflicting_buf = GIT_BUF_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ ADDED_IN_MASTER_INDEX_ENTRY,
+ AUTOMERGEABLE_INDEX_ENTRY,
+ CHANGED_IN_BRANCH_INDEX_ENTRY,
+ CHANGED_IN_MASTER_INDEX_ENTRY,
+
+ { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" },
+ { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" },
+ { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" },
+
+ UNCHANGED_INDEX_ENTRY,
+ };
+
+ struct merge_reuc_entry merge_reuc_entries[] = {
+ AUTOMERGEABLE_REUC_ENTRY,
+ REMOVED_IN_BRANCH_REUC_ENTRY,
+ REMOVED_IN_MASTER_REUC_ENTRY
+ };
+
+ cl_git_pass(git_repository_config(&config, repo));
+ cl_git_pass(git_config_set_string(config, "merge.conflictstyle", "diff3"));
+
+ cl_assert(result = merge_simple_branch(0, GIT_CHECKOUT_CONFLICT_STYLE_MERGE));
+ cl_assert(!git_merge_result_is_fastforward(result));
+
+ cl_git_pass(git_futils_readbuffer(&conflicting_buf,
+ TEST_REPO_PATH "/conflicting.txt"));
+ cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_MERGE_FILE) == 0);
+ git_buf_free(&conflicting_buf);
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
+ cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
+
+ git_merge_result_free(result);
+ git_config_free(config);
}
void test_merge_workdir_simple__checkout_ours(void)
@@ -336,7 +512,7 @@ void test_merge_workdir_simple__favor_ours(void)
REMOVED_IN_MASTER_REUC_ENTRY,
};
- cl_assert(result = merge_simple_branch(GIT_MERGE_AUTOMERGE_FAVOR_OURS, 0));
+ cl_assert(result = merge_simple_branch(GIT_MERGE_FILE_FAVOR_OURS, 0));
cl_assert(!git_merge_result_is_fastforward(result));
cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
@@ -365,7 +541,7 @@ void test_merge_workdir_simple__favor_theirs(void)
REMOVED_IN_MASTER_REUC_ENTRY,
};
- cl_assert(result = merge_simple_branch(GIT_MERGE_AUTOMERGE_FAVOR_THEIRS, 0));
+ cl_assert(result = merge_simple_branch(GIT_MERGE_FILE_FAVOR_THEIRS, 0));
cl_assert(!git_merge_result_is_fastforward(result));
cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
@@ -414,7 +590,7 @@ void test_merge_workdir_simple__directory_file(void)
cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_DIRECTORY_FILE));
cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0]));
- opts.merge_tree_opts.automerge_flags = 0;
+ opts.merge_tree_opts.file_favor = 0;
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts));
cl_assert(merge_test_index(repo_index, merge_index_entries, 20));
@@ -447,7 +623,7 @@ void test_merge_workdir_simple__unrelated(void)
cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_PARENT));
cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0]));
- opts.merge_tree_opts.automerge_flags = 0;
+ opts.merge_tree_opts.file_favor = 0;
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts));
cl_assert(merge_test_index(repo_index, merge_index_entries, 9));
@@ -480,7 +656,7 @@ void test_merge_workdir_simple__unrelated_with_conflicts(void)
cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_OID));
cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0]));
- opts.merge_tree_opts.automerge_flags = 0;
+ opts.merge_tree_opts.file_favor = 0;
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts));
cl_assert(merge_test_index(repo_index, merge_index_entries, 11));
@@ -489,3 +665,40 @@ void test_merge_workdir_simple__unrelated_with_conflicts(void)
git_merge_result_free(result);
}
+void test_merge_workdir_simple__binary(void)
+{
+ git_oid our_oid, their_oid, our_file_oid;
+ git_commit *our_commit;
+ git_merge_head *their_head;
+ git_merge_result *result;
+ const git_index_entry *binary_entry;
+ git_merge_opts opts = GIT_MERGE_OPTS_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "1c51d885170f57a0c4e8c69ff6363d91a5b51f85", 1, "binary" },
+ { 0100644, "23ed141a6ae1e798b2f721afedbe947c119111ba", 2, "binary" },
+ { 0100644, "836b8b82b26cab22eaaed8820877c76d6c8bca19", 3, "binary" },
+ };
+
+ cl_git_pass(git_oid_fromstr(&our_oid, "cc338e4710c9b257106b8d16d82f86458d5beaf1"));
+ cl_git_pass(git_oid_fromstr(&their_oid, "ad01aebfdf2ac13145efafe3f9fcf798882f1730"));
+
+ cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid));
+ cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD));
+
+ cl_git_pass(git_merge_head_from_oid(&their_head, repo, &their_oid));
+
+ cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts));
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 3));
+
+ cl_git_pass(git_index_add_bypath(repo_index, "binary"));
+ cl_assert((binary_entry = git_index_get_bypath(repo_index, "binary", 0)) != NULL);
+
+ cl_git_pass(git_oid_fromstr(&our_file_oid, "23ed141a6ae1e798b2f721afedbe947c119111ba"));
+ cl_assert(git_oid_cmp(&binary_entry->oid, &our_file_oid) == 0);
+
+ git_merge_head_free(their_head);
+ git_merge_result_free(result);
+ git_commit_free(our_commit);
+}
diff --git a/tests/merge/workdir/submodules.c b/tests/merge/workdir/submodules.c
new file mode 100644
index 000000000..f01faac43
--- /dev/null
+++ b/tests/merge/workdir/submodules.c
@@ -0,0 +1,101 @@
+#include "clar_libgit2.h"
+#include "git2/repository.h"
+#include "git2/merge.h"
+#include "buffer.h"
+#include "merge.h"
+#include "../merge_helpers.h"
+
+static git_repository *repo;
+
+#define TEST_REPO_PATH "merge-resolve"
+
+#define SUBMODULE_MAIN_BRANCH "submodules"
+#define SUBMODULE_OTHER_BRANCH "submodules-branch"
+#define SUBMODULE_OTHER2_BRANCH "submodules-branch2"
+
+#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
+
+// Fixture setup and teardown
+void test_merge_workdir_submodules__initialize(void)
+{
+ repo = cl_git_sandbox_init(TEST_REPO_PATH);
+}
+
+void test_merge_workdir_submodules__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
+void test_merge_workdir_submodules__automerge(void)
+{
+ git_reference *our_ref, *their_ref;
+ git_commit *our_commit;
+ git_merge_head *their_head;
+ git_merge_result *result;
+ git_merge_opts opts = GIT_MERGE_OPTS_INIT;
+ git_index *index;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "caff6b7d44973f53e3e0cf31d0d695188b19aec6", 0, ".gitmodules" },
+ { 0100644, "950a663a6a7b2609eed1ed1ba9f41eb1a3192a9f", 0, "file1.txt" },
+ { 0100644, "343e660b9cb4bee5f407c2e33fcb9df24d9407a4", 0, "file2.txt" },
+ { 0160000, "d3d806a4bef96889117fd7ebac0e3cb5ec152932", 1, "submodule" },
+ { 0160000, "297aa6cd028b3336c7802c7a6f49143da4e1602d", 2, "submodule" },
+ { 0160000, "ae39c77c70cb6bad18bb471912460c4e1ba0f586", 3, "submodule" },
+ };
+
+ cl_git_pass(git_reference_lookup(&our_ref, repo, "refs/heads/" SUBMODULE_MAIN_BRANCH));
+ cl_git_pass(git_commit_lookup(&our_commit, repo, git_reference_target(our_ref)));
+ cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD));
+
+ cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_OTHER_BRANCH));
+ cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref));
+
+ cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts));
+
+ cl_git_pass(git_repository_index(&index, repo));
+ cl_assert(merge_test_index(index, merge_index_entries, 6));
+
+ git_index_free(index);
+ git_merge_result_free(result);
+ git_merge_head_free(their_head);
+ git_commit_free(our_commit);
+ git_reference_free(their_ref);
+ git_reference_free(our_ref);
+}
+
+void test_merge_workdir_submodules__take_changed(void)
+{
+ git_reference *our_ref, *their_ref;
+ git_commit *our_commit;
+ git_merge_head *their_head;
+ git_merge_result *result;
+ git_merge_opts opts = GIT_MERGE_OPTS_INIT;
+ git_index *index;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "caff6b7d44973f53e3e0cf31d0d695188b19aec6", 0, ".gitmodules" },
+ { 0100644, "b438ff23300b2e0f80b84a6f30140dfa91e71423", 0, "file1.txt" },
+ { 0100644, "f27fbafdfa6693f8f7a5128506fe3e338dbfcad2", 0, "file2.txt" },
+ { 0160000, "297aa6cd028b3336c7802c7a6f49143da4e1602d", 0, "submodule" },
+ };
+
+ cl_git_pass(git_reference_lookup(&our_ref, repo, "refs/heads/" SUBMODULE_MAIN_BRANCH));
+ cl_git_pass(git_commit_lookup(&our_commit, repo, git_reference_target(our_ref)));
+ cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD));
+
+ cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_OTHER2_BRANCH));
+ cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref));
+
+ cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts));
+
+ cl_git_pass(git_repository_index(&index, repo));
+ cl_assert(merge_test_index(index, merge_index_entries, 4));
+
+ git_index_free(index);
+ git_merge_result_free(result);
+ git_merge_head_free(their_head);
+ git_commit_free(our_commit);
+ git_reference_free(their_ref);
+ git_reference_free(our_ref);
+}
diff --git a/tests/merge/workdir/trivial.c b/tests/merge/workdir/trivial.c
index df18b0e0b..71437d48e 100644
--- a/tests/merge/workdir/trivial.c
+++ b/tests/merge/workdir/trivial.c
@@ -28,7 +28,7 @@ void test_merge_workdir_trivial__cleanup(void)
}
-static int merge_trivial(const char *ours, const char *theirs, bool automerge)
+static int merge_trivial(const char *ours, const char *theirs)
{
git_buf branch_buf = GIT_BUF_INIT;
git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT;
@@ -39,8 +39,6 @@ static int merge_trivial(const char *ours, const char *theirs, bool automerge)
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
- opts.merge_tree_opts.automerge_flags |= automerge ? 0 : GIT_MERGE_AUTOMERGE_NONE;
-
git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours);
cl_git_pass(git_reference_symbolic_create(&our_ref, repo, "HEAD", branch_buf.ptr, 1, NULL, NULL));
@@ -83,7 +81,7 @@ void test_merge_workdir_trivial__2alt(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-2alt", "trivial-2alt-branch", 0));
+ cl_git_pass(merge_trivial("trivial-2alt", "trivial-2alt-branch"));
cl_assert(entry = git_index_get_bypath(repo_index, "new-in-branch.txt", 0));
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -95,7 +93,7 @@ void test_merge_workdir_trivial__3alt(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-3alt", "trivial-3alt-branch", 0));
+ cl_git_pass(merge_trivial("trivial-3alt", "trivial-3alt-branch"));
cl_assert(entry = git_index_get_bypath(repo_index, "new-in-3alt.txt", 0));
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -107,7 +105,7 @@ void test_merge_workdir_trivial__4(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-4", "trivial-4-branch", 0));
+ cl_git_pass(merge_trivial("trivial-4", "trivial-4-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "new-and-different.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -122,7 +120,7 @@ void test_merge_workdir_trivial__5alt_1(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-5alt-1", "trivial-5alt-1-branch", 0));
+ cl_git_pass(merge_trivial("trivial-5alt-1", "trivial-5alt-1-branch"));
cl_assert(entry = git_index_get_bypath(repo_index, "new-and-same.txt", 0));
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -134,7 +132,7 @@ void test_merge_workdir_trivial__5alt_2(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-5alt-2", "trivial-5alt-2-branch", 0));
+ cl_git_pass(merge_trivial("trivial-5alt-2", "trivial-5alt-2-branch"));
cl_assert(entry = git_index_get_bypath(repo_index, "modified-to-same.txt", 0));
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -145,23 +143,9 @@ void test_merge_workdir_trivial__5alt_2(void)
void test_merge_workdir_trivial__6(void)
{
const git_index_entry *entry;
-
- cl_git_pass(merge_trivial("trivial-6", "trivial-6-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(repo_index) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount() == 1);
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 1));
-}
-
-/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */
-void test_merge_workdir_trivial__6_automerge(void)
-{
- const git_index_entry *entry;
const git_index_reuc_entry *reuc;
- cl_git_pass(merge_trivial("trivial-6", "trivial-6-branch", 1));
+ cl_git_pass(merge_trivial("trivial-6", "trivial-6-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(repo_index) == 1);
@@ -174,24 +158,9 @@ void test_merge_workdir_trivial__6_automerge(void)
void test_merge_workdir_trivial__8(void)
{
const git_index_entry *entry;
-
- cl_git_pass(merge_trivial("trivial-8", "trivial-8-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(repo_index) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount() == 2);
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 1));
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 3));
-}
-
-/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */
-void test_merge_workdir_trivial__8_automerge(void)
-{
- const git_index_entry *entry;
const git_index_reuc_entry *reuc;
- cl_git_pass(merge_trivial("trivial-8", "trivial-8-branch", 1));
+ cl_git_pass(merge_trivial("trivial-8", "trivial-8-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 0)) == NULL);
@@ -206,22 +175,7 @@ void test_merge_workdir_trivial__7(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-7", "trivial-7-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(repo_index) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount() == 2);
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 1));
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 3));
-}
-
-/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */
-void test_merge_workdir_trivial__7_automerge(void)
-{
- const git_index_entry *entry;
-
- cl_git_pass(merge_trivial("trivial-7", "trivial-7-branch", 0));
+ cl_git_pass(merge_trivial("trivial-7", "trivial-7-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -235,24 +189,9 @@ void test_merge_workdir_trivial__7_automerge(void)
void test_merge_workdir_trivial__10(void)
{
const git_index_entry *entry;
-
- cl_git_pass(merge_trivial("trivial-10", "trivial-10-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(repo_index) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount() == 2);
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 1));
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 2));
-}
-
-/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */
-void test_merge_workdir_trivial__10_automerge(void)
-{
- const git_index_entry *entry;
const git_index_reuc_entry *reuc;
- cl_git_pass(merge_trivial("trivial-10", "trivial-10-branch", 1));
+ cl_git_pass(merge_trivial("trivial-10", "trivial-10-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 0)) == NULL);
@@ -267,22 +206,7 @@ void test_merge_workdir_trivial__9(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-9", "trivial-9-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(repo_index) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount() == 2);
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 1));
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 2));
-}
-
-/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */
-void test_merge_workdir_trivial__9_automerge(void)
-{
- const git_index_entry *entry;
-
- cl_git_pass(merge_trivial("trivial-9", "trivial-9-branch", 1));
+ cl_git_pass(merge_trivial("trivial-9", "trivial-9-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -298,7 +222,7 @@ void test_merge_workdir_trivial__13(void)
const git_index_entry *entry;
git_oid expected_oid;
- cl_git_pass(merge_trivial("trivial-13", "trivial-13-branch", 0));
+ cl_git_pass(merge_trivial("trivial-13", "trivial-13-branch"));
cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-13.txt", 0));
cl_git_pass(git_oid_fromstr(&expected_oid, "1cff9ec6a47a537380dedfdd17c9e76d74259a2b"));
@@ -314,7 +238,7 @@ void test_merge_workdir_trivial__14(void)
const git_index_entry *entry;
git_oid expected_oid;
- cl_git_pass(merge_trivial("trivial-14", "trivial-14-branch", 0));
+ cl_git_pass(merge_trivial("trivial-14", "trivial-14-branch"));
cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-14-branch.txt", 0));
cl_git_pass(git_oid_fromstr(&expected_oid, "26153a3ff3649b6c2bb652d3f06878c6e0a172f9"));
@@ -329,7 +253,7 @@ void test_merge_workdir_trivial__11(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-11", "trivial-11-branch", 0));
+ cl_git_pass(merge_trivial("trivial-11", "trivial-11-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
diff --git a/tests/resources/merge-resolve/.gitted/config b/tests/resources/merge-resolve/.gitted/config
index af107929f..26c48426d 100644
--- a/tests/resources/merge-resolve/.gitted/config
+++ b/tests/resources/merge-resolve/.gitted/config
@@ -4,3 +4,5 @@
bare = false
logallrefupdates = true
ignorecase = true
+[submodule "submodule"]
+ url = ../submodule
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/HEAD b/tests/resources/merge-resolve/.gitted/modules/submodule/HEAD
new file mode 100644
index 000000000..cb089cd89
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/ORIG_HEAD b/tests/resources/merge-resolve/.gitted/modules/submodule/ORIG_HEAD
new file mode 100644
index 000000000..d1bfcf0f4
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/ORIG_HEAD
@@ -0,0 +1 @@
+ae39c77c70cb6bad18bb471912460c4e1ba0f586
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/config b/tests/resources/merge-resolve/.gitted/modules/submodule/config
new file mode 100644
index 000000000..575cc8599
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/config
@@ -0,0 +1,15 @@
+[core]
+ repositoryformatversion = 0
+ filemode = false
+ bare = false
+ logallrefupdates = true
+ worktree = ../../../submodule
+ symlinks = false
+ ignorecase = true
+ hideDotFiles = dotGitOnly
+[remote "origin"]
+ url = c:/Temp/TestRepos/submodule
+ fetch = +refs/heads/*:refs/remotes/origin/*
+[branch "master"]
+ remote = origin
+ merge = refs/heads/master
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/index b/tests/resources/merge-resolve/.gitted/modules/submodule/index
new file mode 100644
index 000000000..e948afb27
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/index
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/info/exclude b/tests/resources/merge-resolve/.gitted/modules/submodule/info/exclude
new file mode 100644
index 000000000..a5196d1be
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/info/exclude
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/18/fae1354bba0a5f1e6a531f9988369142c24a9e b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/18/fae1354bba0a5f1e6a531f9988369142c24a9e
new file mode 100644
index 000000000..fcf1c6381
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/18/fae1354bba0a5f1e6a531f9988369142c24a9e
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/29/7aa6cd028b3336c7802c7a6f49143da4e1602d b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/29/7aa6cd028b3336c7802c7a6f49143da4e1602d
new file mode 100644
index 000000000..aa9fc5006
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/29/7aa6cd028b3336c7802c7a6f49143da4e1602d
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/38/6c80dc813b89d719797668f40c1be0a6efa996 b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/38/6c80dc813b89d719797668f40c1be0a6efa996
new file mode 100644
index 000000000..bc9a32ebc
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/38/6c80dc813b89d719797668f40c1be0a6efa996
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ab/435a147bae6d5906ecfd0916a570c4ab3eeea8 b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ab/435a147bae6d5906ecfd0916a570c4ab3eeea8
new file mode 100644
index 000000000..65a8d759f
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ab/435a147bae6d5906ecfd0916a570c4ab3eeea8
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ad/16e0a7684ea95bf892980a2ee412293ae979cc b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ad/16e0a7684ea95bf892980a2ee412293ae979cc
new file mode 100644
index 000000000..49e1aafeb
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ad/16e0a7684ea95bf892980a2ee412293ae979cc
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ae/39c77c70cb6bad18bb471912460c4e1ba0f586 b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ae/39c77c70cb6bad18bb471912460c4e1ba0f586
new file mode 100644
index 000000000..6ceffdd4e
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ae/39c77c70cb6bad18bb471912460c4e1ba0f586
@@ -0,0 +1,2 @@
+x !@=S hf%x! ]k/{k-a] xWs =,lP
+#g0KIC ,51 9;alB=>|h}_{{Me?u6">:叄ʃ6^Kd \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/c2/0765f6e24e8bbb63a648d0d11d84da63170190 b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/c2/0765f6e24e8bbb63a648d0d11d84da63170190
new file mode 100644
index 000000000..14781032f
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/c2/0765f6e24e8bbb63a648d0d11d84da63170190
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/d3/d806a4bef96889117fd7ebac0e3cb5ec152932 b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/d3/d806a4bef96889117fd7ebac0e3cb5ec152932
new file mode 100644
index 000000000..8df72a45c
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/d3/d806a4bef96889117fd7ebac0e3cb5ec152932
@@ -0,0 +1,3 @@
+xA
+0E]semDx$҂@gpQs^+ZD[a
+,cGsBO# vhGpIZ4U{^c]zo@ǎ\M-\ <Bt流A \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/f1/065ff5593604072837fecaad3e2e268cb0147b b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/f1/065ff5593604072837fecaad3e2e268cb0147b
new file mode 100644
index 000000000..e0d73e1c2
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/f1/065ff5593604072837fecaad3e2e268cb0147b
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/packed-refs b/tests/resources/merge-resolve/.gitted/modules/submodule/packed-refs
new file mode 100644
index 000000000..992c4eec6
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/packed-refs
@@ -0,0 +1,3 @@
+# pack-refs with: peeled
+297aa6cd028b3336c7802c7a6f49143da4e1602d refs/remotes/origin/master
+ae39c77c70cb6bad18bb471912460c4e1ba0f586 refs/remotes/origin/submodule-branch
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/refs/heads/master b/tests/resources/merge-resolve/.gitted/modules/submodule/refs/heads/master
new file mode 100644
index 000000000..fe282569b
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/refs/heads/master
@@ -0,0 +1 @@
+297aa6cd028b3336c7802c7a6f49143da4e1602d
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/refs/remotes/origin/HEAD b/tests/resources/merge-resolve/.gitted/modules/submodule/refs/remotes/origin/HEAD
new file mode 100644
index 000000000..6efe28fff
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/refs/remotes/origin/HEAD
@@ -0,0 +1 @@
+ref: refs/remotes/origin/master
diff --git a/tests/resources/merge-resolve/.gitted/objects/0f/3fc5dddc8964b9ac1040d0e957f9eb02d9efb3 b/tests/resources/merge-resolve/.gitted/objects/0f/3fc5dddc8964b9ac1040d0e957f9eb02d9efb3
new file mode 100644
index 000000000..d0ca42dad
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/0f/3fc5dddc8964b9ac1040d0e957f9eb02d9efb3
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/11/aeee27ac45a8402c2fd5b875d66dd844e5df00 b/tests/resources/merge-resolve/.gitted/objects/11/aeee27ac45a8402c2fd5b875d66dd844e5df00
new file mode 100644
index 000000000..90e729f6d
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/11/aeee27ac45a8402c2fd5b875d66dd844e5df00
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/1c/51d885170f57a0c4e8c69ff6363d91a5b51f85 b/tests/resources/merge-resolve/.gitted/objects/1c/51d885170f57a0c4e8c69ff6363d91a5b51f85
new file mode 100644
index 000000000..9a21e26c0
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/1c/51d885170f57a0c4e8c69ff6363d91a5b51f85
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/23/ed141a6ae1e798b2f721afedbe947c119111ba b/tests/resources/merge-resolve/.gitted/objects/23/ed141a6ae1e798b2f721afedbe947c119111ba
new file mode 100644
index 000000000..06dee3b23
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/23/ed141a6ae1e798b2f721afedbe947c119111ba
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/27/4bbe983022fb4c02f8a2bf2ebe8da4fe130054 b/tests/resources/merge-resolve/.gitted/objects/27/4bbe983022fb4c02f8a2bf2ebe8da4fe130054
new file mode 100644
index 000000000..c7afad2a8
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/27/4bbe983022fb4c02f8a2bf2ebe8da4fe130054
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/2b/fdd7e1b6c6ae993f23dfe8e84a8e06a772fa2a b/tests/resources/merge-resolve/.gitted/objects/2b/fdd7e1b6c6ae993f23dfe8e84a8e06a772fa2a
new file mode 100644
index 000000000..c86edfb68
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/2b/fdd7e1b6c6ae993f23dfe8e84a8e06a772fa2a
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/34/8dcd41e2b467991578e92bedd16971b877ef1e b/tests/resources/merge-resolve/.gitted/objects/34/8dcd41e2b467991578e92bedd16971b877ef1e
new file mode 100644
index 000000000..fd61b6ce5
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/34/8dcd41e2b467991578e92bedd16971b877ef1e
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/42/18670ab81cc219a9f94befb5c5dad90ec52648 b/tests/resources/merge-resolve/.gitted/objects/42/18670ab81cc219a9f94befb5c5dad90ec52648
new file mode 100644
index 000000000..33ead6112
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/42/18670ab81cc219a9f94befb5c5dad90ec52648
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/49/fd9edac79d15c8fbfca2d481cbb900beba22a6 b/tests/resources/merge-resolve/.gitted/objects/49/fd9edac79d15c8fbfca2d481cbb900beba22a6
new file mode 100644
index 000000000..d808d9fd9
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/49/fd9edac79d15c8fbfca2d481cbb900beba22a6
@@ -0,0 +1,3 @@
+xU
+0D=+
+f5dI~Ehe3x2?ذ$Ɂ%+"SRAWRm Kn\t XZ/hMƱߙg2j># \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/objects/58/87a5e516c53bd58efb0f02ec6aa031b6fe9ad7 b/tests/resources/merge-resolve/.gitted/objects/58/87a5e516c53bd58efb0f02ec6aa031b6fe9ad7
new file mode 100644
index 000000000..550d288d4
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/58/87a5e516c53bd58efb0f02ec6aa031b6fe9ad7
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/60/61fe116ecba0800c26113ea1a7dfac2e16eeaf b/tests/resources/merge-resolve/.gitted/objects/60/61fe116ecba0800c26113ea1a7dfac2e16eeaf
new file mode 100644
index 000000000..3f266f6df
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/60/61fe116ecba0800c26113ea1a7dfac2e16eeaf
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/62/33c6a0670228627f93c01cef32485a30403670 b/tests/resources/merge-resolve/.gitted/objects/62/33c6a0670228627f93c01cef32485a30403670
new file mode 100644
index 000000000..81428dd62
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/62/33c6a0670228627f93c01cef32485a30403670
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/67/110d77886b2af6309b9212961e72b8583e5fa9 b/tests/resources/merge-resolve/.gitted/objects/67/110d77886b2af6309b9212961e72b8583e5fa9
new file mode 100644
index 000000000..877bad703
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/67/110d77886b2af6309b9212961e72b8583e5fa9
@@ -0,0 +1 @@
+x=N1 ^r !J:.`'lP^gT343Ҕup*Z %l4irHz,곥[M]aJҐb5l8OX$XճEa")U$d2zODŽų>m'qZ渍O`lFO1!n'=-]A&e˯^o^ \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/objects/6e/3b9eb35214d4e31ed5789afc7d520ac798ce55 b/tests/resources/merge-resolve/.gitted/objects/6e/3b9eb35214d4e31ed5789afc7d520ac798ce55
new file mode 100644
index 000000000..c6100cb01
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/6e/3b9eb35214d4e31ed5789afc7d520ac798ce55
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/72/cdb057b340205164478565e91eb71647e66891 b/tests/resources/merge-resolve/.gitted/objects/72/cdb057b340205164478565e91eb71647e66891
new file mode 100644
index 000000000..84aa8336b
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/72/cdb057b340205164478565e91eb71647e66891
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/7a/f14d9c679baaef35555095f4f5d33e9a569ab9 b/tests/resources/merge-resolve/.gitted/objects/7a/f14d9c679baaef35555095f4f5d33e9a569ab9
new file mode 100644
index 000000000..b4c4ef734
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/7a/f14d9c679baaef35555095f4f5d33e9a569ab9
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/7c/04ca611203ed320c5f495b9813054dd23be3be b/tests/resources/merge-resolve/.gitted/objects/7c/04ca611203ed320c5f495b9813054dd23be3be
new file mode 100644
index 000000000..e3ba6056d
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/7c/04ca611203ed320c5f495b9813054dd23be3be
@@ -0,0 +1,2 @@
+xQ D{ -,tc^`%b(K|ͼd&k)Dsl<f4a1B8zsCvŘEQdO>E񧯵#}%xu z{yV%rɐdžp֨tDŽ
+UrL \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/objects/81/1c70fcb6d5bbd022d04cc31836d30b436f9551 b/tests/resources/merge-resolve/.gitted/objects/81/1c70fcb6d5bbd022d04cc31836d30b436f9551
new file mode 100644
index 000000000..6d8702404
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/81/1c70fcb6d5bbd022d04cc31836d30b436f9551
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/83/6b8b82b26cab22eaaed8820877c76d6c8bca19 b/tests/resources/merge-resolve/.gitted/objects/83/6b8b82b26cab22eaaed8820877c76d6c8bca19
new file mode 100644
index 000000000..99f828649
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/83/6b8b82b26cab22eaaed8820877c76d6c8bca19
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/8b/7cd60d49ce3a1a770ece43b7d29b5cf462a33a b/tests/resources/merge-resolve/.gitted/objects/8b/7cd60d49ce3a1a770ece43b7d29b5cf462a33a
new file mode 100644
index 000000000..790750c0f
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/8b/7cd60d49ce3a1a770ece43b7d29b5cf462a33a
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/91/f44111cb1cb1358ac6944ad356ca1738813ea1 b/tests/resources/merge-resolve/.gitted/objects/91/f44111cb1cb1358ac6944ad356ca1738813ea1
new file mode 100644
index 000000000..51a456f42
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/91/f44111cb1cb1358ac6944ad356ca1738813ea1
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/96/bca8d4f05cc4c5e33e4389f80a1309e86fe054 b/tests/resources/merge-resolve/.gitted/objects/96/bca8d4f05cc4c5e33e4389f80a1309e86fe054
new file mode 100644
index 000000000..8938d3e56
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/96/bca8d4f05cc4c5e33e4389f80a1309e86fe054
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/ad/01aebfdf2ac13145efafe3f9fcf798882f1730 b/tests/resources/merge-resolve/.gitted/objects/ad/01aebfdf2ac13145efafe3f9fcf798882f1730
new file mode 100644
index 000000000..ae3ef8ce3
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/ad/01aebfdf2ac13145efafe3f9fcf798882f1730
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/ad/26b598134264fd284292cb233fc0b2f25851da b/tests/resources/merge-resolve/.gitted/objects/ad/26b598134264fd284292cb233fc0b2f25851da
new file mode 100644
index 000000000..5819a2e25
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/ad/26b598134264fd284292cb233fc0b2f25851da
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/ca/ff6b7d44973f53e3e0cf31d0d695188b19aec6 b/tests/resources/merge-resolve/.gitted/objects/ca/ff6b7d44973f53e3e0cf31d0d695188b19aec6
new file mode 100644
index 000000000..6d0f60077
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/ca/ff6b7d44973f53e3e0cf31d0d695188b19aec6
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/cc/338e4710c9b257106b8d16d82f86458d5beaf1 b/tests/resources/merge-resolve/.gitted/objects/cc/338e4710c9b257106b8d16d82f86458d5beaf1
new file mode 100644
index 000000000..85b3b8112
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/cc/338e4710c9b257106b8d16d82f86458d5beaf1
@@ -0,0 +1,2 @@
+xK!]s3`bo1 gpWEGmx]6d
+eaΉ碵z.Dv [hD[JﱶwX[.2nuVƉZڳF!x88GPP_?KN \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/objects/d3/3cedf513c059e0515653fa2c2e386631387a05 b/tests/resources/merge-resolve/.gitted/objects/d3/3cedf513c059e0515653fa2c2e386631387a05
new file mode 100644
index 000000000..d6d4c2b45
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/d3/3cedf513c059e0515653fa2c2e386631387a05
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/d7/308cc367b2cc23f710834ec1fd8ffbacf1b460 b/tests/resources/merge-resolve/.gitted/objects/d7/308cc367b2cc23f710834ec1fd8ffbacf1b460
new file mode 100644
index 000000000..b02cda4fa
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/d7/308cc367b2cc23f710834ec1fd8ffbacf1b460
@@ -0,0 +1 @@
+xK @]s)Ё7 ]I(x{ ^,nлSo`/X)ٙB@GÔaD 4xwlCv?-79d,hF4Z ;ƝH}= \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/objects/d8/dec75ff2f8b41d1c5bfef0cd57b7300c834f66 b/tests/resources/merge-resolve/.gitted/objects/d8/dec75ff2f8b41d1c5bfef0cd57b7300c834f66
new file mode 100644
index 000000000..74f807e68
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/d8/dec75ff2f8b41d1c5bfef0cd57b7300c834f66
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/dd/2ae5ab264e5592aa754235d5ad5eac8f0ecdfd b/tests/resources/merge-resolve/.gitted/objects/dd/2ae5ab264e5592aa754235d5ad5eac8f0ecdfd
new file mode 100644
index 000000000..55626a57b
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/dd/2ae5ab264e5592aa754235d5ad5eac8f0ecdfd
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/e5/060729746ca9888239cba08fdcf4bee907b406 b/tests/resources/merge-resolve/.gitted/objects/e5/060729746ca9888239cba08fdcf4bee907b406
new file mode 100644
index 000000000..33299c2b0
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/e5/060729746ca9888239cba08fdcf4bee907b406
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/f2/e1550a0c9e53d5811175864a29536642ae3821 b/tests/resources/merge-resolve/.gitted/objects/f2/e1550a0c9e53d5811175864a29536642ae3821
new file mode 100644
index 000000000..1fdcbe22a
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/f2/e1550a0c9e53d5811175864a29536642ae3821
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/f6/65b45cde9b568009c6e6b7b568e89cfe717df8 b/tests/resources/merge-resolve/.gitted/objects/f6/65b45cde9b568009c6e6b7b568e89cfe717df8
new file mode 100644
index 000000000..7af50d7df
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/f6/65b45cde9b568009c6e6b7b568e89cfe717df8
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/submodules b/tests/resources/merge-resolve/.gitted/refs/heads/submodules
new file mode 100644
index 000000000..e5511eca9
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/refs/heads/submodules
@@ -0,0 +1 @@
+d8dec75ff2f8b41d1c5bfef0cd57b7300c834f66
diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch b/tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch
new file mode 100644
index 000000000..7d47e07b8
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch
@@ -0,0 +1 @@
+811c70fcb6d5bbd022d04cc31836d30b436f9551
diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch2 b/tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch2
new file mode 100644
index 000000000..ced60d813
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch2
@@ -0,0 +1 @@
+7c04ca611203ed320c5f495b9813054dd23be3be
diff --git a/tests/resources/revert/.gitted/index b/tests/resources/revert/.gitted/index
index 87419ff57..3513c04a6 100644
--- a/tests/resources/revert/.gitted/index
+++ b/tests/resources/revert/.gitted/index
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/0a/d19525be6d8cae5e5deb2770fc244b65255057 b/tests/resources/revert/.gitted/objects/0a/d19525be6d8cae5e5deb2770fc244b65255057
new file mode 100644
index 000000000..4aa0459d8
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/0a/d19525be6d8cae5e5deb2770fc244b65255057
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/13/a6fdfd10bd74b1f258fb58801215985dd2e797 b/tests/resources/revert/.gitted/objects/13/a6fdfd10bd74b1f258fb58801215985dd2e797
new file mode 100644
index 000000000..3c54aab0c
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/13/a6fdfd10bd74b1f258fb58801215985dd2e797
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/1b/c915c5cb7185a9438de28a7b1a7dfe8c01ee7f b/tests/resources/revert/.gitted/objects/1b/c915c5cb7185a9438de28a7b1a7dfe8c01ee7f
new file mode 100644
index 000000000..0a6955b5d
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/1b/c915c5cb7185a9438de28a7b1a7dfe8c01ee7f
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/1f/f0c423042b46cb1d617b81efb715defbe8054d b/tests/resources/revert/.gitted/objects/1f/f0c423042b46cb1d617b81efb715defbe8054d
new file mode 100644
index 000000000..2ed1a2292
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/1f/f0c423042b46cb1d617b81efb715defbe8054d
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/21/a96a98ed84d45866e1de6e266fd3a61a4ae9dc b/tests/resources/revert/.gitted/objects/21/a96a98ed84d45866e1de6e266fd3a61a4ae9dc
new file mode 100644
index 000000000..95842dbf8
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/21/a96a98ed84d45866e1de6e266fd3a61a4ae9dc
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/39/9fb3aba3d9d13f7d40a9254ce4402067ef3149 b/tests/resources/revert/.gitted/objects/39/9fb3aba3d9d13f7d40a9254ce4402067ef3149
new file mode 100644
index 000000000..6cb6839d6
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/39/9fb3aba3d9d13f7d40a9254ce4402067ef3149
@@ -0,0 +1,2 @@
+xK!]s
+.;@bozA\0m<֞C,3d@_D @K6ŗ5T=oS$T1.% @zQ["-D x]ry<o];\ ]1YQEĤ$l<,`aGN \ No newline at end of file
diff --git a/tests/resources/revert/.gitted/objects/46/ff0854663aeb2182b9838c8da68e33ac23bc1e b/tests/resources/revert/.gitted/objects/46/ff0854663aeb2182b9838c8da68e33ac23bc1e
new file mode 100644
index 000000000..7064dab52
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/46/ff0854663aeb2182b9838c8da68e33ac23bc1e
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/5c/f1d643f100d8112834e540264546ba2c159976 b/tests/resources/revert/.gitted/objects/5c/f1d643f100d8112834e540264546ba2c159976
new file mode 100644
index 000000000..dbbf711b5
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/5c/f1d643f100d8112834e540264546ba2c159976
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/6b/ccd0dc58cea5ccff86014f3d64b31bd8c02a37 b/tests/resources/revert/.gitted/objects/6b/ccd0dc58cea5ccff86014f3d64b31bd8c02a37
new file mode 100644
index 000000000..2664da480
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/6b/ccd0dc58cea5ccff86014f3d64b31bd8c02a37
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/71/eb9c2b53dbbf3c45fb28b27c850db4b7fb8011 b/tests/resources/revert/.gitted/objects/71/eb9c2b53dbbf3c45fb28b27c850db4b7fb8011
new file mode 100644
index 000000000..995a1e626
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/71/eb9c2b53dbbf3c45fb28b27c850db4b7fb8011
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/87/59ad453cf01cf7daf14e2a668f8218f9a678eb b/tests/resources/revert/.gitted/objects/87/59ad453cf01cf7daf14e2a668f8218f9a678eb
new file mode 100644
index 000000000..ab19acf83
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/87/59ad453cf01cf7daf14e2a668f8218f9a678eb
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/9a/95fd974e03c5b93828ceedd28755965b5d5c60 b/tests/resources/revert/.gitted/objects/9a/95fd974e03c5b93828ceedd28755965b5d5c60
new file mode 100644
index 000000000..bb93a34bb
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/9a/95fd974e03c5b93828ceedd28755965b5d5c60
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/a8/c86221b400b836010567cc3593db6e96c1a83a b/tests/resources/revert/.gitted/objects/a8/c86221b400b836010567cc3593db6e96c1a83a
new file mode 100644
index 000000000..29654616e
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/a8/c86221b400b836010567cc3593db6e96c1a83a
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/ac/c4d33902092efeb3b714aa0b1007c329e2f2e6 b/tests/resources/revert/.gitted/objects/ac/c4d33902092efeb3b714aa0b1007c329e2f2e6
new file mode 100644
index 000000000..91bb68b41
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/ac/c4d33902092efeb3b714aa0b1007c329e2f2e6
@@ -0,0 +1,2 @@
+x[
+1 @QJW t6 F,LW8pe1llU.LiT B<dQuȉ#MTI"v?O7ঽ>dN0z"!:ML䮽$ \ No newline at end of file
diff --git a/tests/resources/revert/.gitted/objects/b6/9d88e177455579896e2be495046e2a51456a9a b/tests/resources/revert/.gitted/objects/b6/9d88e177455579896e2be495046e2a51456a9a
new file mode 100644
index 000000000..a5f69f2c8
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/b6/9d88e177455579896e2be495046e2a51456a9a
@@ -0,0 +1 @@
+x]j!*.yoљ{R l@NFZԴ$@o 54@+z-FP2{Hn"zZR.<J|ˀ2Ț:VfR ´Xanc >5VsNShuC4Yk;݇q߱ 8ZF*W+B\ԡ=,uwd \ No newline at end of file
diff --git a/tests/resources/revert/.gitted/objects/ca/f99de3a49827117bb66721010eac461b06a80c b/tests/resources/revert/.gitted/objects/ca/f99de3a49827117bb66721010eac461b06a80c
new file mode 100644
index 000000000..7f6f4e0c6
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/ca/f99de3a49827117bb66721010eac461b06a80c
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/de/03538407ed18914ff05657eeff70425c0f304d b/tests/resources/revert/.gitted/objects/de/03538407ed18914ff05657eeff70425c0f304d
new file mode 100644
index 000000000..e651676fd
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/de/03538407ed18914ff05657eeff70425c0f304d
@@ -0,0 +1,2 @@
+x]J1})}wIw~D|H:vlL;|)MPLeYuY}ԩ+mX2g0.{z,U5_'!ʂ5i!agǼ+ko{{i:3,u H1"#=NGyON
+Zy2rvh(KabdV[uFrRW(1|_c& \ No newline at end of file
diff --git a/tests/resources/revert/.gitted/objects/e3/4ef1afe54eb526fd92eec66084125f340f1d65 b/tests/resources/revert/.gitted/objects/e3/4ef1afe54eb526fd92eec66084125f340f1d65
new file mode 100644
index 000000000..fc19ebd3d
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/e3/4ef1afe54eb526fd92eec66084125f340f1d65
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/ea/392a157085bc32daccd59aa1998fe2f5fb9fc0 b/tests/resources/revert/.gitted/objects/ea/392a157085bc32daccd59aa1998fe2f5fb9fc0
new file mode 100644
index 000000000..1451a6ac4
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/ea/392a157085bc32daccd59aa1998fe2f5fb9fc0
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/ee/c6adcb2f3ceca0cadeccfe01b19382252ece9b b/tests/resources/revert/.gitted/objects/ee/c6adcb2f3ceca0cadeccfe01b19382252ece9b
new file mode 100644
index 000000000..f59f3d48d
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/ee/c6adcb2f3ceca0cadeccfe01b19382252ece9b
Binary files differ
diff --git a/tests/resources/revert/.gitted/refs/heads/master b/tests/resources/revert/.gitted/refs/heads/master
index d3850daa6..180f407e3 100644
--- a/tests/resources/revert/.gitted/refs/heads/master
+++ b/tests/resources/revert/.gitted/refs/heads/master
@@ -1 +1 @@
-2d440f2b3147d3dc7ad1085813478d6d869d5a4d
+2d440f2b3147d3dc7ad1085813478d6d869d5a4d
diff --git a/tests/resources/revert/.gitted/refs/heads/two b/tests/resources/revert/.gitted/refs/heads/two
new file mode 100644
index 000000000..f31ec00e5
--- /dev/null
+++ b/tests/resources/revert/.gitted/refs/heads/two
@@ -0,0 +1 @@
+e34ef1afe54eb526fd92eec66084125f340f1d65
diff --git a/tests/revert/workdir.c b/tests/revert/workdir.c
index 9dc72a9a8..5be397c93 100644
--- a/tests/revert/workdir.c
+++ b/tests/revert/workdir.c
@@ -137,6 +137,203 @@ void test_revert_workdir__orphan(void)
git_commit_free(head);
}
+/*
+ * revert the same commit twice (when the first reverts cleanly):
+ *
+ * git revert 2d440f2
+ * git revert 2d440f2
+ */
+void test_revert_workdir__again(void)
+{
+ git_reference *head_ref;
+ git_commit *orig_head;
+ git_tree *reverted_tree;
+ git_oid reverted_tree_oid, reverted_commit_oid;
+ git_signature *signature;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "7731926a337c4eaba1e2187d90ebfa0a93659382", 0, "file1.txt" },
+ { 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" },
+ { 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" },
+ { 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" },
+ };
+
+ cl_git_pass(git_repository_head(&head_ref, repo));
+ cl_git_pass(git_reference_peel((git_object **)&orig_head, head_ref, GIT_OBJ_COMMIT));
+ cl_git_pass(git_reset(repo, (git_object *)orig_head, GIT_RESET_HARD));
+
+ cl_git_pass(git_revert(repo, orig_head, NULL));
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
+
+ cl_git_pass(git_index_write_tree(&reverted_tree_oid, repo_index));
+ cl_git_pass(git_tree_lookup(&reverted_tree, repo, &reverted_tree_oid));
+
+ cl_git_pass(git_signature_new(&signature, "Reverter", "reverter@example.org", time(NULL), 0));
+ cl_git_pass(git_commit_create(&reverted_commit_oid, repo, "HEAD", signature, signature, NULL, "Reverted!", reverted_tree, 1, (const git_commit **)&orig_head));
+
+ cl_git_pass(git_revert(repo, orig_head, NULL));
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
+
+ git_signature_free(signature);
+ git_tree_free(reverted_tree);
+ git_commit_free(orig_head);
+ git_reference_free(head_ref);
+}
+
+/* git reset --hard 72333f47d4e83616630ff3b0ffe4c0faebcc3c45
+ * git revert --no-commit d1d403d22cbe24592d725f442835cf46fe60c8ac */
+void test_revert_workdir__again_after_automerge(void)
+{
+ git_commit *head, *commit;
+ git_tree *reverted_tree;
+ git_oid head_oid, revert_oid, reverted_tree_oid, reverted_commit_oid;
+ git_signature *signature;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "caf99de3a49827117bb66721010eac461b06a80c", 0, "file1.txt" },
+ { 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" },
+ { 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" },
+ { 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" },
+ };
+
+ struct merge_index_entry second_revert_entries[] = {
+ { 0100644, "3a3ef367eaf3fe79effbfb0a56b269c04c2b59fe", 1, "file1.txt" },
+ { 0100644, "caf99de3a49827117bb66721010eac461b06a80c", 2, "file1.txt" },
+ { 0100644, "747726e021bc5f44b86de60e3032fd6f9f1b8383", 3, "file1.txt" },
+ { 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" },
+ { 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" },
+ { 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" },
+ };
+
+ git_oid_fromstr(&head_oid, "72333f47d4e83616630ff3b0ffe4c0faebcc3c45");
+ cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD));
+
+ git_oid_fromstr(&revert_oid, "d1d403d22cbe24592d725f442835cf46fe60c8ac");
+ cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
+ cl_git_pass(git_revert(repo, commit, NULL));
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
+
+ cl_git_pass(git_index_write_tree(&reverted_tree_oid, repo_index));
+ cl_git_pass(git_tree_lookup(&reverted_tree, repo, &reverted_tree_oid));
+
+ cl_git_pass(git_signature_new(&signature, "Reverter", "reverter@example.org", time(NULL), 0));
+ cl_git_pass(git_commit_create(&reverted_commit_oid, repo, "HEAD", signature, signature, NULL, "Reverted!", reverted_tree, 1, (const git_commit **)&head));
+
+ cl_git_pass(git_revert(repo, commit, NULL));
+ cl_assert(merge_test_index(repo_index, second_revert_entries, 6));
+
+ git_signature_free(signature);
+ git_tree_free(reverted_tree);
+ git_commit_free(commit);
+ git_commit_free(head);
+}
+
+/*
+ * revert the same commit twice (when the first reverts cleanly):
+ *
+ * git revert 2d440f2
+ * git revert 2d440f2
+ */
+void test_revert_workdir__again_after_edit(void)
+{
+ git_reference *head_ref;
+ git_commit *orig_head, *commit;
+ git_tree *reverted_tree;
+ git_oid orig_head_oid, revert_oid, reverted_tree_oid, reverted_commit_oid;
+ git_signature *signature;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "3721552e06c4bdc7d478e0674e6304888545d5fd", 0, "file1.txt" },
+ { 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" },
+ { 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" },
+ { 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" },
+ };
+
+ cl_git_pass(git_repository_head(&head_ref, repo));
+
+ cl_git_pass(git_oid_fromstr(&orig_head_oid, "399fb3aba3d9d13f7d40a9254ce4402067ef3149"));
+ cl_git_pass(git_commit_lookup(&orig_head, repo, &orig_head_oid));
+ cl_git_pass(git_reset(repo, (git_object *)orig_head, GIT_RESET_HARD));
+
+ cl_git_pass(git_oid_fromstr(&revert_oid, "2d440f2b3147d3dc7ad1085813478d6d869d5a4d"));
+ cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
+
+ cl_git_pass(git_revert(repo, commit, NULL));
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
+
+ cl_git_pass(git_index_write_tree(&reverted_tree_oid, repo_index));
+ cl_git_pass(git_tree_lookup(&reverted_tree, repo, &reverted_tree_oid));
+
+ cl_git_pass(git_signature_new(&signature, "Reverter", "reverter@example.org", time(NULL), 0));
+ cl_git_pass(git_commit_create(&reverted_commit_oid, repo, "HEAD", signature, signature, NULL, "Reverted!", reverted_tree, 1, (const git_commit **)&orig_head));
+
+ cl_git_pass(git_revert(repo, commit, NULL));
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
+
+ git_signature_free(signature);
+ git_tree_free(reverted_tree);
+ git_commit_free(commit);
+ git_commit_free(orig_head);
+ git_reference_free(head_ref);
+}
+
+/*
+ * revert the same commit twice (when the first reverts cleanly):
+ *
+ * git reset --hard e34ef1a
+ * git revert 71eb9c2
+ */
+void test_revert_workdir__again_after_edit_two(void)
+{
+ git_buf diff_buf = GIT_BUF_INIT;
+ git_config *config;
+ git_oid head_commit_oid, revert_commit_oid;
+ git_commit *head_commit, *revert_commit;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "1ff0c423042b46cb1d617b81efb715defbe8054d", 0, ".gitattributes" },
+ { 0100644, "1bc915c5cb7185a9438de28a7b1a7dfe8c01ee7f", 0, ".gitignore" },
+ { 0100644, "a8c86221b400b836010567cc3593db6e96c1a83a", 1, "file.txt" },
+ { 0100644, "46ff0854663aeb2182b9838c8da68e33ac23bc1e", 2, "file.txt" },
+ { 0100644, "21a96a98ed84d45866e1de6e266fd3a61a4ae9dc", 3, "file.txt" },
+ };
+
+ cl_git_pass(git_repository_config(&config, repo));
+ cl_git_pass(git_config_set_bool(config, "core.autocrlf", 0));
+
+ cl_git_pass(git_oid_fromstr(&head_commit_oid, "e34ef1afe54eb526fd92eec66084125f340f1d65"));
+ cl_git_pass(git_commit_lookup(&head_commit, repo, &head_commit_oid));
+ cl_git_pass(git_reset(repo, (git_object *)head_commit, GIT_RESET_HARD));
+
+ cl_git_pass(git_oid_fromstr(&revert_commit_oid, "71eb9c2b53dbbf3c45fb28b27c850db4b7fb8011"));
+ cl_git_pass(git_commit_lookup(&revert_commit, repo, &revert_commit_oid));
+
+ cl_git_pass(git_revert(repo, revert_commit, NULL));
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 5));
+
+ cl_git_pass(git_futils_readbuffer(&diff_buf, "revert/file.txt"));
+ cl_assert(strcmp(diff_buf.ptr, "a\n" \
+ "<<<<<<< HEAD\n" \
+ "=======\n" \
+ "a\n" \
+ ">>>>>>> parent of 71eb9c2... revert me\n" \
+ "a\n" \
+ "a\n" \
+ "a\n" \
+ "a\n" \
+ "ab\n") == 0);
+
+ git_commit_free(revert_commit);
+ git_commit_free(head_commit);
+ git_config_free(config);
+ git_buf_free(&diff_buf);
+}
+
/* git reset --hard 72333f47d4e83616630ff3b0ffe4c0faebcc3c45
* git revert --no-commit d1d403d22cbe24592d725f442835cf46fe60c8ac */
void test_revert_workdir__conflict_use_ours(void)
@@ -146,22 +343,19 @@ void test_revert_workdir__conflict_use_ours(void)
git_revert_opts opts = GIT_REVERT_OPTS_INIT;
struct merge_index_entry merge_index_entries[] = {
- { 0100644, "3a3ef367eaf3fe79effbfb0a56b269c04c2b59fe", 1, "file1.txt" },
- { 0100644, "7731926a337c4eaba1e2187d90ebfa0a93659382", 2, "file1.txt" },
- { 0100644, "747726e021bc5f44b86de60e3032fd6f9f1b8383", 3, "file1.txt" },
+ { 0100644, "caf99de3a49827117bb66721010eac461b06a80c", 0, "file1.txt" },
{ 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" },
{ 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" },
{ 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" },
};
struct merge_index_entry merge_filesystem_entries[] = {
- { 0100644, "7731926a337c4eaba1e2187d90ebfa0a93659382", 0, "file1.txt" },
+ { 0100644, "caf99de3a49827117bb66721010eac461b06a80c", 0, "file1.txt" },
{ 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" },
{ 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" },
{ 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" },
};
- opts.merge_tree_opts.automerge_flags = GIT_MERGE_AUTOMERGE_NONE;
opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS;
git_oid_fromstr(&head_oid, "72333f47d4e83616630ff3b0ffe4c0faebcc3c45");
@@ -172,7 +366,7 @@ void test_revert_workdir__conflict_use_ours(void)
cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
cl_git_pass(git_revert(repo, commit, &opts));
- cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
cl_assert(merge_test_workdir(repo, merge_filesystem_entries, 4));
git_commit_free(commit);