{"thread":{"id":"60426","subject":"[PATCH] merge: ignore whitespace changes when detecting renames","startedAt":"2023-10-25T12:14:22Z","lastAt":"2023-10-25T12:14:22Z","messageCount":1,"participants":["Stefan Muenzel via GitGitGadget"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"483853","messageId":"pull.1600.git.git.1698236057229.gitgitgadget@gmail.com","threadId":"60426","inReplyTo":null,"subject":"[PATCH] merge: ignore whitespace changes when detecting renames","fromName":"Stefan Muenzel via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2023-10-25T12:14:16Z","receivedAt":"2023-10-25T12:14:22Z","isPatch":true,"sender":{"key":"name:Stefan Muenzel","avatar":null},"body":"From: Stefan Muenzel <source@s.muenzel.net>\n\nThe options ignore-space-changes and ignore-all-space for\nmerge strategies based on \"ort\" are now propagated\nto the computation of file renames, by normalizing spacing\nchanges when computing file hashes.\n\nSigned-off-by: Stefan Muenzel <source@s.muenzel.net>\n---\n    merge: ignore whitespace changes when detecting renames\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1600%2Fsmuenzel%2Frenames-ignore-whitespace-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1600/smuenzel/renames-ignore-whitespace-v1\nPull-Request: https://github.com/git/git/pull/1600\n\n diff.c            |  4 ++++\n diffcore-delta.c  | 14 ++++++++++++++\n diffcore-rename.c |  9 +++++++++\n diffcore.h        |  2 ++\n merge-recursive.c |  1 +\n 5 files changed, 30 insertions(+)\n\ndiff --git a/diff.c b/diff.c\nindex 2c602df10a3..916cc38f57c 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -4081,6 +4081,7 @@ int diff_populate_filespec(struct repository *r,\n {\n \tint size_only = options ? options->check_size_only : 0;\n \tint check_binary = options ? options->check_binary : 0;\n+\tint ignore_whitespace = options ? options->ignore_whitespace : 0;\n \tint err = 0;\n \tint conv_flags = global_conv_flags_eol;\n \t/*\n@@ -4090,6 +4091,9 @@ int diff_populate_filespec(struct repository *r,\n \tif (conv_flags & CONV_EOL_RNDTRP_DIE)\n \t\tconv_flags = CONV_EOL_RNDTRP_WARN;\n \n+\tif (ignore_whitespace)\n+\t\ts->ignore_whitespace = 1;\n+\n \tif (!DIFF_FILE_VALID(s))\n \t\tdie(\"internal error: asking to populate invalid file.\");\n \tif (S_ISDIR(s->mode))\ndiff --git a/diffcore-delta.c b/diffcore-delta.c\nindex c30b56e983b..e2bb5f9133a 100644\n--- a/diffcore-delta.c\n+++ b/diffcore-delta.c\n@@ -130,6 +130,7 @@ static struct spanhash_top *hash_chars(struct repository *r,\n \tunsigned char *buf = one->data;\n \tunsigned int sz = one->size;\n \tint is_text = !diff_filespec_is_binary(r, one);\n+\tint ignore_whitespace = one->ignore_whitespace;\n \n \ti = INITIAL_HASH_SIZE;\n \thash = xmalloc(st_add(sizeof(*hash),\n@@ -149,6 +150,19 @@ static struct spanhash_top *hash_chars(struct repository *r,\n \t\tif (is_text && c == '\\r' && sz && *buf == '\\n')\n \t\t\tcontinue;\n \n+\t\tif (is_text && ignore_whitespace && isspace(c)) {\n+\t\t\tif (sz) {\n+\t\t\t\tchar next = *buf;\n+\t\t\t\tif ( c == '\\n' && next == '\\n')\n+\t\t\t\t\tcontinue;\n+\t\t\t\telse if ( c != '\\n' && isspace(next))\n+\t\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif ( c != '\\n')\n+\t\t\t\t/* Normalize whitespace to space*/\n+\t\t\t\tc = ' ';\n+\t\t}\n+\n \t\taccum1 = (accum1 << 7) ^ (accum2 >> 25);\n \t\taccum2 = (accum2 << 7) ^ (old_1 >> 25);\n \t\taccum1 += c;\ndiff --git a/diffcore-rename.c b/diffcore-rename.c\nindex 5a6e2bcac71..ee68442afc3 100644\n--- a/diffcore-rename.c\n+++ b/diffcore-rename.c\n@@ -14,6 +14,7 @@\n #include \"string-list.h\"\n #include \"strmap.h\"\n #include \"trace2.h\"\n+#include \"xdiff-interface.h\"\n \n /* Table of rename/copy destinations */\n \n@@ -950,6 +951,10 @@ static int find_basename_matches(struct diff_options *options,\n \t\t.info = info\n \t};\n \n+\tdpf_options.ignore_whitespace =\n+\t\tDIFF_XDL_TST(options, IGNORE_WHITESPACE_CHANGE)\n+\t\t|| DIFF_XDL_TST(options, IGNORE_WHITESPACE);\n+\n \t/*\n \t * Create maps of basename -> fullname(s) for remaining sources and\n \t * dests.\n@@ -1402,6 +1407,10 @@ void diffcore_rename_extended(struct diff_options *options,\n \t\t.repo = options->repo\n \t};\n \n+\tdpf_options.ignore_whitespace =\n+\t\tDIFF_XDL_TST(options, IGNORE_WHITESPACE_CHANGE)\n+\t\t|| DIFF_XDL_TST(options, IGNORE_WHITESPACE);\n+\n \ttrace2_region_enter(\"diff\", \"setup\", options->repo);\n \tinfo.setup = 0;\n \tassert(!dir_rename_count || strmap_empty(dir_rename_count));\ndiff --git a/diffcore.h b/diffcore.h\nindex 5ffe4ec788f..d6bee67e646 100644\n--- a/diffcore.h\n+++ b/diffcore.h\n@@ -61,6 +61,7 @@ struct diff_filespec {\n \tunsigned has_more_entries : 1; /* only appear in combined diff */\n \t/* data should be considered \"binary\"; -1 means \"don't know yet\" */\n \tsigned int is_binary : 2;\n+\tunsigned ignore_whitespace : 1;\n \tstruct userdiff_driver *driver;\n };\n \n@@ -78,6 +79,7 @@ void diff_queued_diff_prefetch(void *repository);\n struct diff_populate_filespec_options {\n \tunsigned check_size_only : 1;\n \tunsigned check_binary : 1;\n+\tunsigned ignore_whitespace : 1;\n \n \t/*\n \t * If an object is missing, diff_populate_filespec() will invoke this\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex e3beb0801b1..0e52c45158a 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -1894,6 +1894,7 @@ static struct diff_queue_struct *get_diffpairs(struct merge_options *opt,\n \trepo_diff_setup(opt->repo, &opts);\n \topts.flags.recursive = 1;\n \topts.flags.rename_empty = 0;\n+\topts.xdl_opts = opt->xdl_opts;\n \topts.detect_rename = merge_detect_rename(opt);\n \t/*\n \t * We do not have logic to handle the detection of copies.  In\n\nbase-commit: 2e8e77cbac8ac17f94eee2087187fa1718e38b14\n-- \ngitgitgadget\n"}]}