Merge pull request #2616 from ethomson/index_crlf Apply filters when writing index
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
diff --git a/src/checkout.c b/src/checkout.c
index f25a6ef..8aaf8c5 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -1761,10 +1761,12 @@ static int checkout_write_merge(
checkout_conflictdata *conflict)
{
git_buf our_label = GIT_BUF_INIT, their_label = GIT_BUF_INIT,
- path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT;
+ path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT,
+ in_data = GIT_BUF_INIT, out_data = GIT_BUF_INIT;
git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
git_merge_file_result result = {0};
git_filebuf output = GIT_FILEBUF_INIT;
+ git_filter_list *fl = NULL;
int error = 0;
if (data->opts.checkout_strategy & GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)
@@ -1810,13 +1812,29 @@ static int checkout_write_merge(
(error = checkout_safe_for_update_only(git_buf_cstr(&path_workdir), result.mode)) <= 0)
goto done;
+ if (!data->opts.disable_filters) {
+ in_data.ptr = (char *)result.ptr;
+ in_data.size = result.len;
+
+ if ((error = git_filter_list_load(&fl, data->repo, NULL, git_buf_cstr(&path_workdir),
+ GIT_FILTER_TO_WORKTREE, GIT_FILTER_OPT_DEFAULT)) < 0 ||
+ (error = git_filter_list_apply_to_data(&out_data, fl, &in_data)) < 0)
+ goto done;
+ } else {
+ out_data.ptr = (char *)result.ptr;
+ out_data.size = result.len;
+ }
+
if ((error = git_futils_mkpath2file(path_workdir.ptr, 0755)) < 0 ||
- (error = git_filebuf_open(&output, path_workdir.ptr, GIT_FILEBUF_DO_NOT_BUFFER, result.mode)) < 0 ||
- (error = git_filebuf_write(&output, result.ptr, result.len)) < 0 ||
+ (error = git_filebuf_open(&output, git_buf_cstr(&path_workdir), GIT_FILEBUF_DO_NOT_BUFFER, result.mode)) < 0 ||
+ (error = git_filebuf_write(&output, out_data.ptr, out_data.size)) < 0 ||
(error = git_filebuf_commit(&output)) < 0)
goto done;
done:
+ git_filter_list_free(fl);
+
+ git_buf_free(&out_data);
git_buf_free(&our_label);
git_buf_free(&their_label);
diff --git a/tests/checkout/index.c b/tests/checkout/index.c
index 7f641b3..3c01e24 100644
--- a/tests/checkout/index.c
+++ b/tests/checkout/index.c
@@ -618,3 +618,72 @@ void test_checkout_index__can_get_repo_from_index(void)
git_index_free(index);
}
+
+static void add_conflict(void)
+{
+ git_index *index;
+ git_index_entry entry;
+
+ memset(&entry, 0, sizeof(git_index_entry));
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+
+ entry.mode = 0100644;
+ entry.path = "conflicting.txt";
+
+ git_oid_fromstr(&entry.id, "d427e0b2e138501a3d15cc376077a3631e15bd46");
+ entry.flags = (1 << GIT_IDXENTRY_STAGESHIFT);
+ cl_git_pass(git_index_add(index, &entry));
+
+ git_oid_fromstr(&entry.id, "4e886e602529caa9ab11d71f86634bd1b6e0de10");
+ entry.flags = (2 << GIT_IDXENTRY_STAGESHIFT);
+ cl_git_pass(git_index_add(index, &entry));
+
+ git_oid_fromstr(&entry.id, "2bd0a343aeef7a2cf0d158478966a6e587ff3863");
+ entry.flags = (3 << GIT_IDXENTRY_STAGESHIFT);
+ cl_git_pass(git_index_add(index, &entry));
+
+ cl_git_pass(git_index_write(index));
+ git_index_free(index);
+}
+
+void test_checkout_index__writes_conflict_file(void)
+{
+ git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
+ git_buf conflicting_buf = GIT_BUF_INIT;
+
+ add_conflict();
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
+
+ cl_git_pass(git_futils_readbuffer(&conflicting_buf, "testrepo/conflicting.txt"));
+ cl_assert(strcmp(conflicting_buf.ptr,
+ "<<<<<<< ours\n"
+ "this file is changed in master and branch\n"
+ "=======\n"
+ "this file is changed in branch and master\n"
+ ">>>>>>> theirs\n") == 0);
+ git_buf_free(&conflicting_buf);
+}
+
+void test_checkout_index__conflicts_honor_coreautocrlf(void)
+{
+#ifdef GIT_WIN32
+ git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
+ git_buf conflicting_buf = GIT_BUF_INIT;
+
+ cl_git_pass(p_unlink("./testrepo/.gitattributes"));
+ cl_repo_set_bool(g_repo, "core.autocrlf", true);
+
+ add_conflict();
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
+
+ cl_git_pass(git_futils_readbuffer(&conflicting_buf, "testrepo/conflicting.txt"));
+ cl_assert(strcmp(conflicting_buf.ptr,
+ "<<<<<<< ours\r\n"
+ "this file is changed in master and branch\r\n"
+ "=======\r\n"
+ "this file is changed in branch and master\r\n"
+ ">>>>>>> theirs\r\n") == 0);
+ git_buf_free(&conflicting_buf);
+#endif
+}
diff --git a/tests/resources/testrepo/.gitted/objects/2b/d0a343aeef7a2cf0d158478966a6e587ff3863 b/tests/resources/testrepo/.gitted/objects/2b/d0a343aeef7a2cf0d158478966a6e587ff3863
new file mode 100644
index 0000000..d10ca63
Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/2b/d0a343aeef7a2cf0d158478966a6e587ff3863 differ
diff --git a/tests/resources/testrepo/.gitted/objects/4e/886e602529caa9ab11d71f86634bd1b6e0de10 b/tests/resources/testrepo/.gitted/objects/4e/886e602529caa9ab11d71f86634bd1b6e0de10
new file mode 100644
index 0000000..53168a0
Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/4e/886e602529caa9ab11d71f86634bd1b6e0de10 differ
diff --git a/tests/resources/testrepo/.gitted/objects/d4/27e0b2e138501a3d15cc376077a3631e15bd46 b/tests/resources/testrepo/.gitted/objects/d4/27e0b2e138501a3d15cc376077a3631e15bd46
new file mode 100644
index 0000000..0b3611a
Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/d4/27e0b2e138501a3d15cc376077a3631e15bd46 differ