{"thread":{"id":"24250","subject":"[PATCH v5 0/4] Re-rolled merge normalization","startedAt":"2010-07-01T09:09:48Z","lastAt":"2010-07-01T20:25:01Z","messageCount":13,"participants":["Eyvind Bernhardsen","Johannes Sixt","Junio C Hamano","Jakub Narebski","Finn Arne Gangstad"],"isPatch":true,"patchVersion":5,"patchTotal":4},"messages":[{"id":"144568","messageId":"cover.1277974452.git.eyvind.bernhardsen@gmail.com","threadId":"24250","inReplyTo":null,"subject":"[PATCH v5 0/4] Re-rolled merge normalization","fromName":"Eyvind Bernhardsen","fromEmail":"eyvind.bernhardsen@gmail.com","sentAt":"2010-07-01T09:09:48Z","receivedAt":"2010-07-01T09:09:48Z","isPatch":true,"sender":{"key":"eyvind.bernhardsen@gmail.com","avatar":"https://avatars.githubusercontent.com/u/106762?v=4"},"body":"Hi Junio,\n\nI took the liberty of re-rolling my series with your improved d/m patch.\nI re-added some optimizations to your patch and renamed the config\nvariable to something a little more typeable.\n-- \nEyvind\n\nEyvind Bernhardsen (3):\n  Avoid conflicts when merging branches with mixed normalization\n  Try normalizing files to avoid delete/modify conflicts when merging\n  Don't expand CRLFs when normalizing text during merge\n\nJunio C Hamano (1):\n  Introduce \"double conversion during merge\" more gradually\n\n Documentation/config.txt        |   10 ++++++\n Documentation/gitattributes.txt |   34 ++++++++++++++++++++++\n cache.h                         |    2 +\n config.c                        |    5 +++\n convert.c                       |   37 ++++++++++++++++++++----\n environment.c                   |    1 +\n ll-merge.c                      |   15 ++++++++++\n merge-recursive.c               |   51 ++++++++++++++++++++++++++++++++-\n t/t6038-merge-text-auto.sh      |   59 +++++++++++++++++++++++++++++++++++++++\n 9 files changed, 206 insertions(+), 8 deletions(-)\n create mode 100755 t/t6038-merge-text-auto.sh\n\n-- \n1.7.2.rc1.4.g09d06\n"},{"id":"144571","messageId":"341c6df1dd591c54a5aa386803ea4e0c77bd0047.1277974452.git.eyvind.bernhardsen@gmail.com","threadId":"24250","inReplyTo":"cover.1277974452.git.eyvind.bernhardsen@gmail.com","subject":"[PATCH v5 1/4] Avoid conflicts when merging branches with mixed normalization","fromName":"Eyvind Bernhardsen","fromEmail":"eyvind.bernhardsen@gmail.com","sentAt":"2010-07-01T09:09:49Z","receivedAt":"2010-07-01T09:09:49Z","isPatch":true,"sender":{"key":"eyvind.bernhardsen@gmail.com","avatar":"https://avatars.githubusercontent.com/u/106762?v=4"},"body":"Currently, merging across changes in line ending normalization is\npainful since files containing CRLF will conflict with normalized files,\neven if the only difference between the two versions is the line\nendings.  Additionally, any \"real\" merge conflicts that exist are\nobscured because every line in the file has a conflict.\n\nAssume you start out with a repo that has a lot of text files with CRLF\nchecked in (A):\n\n      o---C\n     /     \\\n    A---B---D\n\nB: Add \"* text=auto\" to .gitattributes and normalize all files to\n   LF-only\n\nC: Modify some of the text files\n\nD: Try to merge C\n\nYou will get a ridiculous number of LF/CRLF conflicts when trying to\nmerge C into D, since the repository contents for C are \"wrong\" wrt the\nnew .gitattributes file.\n\nFix ll-merge so that the \"base\", \"theirs\" and \"ours\" stages are passed\nthrough convert_to_worktree() and convert_to_git() before a three-way\nmerge.  This ensures that all three stages are normalized in the same\nway, removing from consideration differences that are only due to\nnormalization.\n\nSigned-off-by: Eyvind Bernhardsen <eyvind.bernhardsen@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/gitattributes.txt |   33 ++++++++++++++++++++++\n cache.h                         |    1 +\n convert.c                       |   16 +++++++++-\n ll-merge.c                      |   13 +++++++++\n t/t6038-merge-text-auto.sh      |   58 +++++++++++++++++++++++++++++++++++++++\n 5 files changed, 119 insertions(+), 2 deletions(-)\n create mode 100755 t/t6038-merge-text-auto.sh\n\ndiff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt\nindex 564586b..22400c1 100644\n--- a/Documentation/gitattributes.txt\n+++ b/Documentation/gitattributes.txt\n@@ -317,6 +317,17 @@ command is \"cat\").\n \tsmudge = cat\n ------------------------\n \n+For best results, `clean` should not alter its output further if it is\n+run twice (\"clean->clean\" should be equivalent to \"clean\"), and\n+multiple `smudge` commands should not alter `clean`'s output\n+(\"smudge->smudge->clean\" should be equivalent to \"clean\").  See the\n+section on merging below.\n+\n+The \"indent\" filter is well-behaved in this regard: it will not modify\n+input that is already correctly indented.  In this case, the lack of a\n+smudge filter means that the clean filter _must_ accept its own output\n+without modifying it.\n+\n \n Interaction between checkin/checkout attributes\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n@@ -331,6 +342,28 @@ In the check-out codepath, the blob content is first converted\n with `text`, and then `ident` and fed to `filter`.\n \n \n+Merging branches with differing checkin/checkout attributes\n+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n+\n+If you have added attributes to a file that cause the canonical\n+repository format for that file to change, such as adding a\n+clean/smudge filter or text/eol/ident attributes, merging anything\n+where the attribute is not in place would normally cause merge\n+conflicts.\n+\n+To prevent these unnecessary merge conflicts, git runs a virtual\n+check-out and check-in of all three stages of a file when resolving a\n+three-way merge.  This prevents changes caused by check-in conversion\n+from causing spurious merge conflicts when a converted file is merged\n+with an unconverted file.\n+\n+As long as a \"smudge->clean\" results in the same output as a \"clean\"\n+even on files that are already smudged, this strategy will\n+automatically resolve all filter-related conflicts.  Filters that do\n+not act in this way may cause additional merge conflicts that must be\n+resolved manually.\n+\n+\n Generating diff text\n ~~~~~~~~~~~~~~~~~~~~\n \ndiff --git a/cache.h b/cache.h\nindex c9fa3df..aa725b0 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1054,6 +1054,7 @@ extern void trace_argv_printf(const char **argv, const char *format, ...);\n extern int convert_to_git(const char *path, const char *src, size_t len,\n                           struct strbuf *dst, enum safe_crlf checksafe);\n extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);\n+extern int renormalize_buffer(const char *path, const char *src, size_t len, struct strbuf *dst);\n \n /* add */\n /*\ndiff --git a/convert.c b/convert.c\nindex e41a31e..0203be8 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -93,7 +93,8 @@ static int is_binary(unsigned long size, struct text_stat *stats)\n \treturn 0;\n }\n \n-static enum eol determine_output_conversion(enum action action) {\n+static enum eol determine_output_conversion(enum action action)\n+{\n \tswitch (action) {\n \tcase CRLF_BINARY:\n \t\treturn EOL_UNSET;\n@@ -693,7 +694,8 @@ static int git_path_check_ident(const char *path, struct git_attr_check *check)\n \treturn !!ATTR_TRUE(value);\n }\n \n-enum action determine_action(enum action text_attr, enum eol eol_attr) {\n+static enum action determine_action(enum action text_attr, enum eol eol_attr)\n+{\n \tif (text_attr == CRLF_BINARY)\n \t\treturn CRLF_BINARY;\n \tif (eol_attr == EOL_LF)\n@@ -773,3 +775,13 @@ int convert_to_working_tree(const char *path, const char *src, size_t len, struc\n \t}\n \treturn ret | apply_filter(path, src, len, dst, filter);\n }\n+\n+int renormalize_buffer(const char *path, const char *src, size_t len, struct strbuf *dst)\n+{\n+\tint ret = convert_to_working_tree(path, src, len, dst);\n+\tif (ret) {\n+\t\tsrc = dst->buf;\n+\t\tlen = dst->len;\n+\t}\n+\treturn ret | convert_to_git(path, src, len, dst, 0);\n+}\ndiff --git a/ll-merge.c b/ll-merge.c\nindex 3764a1a..28c6f54 100644\n--- a/ll-merge.c\n+++ b/ll-merge.c\n@@ -321,6 +321,16 @@ static int git_path_check_merge(const char *path, struct git_attr_check check[2]\n \treturn git_checkattr(path, 2, check);\n }\n \n+static void normalize_file(mmfile_t *mm, const char *path)\n+{\n+\tstruct strbuf strbuf = STRBUF_INIT;\n+\tif (renormalize_buffer(path, mm->ptr, mm->size, &strbuf)) {\n+\t\tfree(mm->ptr);\n+\t\tmm->size = strbuf.len;\n+\t\tmm->ptr = strbuf_detach(&strbuf, NULL);\n+\t}\n+}\n+\n int ll_merge(mmbuffer_t *result_buf,\n \t     const char *path,\n \t     mmfile_t *ancestor, const char *ancestor_label,\n@@ -334,6 +344,9 @@ int ll_merge(mmbuffer_t *result_buf,\n \tconst struct ll_merge_driver *driver;\n \tint virtual_ancestor = flag & 01;\n \n+\tnormalize_file(ancestor, path);\n+\tnormalize_file(ours, path);\n+\tnormalize_file(theirs, path);\n \tif (!git_path_check_merge(path, check)) {\n \t\tll_driver_name = check[0].value;\n \t\tif (check[1].value) {\ndiff --git a/t/t6038-merge-text-auto.sh b/t/t6038-merge-text-auto.sh\nnew file mode 100755\nindex 0000000..44e6003\n--- /dev/null\n+++ b/t/t6038-merge-text-auto.sh\n@@ -0,0 +1,58 @@\n+#!/bin/sh\n+\n+test_description='CRLF merge conflict across text=auto change'\n+\n+. ./test-lib.sh\n+\n+test_expect_success setup '\n+\tgit config core.autocrlf false &&\n+\techo first line | append_cr >file &&\n+\tgit add file &&\n+\tgit commit -m \"Initial\" &&\n+\tgit tag initial &&\n+\tgit branch side &&\n+\techo \"* text=auto\" >.gitattributes &&\n+\ttouch file &&\n+\tgit add .gitattributes file &&\n+\tgit commit -m \"normalize file\" &&\n+\techo same line | append_cr >>file &&\n+\tgit add file &&\n+\tgit commit -m \"add line from a\" &&\n+\tgit tag a &&\n+\tgit rm .gitattributes &&\n+\trm file &&\n+\tgit checkout file &&\n+\tgit commit -m \"remove .gitattributes\" &&\n+\tgit tag c &&\n+\tgit checkout side &&\n+\techo same line | append_cr >>file &&\n+\tgit commit -m \"add line from b\" file &&\n+\tgit tag b &&\n+\tgit checkout master\n+'\n+\n+test_expect_success 'Check merging after setting text=auto' '\n+\tgit reset --hard a &&\n+\tgit merge b &&\n+\tcat file | remove_cr >file.temp &&\n+\ttest_cmp file file.temp\n+'\n+\n+test_expect_success 'Check merging addition of text=auto' '\n+\tgit reset --hard b &&\n+\tgit merge a &&\n+\tcat file | remove_cr >file.temp &&\n+\ttest_cmp file file.temp\n+'\n+\n+test_expect_failure 'Test delete/normalize conflict' '\n+\tgit checkout side &&\n+\tgit reset --hard initial &&\n+\tgit rm file &&\n+\tgit commit -m \"remove file\" &&\n+\tgit checkout master &&\n+\tgit reset --hard a^ &&\n+\tgit merge side\n+'\n+\n+test_done\n-- \n1.7.2.rc1.4.g09d06\n"},{"id":"144569","messageId":"3ae294ef30c3539da47d101bc39638e63721eb0e.1277974452.git.eyvind.bernhardsen@gmail.com","threadId":"24250","inReplyTo":"cover.1277974452.git.eyvind.bernhardsen@gmail.com","subject":"[PATCH v5 2/4] Introduce \"double conversion during merge\" more gradually","fromName":"Eyvind Bernhardsen","fromEmail":"eyvind.bernhardsen@gmail.com","sentAt":"2010-07-01T09:09:50Z","receivedAt":"2010-07-01T09:09:50Z","isPatch":true,"sender":{"key":"eyvind.bernhardsen@gmail.com","avatar":"https://avatars.githubusercontent.com/u/106762?v=4"},"body":"From: Junio C Hamano <gitster@pobox.com>\n\nThis marks the recent improvement to the merge machinery that helps people\nwho changed their mind between CRLF/LF an opt in feature, so that we can\nmore easily release it early to everybody, without fear of breaking the\nmajority of users (read: on POSIX) that don't need it.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Eyvind Bernhardsen <eyvind.bernhardsen@gmail.com>\n---\n Documentation/config.txt        |   10 ++++++++++\n Documentation/gitattributes.txt |    5 +++--\n cache.h                         |    1 +\n config.c                        |    5 +++++\n environment.c                   |    1 +\n ll-merge.c                      |    8 +++++---\n t/t6038-merge-text-auto.sh      |    1 +\n 7 files changed, 26 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 72949e7..454cbc7 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -538,6 +538,16 @@ core.sparseCheckout::\n \tEnable \"sparse checkout\" feature. See section \"Sparse checkout\" in\n \tlinkgit:git-read-tree[1] for more information.\n \n+core.mergePrefilter::\n+\tTell git that canonical representation of files in the repository\n+\thas changed over time (e.g. earlier commits record text files\n+\twith CRLF line endings, but recent ones use LF line endings).  In\n+\tsuch a repository, git can convert the data recorded in commits to\n+\ta canonical form before performing a merge to reduce unnecessary\n+\tconflicts.  For more information, see section\n+\t\"Merging branches with differing checkin/checkout attributes\" in\n+\tlinkgit:gitattributes[5].\n+\n add.ignore-errors::\n \tTells 'git add' to continue adding files when some files cannot be\n \tadded due to indexing errors. Equivalent to the '--ignore-errors'\ndiff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt\nindex 22400c1..316fac0 100644\n--- a/Documentation/gitattributes.txt\n+++ b/Documentation/gitattributes.txt\n@@ -351,9 +351,10 @@ clean/smudge filter or text/eol/ident attributes, merging anything\n where the attribute is not in place would normally cause merge\n conflicts.\n \n-To prevent these unnecessary merge conflicts, git runs a virtual\n+To prevent these unnecessary merge conflicts, git can be told to run a virtual\n check-out and check-in of all three stages of a file when resolving a\n-three-way merge.  This prevents changes caused by check-in conversion\n+three-way merge by setting the `core.mergePrefilter` configuration variable.\n+This prevents changes caused by check-in conversion\n from causing spurious merge conflicts when a converted file is merged\n with an unconverted file.\n \ndiff --git a/cache.h b/cache.h\nindex aa725b0..255da02 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -551,6 +551,7 @@ extern int read_replace_refs;\n extern int fsync_object_files;\n extern int core_preload_index;\n extern int core_apply_sparse_checkout;\n+extern int core_merge_prefilter;\n \n enum safe_crlf {\n \tSAFE_CRLF_FALSE = 0,\ndiff --git a/config.c b/config.c\nindex cdcf583..36a0d1a 100644\n--- a/config.c\n+++ b/config.c\n@@ -595,6 +595,11 @@ static int git_default_core_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"core.mergeprefilter\")) {\n+\t\tcore_merge_prefilter = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n+\n \t/* Add other config variables here and to Documentation/config.txt. */\n \treturn 0;\n }\ndiff --git a/environment.c b/environment.c\nindex 83d38d3..59c4515 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -53,6 +53,7 @@ enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n char *notes_ref_name;\n int grafts_replace_parents = 1;\n int core_apply_sparse_checkout;\n+int core_merge_prefilter;\n \n /* Parallel index stat data preload? */\n int core_preload_index = 0;\ndiff --git a/ll-merge.c b/ll-merge.c\nindex 28c6f54..8e59ea7 100644\n--- a/ll-merge.c\n+++ b/ll-merge.c\n@@ -344,9 +344,11 @@ int ll_merge(mmbuffer_t *result_buf,\n \tconst struct ll_merge_driver *driver;\n \tint virtual_ancestor = flag & 01;\n \n-\tnormalize_file(ancestor, path);\n-\tnormalize_file(ours, path);\n-\tnormalize_file(theirs, path);\n+\tif (core_merge_prefilter) {\n+\t\tnormalize_file(ancestor, path);\n+\t\tnormalize_file(ours, path);\n+\t\tnormalize_file(theirs, path);\n+\t}\n \tif (!git_path_check_merge(path, check)) {\n \t\tll_driver_name = check[0].value;\n \t\tif (check[1].value) {\ndiff --git a/t/t6038-merge-text-auto.sh b/t/t6038-merge-text-auto.sh\nindex 44e6003..1f2b3a8 100755\n--- a/t/t6038-merge-text-auto.sh\n+++ b/t/t6038-merge-text-auto.sh\n@@ -5,6 +5,7 @@ test_description='CRLF merge conflict across text=auto change'\n . ./test-lib.sh\n \n test_expect_success setup '\n+\tgit config core.mergeprefilter true &&\n \tgit config core.autocrlf false &&\n \techo first line | append_cr >file &&\n \tgit add file &&\n-- \n1.7.2.rc1.4.g09d06\n"},{"id":"144572","messageId":"1081907f5a1044050c912e742b8500785dcc6b48.1277974452.git.eyvind.bernhardsen@gmail.com","threadId":"24250","inReplyTo":"cover.1277974452.git.eyvind.bernhardsen@gmail.com","subject":"[PATCH v5 3/4] Try normalizing files to avoid delete/modify conflicts when merging","fromName":"Eyvind Bernhardsen","fromEmail":"eyvind.bernhardsen@gmail.com","sentAt":"2010-07-01T09:09:51Z","receivedAt":"2010-07-01T09:09:51Z","isPatch":true,"sender":{"key":"eyvind.bernhardsen@gmail.com","avatar":"https://avatars.githubusercontent.com/u/106762?v=4"},"body":"If a file is modified due to normalization on one branch, and deleted on\nanother, a merge of the two branches will result in a delete/modify\nconflict for that file even if it is otherwise unchanged.\n\nTry to avoid the conflict by normalizing and comparing the \"base\" file\nand the modified file when their sha1s differ.  If they compare equal,\nthe file is considered unmodified and is deleted.\n\nSigned-off-by: Eyvind Bernhardsen <eyvind.bernhardsen@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n merge-recursive.c          |   51 ++++++++++++++++++++++++++++++++++++++++++-\n t/t6038-merge-text-auto.sh |    2 +-\n 2 files changed, 50 insertions(+), 3 deletions(-)\n\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 856e98c..4a84efe 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -1056,6 +1056,53 @@ static unsigned char *stage_sha(const unsigned char *sha, unsigned mode)\n \treturn (is_null_sha1(sha) || mode == 0) ? NULL: (unsigned char *)sha;\n }\n \n+static int read_sha1_strbuf(const unsigned char *sha1, struct strbuf *dst)\n+{\n+\tvoid *buf;\n+\tenum object_type type;\n+\tunsigned long size;\n+\tbuf = read_sha1_file(sha1, &type, &size);\n+\tif (!buf)\n+\t\treturn error(\"cannot read object %s\", sha1_to_hex(sha1));\n+\tif (type != OBJ_BLOB) {\n+\t\tfree(buf);\n+\t\treturn error(\"object %s is not a blob\", sha1_to_hex(sha1));\n+\t}\n+\tstrbuf_attach(dst, buf, size, size + 1);\n+\treturn 0;\n+}\n+\n+static int blob_unchanged(const unsigned char *o_sha,\n+\t\t\t  const unsigned char *a_sha,\n+\t\t\t  const char *path)\n+{\n+\tstruct strbuf o = STRBUF_INIT;\n+\tstruct strbuf a = STRBUF_INIT;\n+\tint ret = 0; /* assume changed for safety */\n+\n+\tif (sha_eq(o_sha, a_sha))\n+\t\treturn 1;\n+\tif (!core_merge_prefilter)\n+\t\treturn 0;\n+\n+\tassert(o_sha && a_sha);\n+\tif (read_sha1_strbuf(o_sha, &o) || read_sha1_strbuf(a_sha, &a))\n+\t\tgoto error_return;\n+\t/*\n+\t * Note: binary | is used so that both renormalizations are\n+\t * performed.  Comparison can be skipped if both files are\n+\t * unchanged since their sha1s have already been compared.\n+\t */\n+\tif (renormalize_buffer(path, o.buf, o.len, &o) |\n+\t    renormalize_buffer(path, a.buf, o.len, &a))\n+\t\tret = (o.len == a.len && !memcmp(o.buf, a.buf, o.len));\n+\n+error_return:\n+\tstrbuf_release(&o);\n+\tstrbuf_release(&a);\n+\treturn ret;\n+}\n+\n /* Per entry merge function */\n static int process_entry(struct merge_options *o,\n \t\t\t const char *path, struct stage_data *entry)\n@@ -1075,8 +1122,8 @@ static int process_entry(struct merge_options *o,\n \tif (o_sha && (!a_sha || !b_sha)) {\n \t\t/* Case A: Deleted in one */\n \t\tif ((!a_sha && !b_sha) ||\n-\t\t    (sha_eq(a_sha, o_sha) && !b_sha) ||\n-\t\t    (!a_sha && sha_eq(b_sha, o_sha))) {\n+\t\t    (!b_sha && blob_unchanged(o_sha, a_sha, path)) ||\n+\t\t    (!a_sha && blob_unchanged(o_sha, b_sha, path))) {\n \t\t\t/* Deleted in both or deleted in one and\n \t\t\t * unchanged in the other */\n \t\t\tif (a_sha)\ndiff --git a/t/t6038-merge-text-auto.sh b/t/t6038-merge-text-auto.sh\nindex 1f2b3a8..1307ec0 100755\n--- a/t/t6038-merge-text-auto.sh\n+++ b/t/t6038-merge-text-auto.sh\n@@ -46,7 +46,7 @@ test_expect_success 'Check merging addition of text=auto' '\n \ttest_cmp file file.temp\n '\n \n-test_expect_failure 'Test delete/normalize conflict' '\n+test_expect_success 'Test delete/normalize conflict' '\n \tgit checkout side &&\n \tgit reset --hard initial &&\n \tgit rm file &&\n-- \n1.7.2.rc1.4.g09d06\n"},{"id":"144570","messageId":"09d063fc517ef0de32adb53e832ad6a7a76649db.1277974452.git.eyvind.bernhardsen@gmail.com","threadId":"24250","inReplyTo":"cover.1277974452.git.eyvind.bernhardsen@gmail.com","subject":"[PATCH v5 4/4] Don't expand CRLFs when normalizing text during merge","fromName":"Eyvind Bernhardsen","fromEmail":"eyvind.bernhardsen@gmail.com","sentAt":"2010-07-01T09:09:52Z","receivedAt":"2010-07-01T09:09:52Z","isPatch":true,"sender":{"key":"eyvind.bernhardsen@gmail.com","avatar":"https://avatars.githubusercontent.com/u/106762?v=4"},"body":"Disable CRLF expansion when convert_to_working_tree() is called from\nnormalize_buffer().  This improves performance when merging branches\nwith conflicting line endings when core.eol=crlf or core.autocrlf=true\nby making the normalization act as if core.eol=lf.\n\nSigned-off-by: Eyvind Bernhardsen <eyvind.bernhardsen@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n convert.c |   27 ++++++++++++++++++++-------\n 1 files changed, 20 insertions(+), 7 deletions(-)\n\ndiff --git a/convert.c b/convert.c\nindex 0203be8..01de9a8 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -741,7 +741,9 @@ int convert_to_git(const char *path, const char *src, size_t len,\n \treturn ret | ident_to_git(path, src, len, dst, ident);\n }\n \n-int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst)\n+static int convert_to_working_tree_internal(const char *path, const char *src,\n+\t\t\t\t\t    size_t len, struct strbuf *dst,\n+\t\t\t\t\t    int normalizing)\n {\n \tstruct git_attr_check check[5];\n \tenum action action = CRLF_GUESS;\n@@ -767,18 +769,29 @@ int convert_to_working_tree(const char *path, const char *src, size_t len, struc\n \t\tsrc = dst->buf;\n \t\tlen = dst->len;\n \t}\n-\taction = determine_action(action, eol_attr);\n-\tret |= crlf_to_worktree(path, src, len, dst, action);\n-\tif (ret) {\n-\t\tsrc = dst->buf;\n-\t\tlen = dst->len;\n+\t/*\n+\t * CRLF conversion can be skipped if normalizing, unless there\n+\t * is a smudge filter.  The filter might expect CRLFs.\n+\t */\n+\tif (filter || !normalizing) {\n+\t\taction = determine_action(action, eol_attr);\n+\t\tret |= crlf_to_worktree(path, src, len, dst, action);\n+\t\tif (ret) {\n+\t\t\tsrc = dst->buf;\n+\t\t\tlen = dst->len;\n+\t\t}\n \t}\n \treturn ret | apply_filter(path, src, len, dst, filter);\n }\n \n+int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst)\n+{\n+\treturn convert_to_working_tree_internal(path, src, len, dst, 0);\n+}\n+\n int renormalize_buffer(const char *path, const char *src, size_t len, struct strbuf *dst)\n {\n-\tint ret = convert_to_working_tree(path, src, len, dst);\n+\tint ret = convert_to_working_tree_internal(path, src, len, dst, 1);\n \tif (ret) {\n \t\tsrc = dst->buf;\n \t\tlen = dst->len;\n-- \n1.7.2.rc1.4.g09d06\n"},{"id":"144580","messageId":"4C2C6BC5.1030905@viscovery.net","threadId":"24250","inReplyTo":"3ae294ef30c3539da47d101bc39638e63721eb0e.1277974452.git.eyvind.bernhardsen@gmail.com","subject":"Re: [PATCH v5 2/4] Introduce \"double conversion during merge\" more gradually","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2010-07-01T10:19:49Z","receivedAt":"2010-07-01T10:19:49Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 7/1/2010 11:09, schrieb Eyvind Bernhardsen:\n> +core.mergePrefilter::\n\nBTW, any particular reason that this is in the core namespace rather than\nmerge namespace? It could be merge.prefilter.\n\n-- Hannes\n"},{"id":"144608","messageId":"7v630z41ao.fsf@alter.siamese.dyndns.org","threadId":"24250","inReplyTo":"4C2C6BC5.1030905@viscovery.net","subject":"Re: [PATCH v5 2/4] Introduce \"double conversion during merge\" more gradually","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-07-01T16:25:19Z","receivedAt":"2010-07-01T16:25:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j.sixt@viscovery.net> writes:\n\n> Am 7/1/2010 11:09, schrieb Eyvind Bernhardsen:\n>> +core.mergePrefilter::\n>\n> BTW, any particular reason that this is in the core namespace rather than\n> merge namespace? It could be merge.prefilter.\n\nGood point.\n\nSomehow to me \"prefilter\" does not sound to convey what really is going on\nhere, though.\n"},{"id":"144612","messageId":"D2F8C67C-F7AE-4523-870F-879B741C2591@gmail.com","threadId":"24250","inReplyTo":"7v630z41ao.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v5 2/4] Introduce \"double conversion during merge\" more gradually","fromName":"Eyvind Bernhardsen","fromEmail":"eyvind.bernhardsen@gmail.com","sentAt":"2010-07-01T16:41:42Z","receivedAt":"2010-07-01T16:41:42Z","isPatch":true,"sender":{"key":"eyvind.bernhardsen@gmail.com","avatar":"https://avatars.githubusercontent.com/u/106762?v=4"},"body":"On 1. juli 2010, at 18:25, Junio C Hamano <gitster@pobox.com> wrote:\n\n> Johannes Sixt <j.sixt@viscovery.net> writes:\n> \n>> Am 7/1/2010 11:09, schrieb Eyvind Bernhardsen:\n>>> +core.mergePrefilter::\n>> \n>> BTW, any particular reason that this is in the core namespace rather than\n>> merge namespace? It could be merge.prefilter.\n> \n> Good point.\n> \n> Somehow to me \"prefilter\" does not sound to convey what really is going on\n> here, though.\n\n\"Doubleconvert\" doesn't really mean anything either though, and \"convert\" and \"normalise\" are too generic. I think the problem is that there's no existing name for what convert.c does.\n\nI chose \"filter\" because of the filter property; the crlf and ident things can be regarded as built-in filters.\n-- \nEyvind\n"},{"id":"144613","messageId":"m3iq4znnfr.fsf@localhost.localdomain","threadId":"24250","inReplyTo":"D2F8C67C-F7AE-4523-870F-879B741C2591@gmail.com","subject":"Re: [PATCH v5 2/4] Introduce \"double conversion during merge\" more gradually","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-07-01T17:05:17Z","receivedAt":"2010-07-01T17:05:17Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Eyvind Bernhardsen <eyvind.bernhardsen@gmail.com> writes:\n> On 1. juli 2010, at 18:25, Junio C Hamano <gitster@pobox.com> wrote:\n> > Johannes Sixt <j.sixt@viscovery.net> writes:\n> >> Am 7/1/2010 11:09, schrieb Eyvind Bernhardsen:\n>>>\n>>>> +core.mergePrefilter::\n>>> \n>>> BTW, any particular reason that this is in the core namespace rather than\n>>> merge namespace? It could be merge.prefilter.\n>> \n>> Good point.\n>> \n>> Somehow to me \"prefilter\" does not sound to convey what really is going on\n>> here, though.\n> \n> \"Doubleconvert\" doesn't really mean anything either though, and\n> \"convert\" and \"normalise\" are too generic. I think the problem is\n> that there's no existing name for what convert.c does.\n> \n> I chose \"filter\" because of the filter property; the crlf and ident\n> things can be regarded as built-in filters.  -- Eyvind\n\nWhat about `merge.renormalize' ;-) ?\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"144617","messageId":"20100701185712.GA22421@pvv.org","threadId":"24250","inReplyTo":"m3iq4znnfr.fsf@localhost.localdomain","subject":"Re: [PATCH v5 2/4] Introduce \"double conversion during merge\" more gradually","fromName":"Finn Arne Gangstad","fromEmail":"finnag@pvv.org","sentAt":"2010-07-01T18:57:12Z","receivedAt":"2010-07-01T18:57:12Z","isPatch":true,"sender":{"key":"finnag@pvv.org","avatar":"https://gravatar.com/avatar/b421ddd58c3f0f93aa473e17b98bb8d53c221fef741746bc8cb59fae4ec6d95e?d=mp&s=160"},"body":"On Thu, Jul 01, 2010 at 10:05:17AM -0700, Jakub Narebski wrote:\n> Eyvind Bernhardsen <eyvind.bernhardsen@gmail.com> writes:\n> > On 1. juli 2010, at 18:25, Junio C Hamano <gitster@pobox.com> wrote:\n> > > Johannes Sixt <j.sixt@viscovery.net> writes:\n> > >> Am 7/1/2010 11:09, schrieb Eyvind Bernhardsen:\n> >>>\n> >>>> +core.mergePrefilter::\n> [...]\n> >> \n> >> Somehow to me \"prefilter\" does not sound to convey what really is going on\n> >> here, though.\n> > \n> > \"Doubleconvert\" doesn't really mean anything either though, and\n> > \"convert\" and \"normalise\" are too generic. I think the problem is\n> > that there's no existing name for what convert.c does.\n> > \n> > I chose \"filter\" because of the filter property; the crlf and ident\n> > things can be regarded as built-in filters.  -- Eyvind\n> \n> What about `merge.renormalize' ;-) ?\n\nBest so far! Or what about \"merge.canonicalize\"? Sorry for bikeshedding :)\n\n- Finn Arne\n"},{"id":"144624","messageId":"2B6AD816-8BF8-4778-A5AD-D31DA154E8F5@gmail.com","threadId":"24250","inReplyTo":"m3iq4znnfr.fsf@localhost.localdomain","subject":"Re: [PATCH v5 2/4] Introduce \"double conversion during merge\" more gradually","fromName":"Eyvind Bernhardsen","fromEmail":"eyvind.bernhardsen@gmail.com","sentAt":"2010-07-01T20:13:28Z","receivedAt":"2010-07-01T20:13:28Z","isPatch":true,"sender":{"key":"eyvind.bernhardsen@gmail.com","avatar":"https://avatars.githubusercontent.com/u/106762?v=4"},"body":"On 1. juli 2010, at 19.05, Jakub Narebski wrote:\n\n> Eyvind Bernhardsen <eyvind.bernhardsen@gmail.com> writes:\n>> On 1. juli 2010, at 18:25, Junio C Hamano <gitster@pobox.com> wrote:\n>>> Somehow to me \"prefilter\" does not sound to convey what really is going on\n>>> here, though.\n>> \n>> \"Doubleconvert\" doesn't really mean anything either though, and\n>> \"convert\" and \"normalise\" are too generic. I think the problem is\n>> that there's no existing name for what convert.c does.\n>> \n>> I chose \"filter\" because of the filter property; the crlf and ident\n>> things can be regarded as built-in filters.  -- Eyvind\n> \n> What about `merge.renormalize' ;-) ?\n\nI like it, but it's still a bit generic.  \"merge.renormalizeContent\", perhaps?\n-- \nEyvind\n"},{"id":"144625","messageId":"m3aaqbnemz.fsf@localhost.localdomain","threadId":"24250","inReplyTo":"20100701185712.GA22421@pvv.org","subject":"Re: [PATCH v5 2/4] Introduce \"double conversion during merge\" more gradually","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-07-01T20:15:28Z","receivedAt":"2010-07-01T20:15:28Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Finn Arne Gangstad <finnag@pvv.org> writes:\n> On Thu, Jul 01, 2010 at 10:05:17AM -0700, Jakub Narebski wrote:\n>> Eyvind Bernhardsen <eyvind.bernhardsen@gmail.com> writes:\n>>> On 1. juli 2010, at 18:25, Junio C Hamano <gitster@pobox.com> wrote:\n>>>> Johannes Sixt <j.sixt@viscovery.net> writes:\n>>>>> Am 7/1/2010 11:09, schrieb Eyvind Bernhardsen:\n>>>>>\n>>>>>> +core.mergePrefilter::\n>> [...]\n>>>> \n>>>> Somehow to me \"prefilter\" does not sound to convey what really is going on\n>>>> here, though.\n>>> \n>>> \"Doubleconvert\" doesn't really mean anything either though, and\n>>> \"convert\" and \"normalise\" are too generic. I think the problem is\n>>> that there's no existing name for what convert.c does.\n>>> \n>>> I chose \"filter\" because of the filter property; the crlf and ident\n>>> things can be regarded as built-in filters.  -- Eyvind\n>> \n>> What about `merge.renormalize' ;-) ?\n> \n> Best so far! Or what about \"merge.canonicalize\"? Sorry for bikeshedding :)\n\nPerhaps `merge.regularize'?  Or `merge.normalizeToWorkTree'?\nIt is about converting to worktree version according to current\nsettings, IIUC...\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"144635","messageId":"531FFACB-CBEA-4BC6-B831-CC7C6F954DB5@gmail.com","threadId":"24250","inReplyTo":"m3aaqbnemz.fsf@localhost.localdomain","subject":"Re: [PATCH v5 2/4] Introduce \"double conversion during merge\" more gradually","fromName":"Eyvind Bernhardsen","fromEmail":"eyvind.bernhardsen@gmail.com","sentAt":"2010-07-01T20:25:01Z","receivedAt":"2010-07-01T20:25:01Z","isPatch":true,"sender":{"key":"eyvind.bernhardsen@gmail.com","avatar":"https://avatars.githubusercontent.com/u/106762?v=4"},"body":"On 1. juli 2010, at 22.15, Jakub Narebski wrote:\n\n> Finn Arne Gangstad <finnag@pvv.org> writes:\n>> On Thu, Jul 01, 2010 at 10:05:17AM -0700, Jakub Narebski wrote:\n>>> What about `merge.renormalize' ;-) ?\n>> \n>> Best so far! Or what about \"merge.canonicalize\"? Sorry for bikeshedding :)\n> \n> Perhaps `merge.regularize'?  Or `merge.normalizeToWorkTree'?\n> It is about converting to worktree version according to current\n> settings, IIUC...\n\nAlmost, it's about converting to the _repository_ version according to current (that is, merged) settings.  Since the content is already in repository format it needs to be converted to the worktree version before it is converted back, hence Junio's \"doubleConvert\".\n\n\"merge.renormalizeUsingMergedGitattributes\"?\n-- \nEyvind\n"}]}