{"thread":{"id":"29670","subject":"[PATCH 0/5] diff --ignore-case","startedAt":"2012-02-20T02:16:23Z","lastAt":"2012-02-22T18:07:56Z","messageCount":14,"participants":["Junio C Hamano","Johannes Sixt","Thomas Rast","Chris Leong","Jakub Narebski"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"184958","messageId":"1329704188-9955-1-git-send-email-gitster@pobox.com","threadId":"29670","inReplyTo":null,"subject":"[PATCH 0/5] diff --ignore-case","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-20T02:16:23Z","receivedAt":"2012-02-20T02:16:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This teaches our \"diff\" machinery to optionally consider lines that are\ndifferent only in upper/lower-cases to be equivalent.\n\nJunio C Hamano (5):\n  xdiff: remove XDL_PATCH_* macros\n  xdiff: PATIENCE/HISTOGRAM are not independent option bits\n  xdiff: introduce XDF_INEXACT_MATCH\n  xdiff: introduce XDF_IGNORE_CASE\n  diff: --ignore-case\n\n Documentation/diff-options.txt |    4 +++\n diff.c                         |    8 +++---\n diff.h                         |    2 ++\n merge-recursive.c              |    4 +--\n t/lib-diff-alternative.sh      |   45 +++++++++++++++++++++++++++++++--\n t/t4033-diff-patience.sh       |    6 +++++\n t/t4050-diff-histogram.sh      |    2 ++\n xdiff/xdiff.h                  |   19 ++++++++------\n xdiff/xdiffi.c                 |    4 +--\n xdiff/xhistogram.c             |    2 +-\n xdiff/xpatience.c              |    2 +-\n xdiff/xprepare.c               |   21 ++++++++--------\n xdiff/xutils.c                 |   54 ++++++++++++++++++++++++++++++++--------\n 13 files changed, 133 insertions(+), 40 deletions(-)\n\n-- \n1.7.9.1.265.g25f75\n"},{"id":"184959","messageId":"1329704188-9955-2-git-send-email-gitster@pobox.com","threadId":"29670","inReplyTo":"1329704188-9955-1-git-send-email-gitster@pobox.com","subject":"[PATCH 1/5] xdiff: remove XDL_PATCH_* macros","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-20T02:16:24Z","receivedAt":"2012-02-20T02:16:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"These are not used anywhere in our codebase, and the bit assignment\ndefinition is merely confusing.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n xdiff/xdiff.h |    5 -----\n 1 file changed, 5 deletions(-)\n\ndiff --git a/xdiff/xdiff.h b/xdiff/xdiff.h\nindex 00d36c3..70c8b87 100644\n--- a/xdiff/xdiff.h\n+++ b/xdiff/xdiff.h\n@@ -36,11 +36,6 @@ extern \"C\" {\n #define XDF_HISTOGRAM_DIFF (1 << 6)\n #define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE | XDF_IGNORE_WHITESPACE_AT_EOL)\n \n-#define XDL_PATCH_NORMAL '-'\n-#define XDL_PATCH_REVERSE '+'\n-#define XDL_PATCH_MODEMASK ((1 << 8) - 1)\n-#define XDL_PATCH_IGNOREBSPACE (1 << 8)\n-\n #define XDL_EMIT_FUNCNAMES (1 << 0)\n #define XDL_EMIT_COMMON (1 << 1)\n #define XDL_EMIT_FUNCCONTEXT (1 << 2)\n-- \n1.7.9.1.265.g25f75\n"},{"id":"184960","messageId":"1329704188-9955-3-git-send-email-gitster@pobox.com","threadId":"29670","inReplyTo":"1329704188-9955-1-git-send-email-gitster@pobox.com","subject":"[PATCH 2/5] xdiff: PATIENCE/HISTOGRAM are not independent option bits","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-20T02:16:25Z","receivedAt":"2012-02-20T02:16:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Because the default Myers, patience and histogram algorithms cannot be in\neffect at the same time, XDL_PATIENCE_DIFF and XDL_HISTOGRAM_DIFF are not\nindependent bits.  Instead of wasting one bit per algorithm, define a few\nmacros to access the few bits they occupy and update the code that access\nthem.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n diff.c             |    4 ++--\n diff.h             |    2 ++\n merge-recursive.c  |    4 ++--\n xdiff/xdiff.h      |    5 ++++-\n xdiff/xdiffi.c     |    4 ++--\n xdiff/xhistogram.c |    2 +-\n xdiff/xpatience.c  |    2 +-\n xdiff/xprepare.c   |   21 ++++++++++-----------\n 8 files changed, 24 insertions(+), 20 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 374ecf3..52cda7a 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -3400,9 +3400,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)\n \telse if (!strcmp(arg, \"--ignore-space-at-eol\"))\n \t\tDIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL);\n \telse if (!strcmp(arg, \"--patience\"))\n-\t\tDIFF_XDL_SET(options, PATIENCE_DIFF);\n+\t\toptions->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);\n \telse if (!strcmp(arg, \"--histogram\"))\n-\t\tDIFF_XDL_SET(options, HISTOGRAM_DIFF);\n+\t\toptions->xdl_opts = DIFF_WITH_ALG(options, HISTOGRAM_DIFF);\n \n \t/* flags options */\n \telse if (!strcmp(arg, \"--binary\")) {\ndiff --git a/diff.h b/diff.h\nindex 0c51724..e688a48 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -88,6 +88,8 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)\n #define DIFF_XDL_SET(opts, flag)    ((opts)->xdl_opts |= XDF_##flag)\n #define DIFF_XDL_CLR(opts, flag)    ((opts)->xdl_opts &= ~XDF_##flag)\n \n+#define DIFF_WITH_ALG(opts, flag)   (((opts)->xdl_opts & ~XDF_DIFF_ALGORITHM_MASK) | XDF_##flag)\n+\n enum diff_words_type {\n \tDIFF_WORDS_NONE = 0,\n \tDIFF_WORDS_PORCELAIN,\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex cc664c3..1d574fe 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -2069,9 +2069,9 @@ int parse_merge_opt(struct merge_options *o, const char *s)\n \telse if (!prefixcmp(s, \"subtree=\"))\n \t\to->subtree_shift = s + strlen(\"subtree=\");\n \telse if (!strcmp(s, \"patience\"))\n-\t\to->xdl_opts |= XDF_PATIENCE_DIFF;\n+\t\to->xdl_opts = DIFF_WITH_ALG(o, PATIENCE_DIFF);\n \telse if (!strcmp(s, \"histogram\"))\n-\t\to->xdl_opts |= XDF_HISTOGRAM_DIFF;\n+\t\to->xdl_opts = DIFF_WITH_ALG(o, HISTOGRAM_DIFF);\n \telse if (!strcmp(s, \"ignore-space-change\"))\n \t\to->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;\n \telse if (!strcmp(s, \"ignore-all-space\"))\ndiff --git a/xdiff/xdiff.h b/xdiff/xdiff.h\nindex 70c8b87..09215af 100644\n--- a/xdiff/xdiff.h\n+++ b/xdiff/xdiff.h\n@@ -32,9 +32,12 @@ extern \"C\" {\n #define XDF_IGNORE_WHITESPACE (1 << 2)\n #define XDF_IGNORE_WHITESPACE_CHANGE (1 << 3)\n #define XDF_IGNORE_WHITESPACE_AT_EOL (1 << 4)\n+#define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE | XDF_IGNORE_WHITESPACE_AT_EOL)\n+\n #define XDF_PATIENCE_DIFF (1 << 5)\n #define XDF_HISTOGRAM_DIFF (1 << 6)\n-#define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE | XDF_IGNORE_WHITESPACE_AT_EOL)\n+#define XDF_DIFF_ALGORITHM_MASK (XDF_PATIENCE_DIFF | XDF_HISTOGRAM_DIFF)\n+#define XDF_DIFF_ALG(x) ((x) & XDF_DIFF_ALGORITHM_MASK)\n \n #define XDL_EMIT_FUNCNAMES (1 << 0)\n #define XDL_EMIT_COMMON (1 << 1)\ndiff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c\nindex 75a3922..bc889e8 100644\n--- a/xdiff/xdiffi.c\n+++ b/xdiff/xdiffi.c\n@@ -328,10 +328,10 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,\n \txdalgoenv_t xenv;\n \tdiffdata_t dd1, dd2;\n \n-\tif (xpp->flags & XDF_PATIENCE_DIFF)\n+\tif (XDF_DIFF_ALG(xpp->flags) == XDF_PATIENCE_DIFF)\n \t\treturn xdl_do_patience_diff(mf1, mf2, xpp, xe);\n \n-\tif (xpp->flags & XDF_HISTOGRAM_DIFF)\n+\tif (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF)\n \t\treturn xdl_do_histogram_diff(mf1, mf2, xpp, xe);\n \n \tif (xdl_prepare_env(mf1, mf2, xpp, xe) < 0) {\ndiff --git a/xdiff/xhistogram.c b/xdiff/xhistogram.c\nindex 18f6f99..bf99787 100644\n--- a/xdiff/xhistogram.c\n+++ b/xdiff/xhistogram.c\n@@ -252,7 +252,7 @@ static int fall_back_to_classic_diff(struct histindex *index,\n \t\tint line1, int count1, int line2, int count2)\n {\n \txpparam_t xpp;\n-\txpp.flags = index->xpp->flags & ~XDF_HISTOGRAM_DIFF;\n+\txpp.flags = index->xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;\n \n \treturn xdl_fall_back_diff(index->env, &xpp,\n \t\t\t\t  line1, count1, line2, count2);\ndiff --git a/xdiff/xpatience.c b/xdiff/xpatience.c\nindex fdd7d02..04e1a1a 100644\n--- a/xdiff/xpatience.c\n+++ b/xdiff/xpatience.c\n@@ -288,7 +288,7 @@ static int fall_back_to_classic_diff(struct hashmap *map,\n \t\tint line1, int count1, int line2, int count2)\n {\n \txpparam_t xpp;\n-\txpp.flags = map->xpp->flags & ~XDF_PATIENCE_DIFF;\n+\txpp.flags = map->xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;\n \n \treturn xdl_fall_back_diff(map->env, &xpp,\n \t\t\t\t  line1, count1, line2, count2);\ndiff --git a/xdiff/xprepare.c b/xdiff/xprepare.c\nindex e419f4f..63a22c6 100644\n--- a/xdiff/xprepare.c\n+++ b/xdiff/xprepare.c\n@@ -181,7 +181,7 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_\n \tif (!(recs = (xrecord_t **) xdl_malloc(narec * sizeof(xrecord_t *))))\n \t\tgoto abort;\n \n-\tif (xpp->flags & XDF_HISTOGRAM_DIFF)\n+\tif (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF)\n \t\thbits = hsize = 0;\n \telse {\n \t\thbits = xdl_hashbits((unsigned int) narec);\n@@ -209,8 +209,8 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_\n \t\t\tcrec->ha = hav;\n \t\t\trecs[nrec++] = crec;\n \n-\t\t\tif (!(xpp->flags & XDF_HISTOGRAM_DIFF) &&\n-\t\t\t\txdl_classify_record(pass, cf, rhash, hbits, crec) < 0)\n+\t\t\tif ((XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF) &&\n+\t\t\t    xdl_classify_record(pass, cf, rhash, hbits, crec) < 0)\n \t\t\t\tgoto abort;\n \t\t}\n \t}\n@@ -273,16 +273,15 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,\n \t * (nrecs) will be updated correctly anyway by\n \t * xdl_prepare_ctx().\n \t */\n-\tsample = xpp->flags & XDF_HISTOGRAM_DIFF ? XDL_GUESS_NLINES2 : XDL_GUESS_NLINES1;\n+\tsample = (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF\n+\t\t  ? XDL_GUESS_NLINES2 : XDL_GUESS_NLINES1);\n \n \tenl1 = xdl_guess_lines(mf1, sample) + 1;\n \tenl2 = xdl_guess_lines(mf2, sample) + 1;\n \n-\tif (!(xpp->flags & XDF_HISTOGRAM_DIFF) &&\n-\t\txdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0) {\n-\n+\tif (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF &&\n+\t    xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0)\n \t\treturn -1;\n-\t}\n \n \tif (xdl_prepare_ctx(1, mf1, enl1, xpp, &cf, &xe->xdf1) < 0) {\n \n@@ -296,9 +295,9 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,\n \t\treturn -1;\n \t}\n \n-\tif (!(xpp->flags & XDF_PATIENCE_DIFF) &&\n-\t\t\t!(xpp->flags & XDF_HISTOGRAM_DIFF) &&\n-\t\t\txdl_optimize_ctxs(&cf, &xe->xdf1, &xe->xdf2) < 0) {\n+\tif ((XDF_DIFF_ALG(xpp->flags) != XDF_PATIENCE_DIFF) &&\n+\t    (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF) &&\n+\t    xdl_optimize_ctxs(&cf, &xe->xdf1, &xe->xdf2) < 0) {\n \n \t\txdl_free_ctx(&xe->xdf2);\n \t\txdl_free_ctx(&xe->xdf1);\n-- \n1.7.9.1.265.g25f75\n"},{"id":"184963","messageId":"1329704188-9955-4-git-send-email-gitster@pobox.com","threadId":"29670","inReplyTo":"1329704188-9955-1-git-send-email-gitster@pobox.com","subject":"[PATCH 3/5] xdiff: introduce XDF_INEXACT_MATCH","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-20T02:16:26Z","receivedAt":"2012-02-20T02:16:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The XDF_WHITESPACE_FLAGS mask is used to decide if a simple memcmp() is\nsufficient to tell if two lines are the same for the purpose of producing\ndiff. In the current code, only options in the ignore-whitespace family\nhappen to call for a matching logic that is more complex than memcmp(),\nbut when we add new options, e.g. ignore-case, it will become apparent\nthat the mask is misnamed.\n\nIntroduce XDF_INEXACT_MATCH mask to express its true meaning: when any of\nthese bits are set, we may need to inspect the contents of the two lines\nthat are not exactly the same, as we may still consider them \"matching\".\n\nThe XDF_WHITESPACE_FLAGS will become useful again in a later patch in the\nseries and its definition is kept.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n diff.c         |    2 +-\n xdiff/xdiff.h  |    6 +++++-\n xdiff/xutils.c |    4 ++--\n 3 files changed, 8 insertions(+), 4 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 52cda7a..87b2ec1 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -2142,7 +2142,7 @@ static void builtin_diff(const char *name_a,\n \t\tstruct emit_callback ecbdata;\n \t\tconst struct userdiff_funcname *pe;\n \n-\t\tif (!DIFF_XDL_TST(o, WHITESPACE_FLAGS) || must_show_header) {\n+\t\tif (!DIFF_XDL_TST(o, INEXACT_MATCH) || must_show_header) {\n \t\t\tfprintf(o->file, \"%s\", header.buf);\n \t\t\tstrbuf_reset(&header);\n \t\t}\ndiff --git a/xdiff/xdiff.h b/xdiff/xdiff.h\nindex 09215af..48793f9 100644\n--- a/xdiff/xdiff.h\n+++ b/xdiff/xdiff.h\n@@ -32,7 +32,11 @@ extern \"C\" {\n #define XDF_IGNORE_WHITESPACE (1 << 2)\n #define XDF_IGNORE_WHITESPACE_CHANGE (1 << 3)\n #define XDF_IGNORE_WHITESPACE_AT_EOL (1 << 4)\n-#define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE | XDF_IGNORE_WHITESPACE_AT_EOL)\n+#define XDF_WHITESPACE_FLAGS \\\n+\t(XDF_IGNORE_WHITESPACE | \\\n+\t XDF_IGNORE_WHITESPACE_CHANGE | \\\n+\t XDF_IGNORE_WHITESPACE_AT_EOL)\n+#define XDF_INEXACT_MATCH XDF_WHITESPACE_FLAGS\n \n #define XDF_PATIENCE_DIFF (1 << 5)\n #define XDF_HISTOGRAM_DIFF (1 << 6)\ndiff --git a/xdiff/xutils.c b/xdiff/xutils.c\nindex 0de084e..aa6de74 100644\n--- a/xdiff/xutils.c\n+++ b/xdiff/xutils.c\n@@ -176,7 +176,7 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)\n \n \tif (s1 == s2 && !memcmp(l1, l2, s1))\n \t\treturn 1;\n-\tif (!(flags & XDF_WHITESPACE_FLAGS))\n+\tif (!(flags & XDF_INEXACT_MATCH))\n \t\treturn 0;\n \n \ti1 = 0;\n@@ -281,7 +281,7 @@ unsigned long xdl_hash_record(char const **data, char const *top, long flags) {\n \tunsigned long ha = 5381;\n \tchar const *ptr = *data;\n \n-\tif (flags & XDF_WHITESPACE_FLAGS)\n+\tif (flags & XDF_INEXACT_MATCH)\n \t\treturn xdl_hash_record_with_whitespace(data, top, flags);\n \n \tfor (; ptr < top && *ptr != '\\n'; ptr++) {\n-- \n1.7.9.1.265.g25f75\n"},{"id":"184962","messageId":"1329704188-9955-5-git-send-email-gitster@pobox.com","threadId":"29670","inReplyTo":"1329704188-9955-1-git-send-email-gitster@pobox.com","subject":"[PATCH 4/5] xdiff: introduce XDF_IGNORE_CASE","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-20T02:16:27Z","receivedAt":"2012-02-20T02:16:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Teach the hash function and per-line comparison logic to compare lines\nwhile ignoring the differences in case.  It is not an ignore-whitespace\noption but still needs to trigger the inexact match logic, and that is\nwhy the previous step introduced XDF_INEXACT_MATCH mask.\n\nAssign the 7th bit for this option, and move the bits to select diff\nalgorithms out of the way in order to leave room for a few bits to add\nmore variants of ignore-whitespace, such as --ignore-tab-expansion, if\nsomebody else is inclined to do so later.\n\nWe would still need to teach the front-end to flip this bit, for this\nchange to be any useful.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n xdiff/xdiff.h  |    7 ++++---\n xdiff/xutils.c |   50 ++++++++++++++++++++++++++++++++++++++++++--------\n 2 files changed, 46 insertions(+), 11 deletions(-)\n\ndiff --git a/xdiff/xdiff.h b/xdiff/xdiff.h\nindex 48793f9..5a01a0e 100644\n--- a/xdiff/xdiff.h\n+++ b/xdiff/xdiff.h\n@@ -36,10 +36,11 @@ extern \"C\" {\n \t(XDF_IGNORE_WHITESPACE | \\\n \t XDF_IGNORE_WHITESPACE_CHANGE | \\\n \t XDF_IGNORE_WHITESPACE_AT_EOL)\n-#define XDF_INEXACT_MATCH XDF_WHITESPACE_FLAGS\n+#define XDF_IGNORE_CASE (1 << 7)\n+#define XDF_INEXACT_MATCH (XDF_WHITESPACE_FLAGS | XDF_IGNORE_CASE)\n \n-#define XDF_PATIENCE_DIFF (1 << 5)\n-#define XDF_HISTOGRAM_DIFF (1 << 6)\n+#define XDF_PATIENCE_DIFF (1 << 8)\n+#define XDF_HISTOGRAM_DIFF (1 << 9)\n #define XDF_DIFF_ALGORITHM_MASK (XDF_PATIENCE_DIFF | XDF_HISTOGRAM_DIFF)\n #define XDF_DIFF_ALG(x) ((x) & XDF_DIFF_ALGORITHM_MASK)\n \ndiff --git a/xdiff/xutils.c b/xdiff/xutils.c\nindex aa6de74..925f1d0 100644\n--- a/xdiff/xutils.c\n+++ b/xdiff/xutils.c\n@@ -170,6 +170,19 @@ long xdl_guess_lines(mmfile_t *mf, long sample) {\n \treturn nl + 1;\n }\n \n+static inline int match_a_byte(char ch1, char ch2, long flags)\n+{\n+\tif (ch1 == ch2)\n+\t\treturn 1;\n+\tif (!(flags & XDF_IGNORE_CASE) || ((ch1 | ch2) & 0x80))\n+\t\treturn 0;\n+\tif (isupper(ch1))\n+\t\tch1 = tolower(ch1);\n+\tif (isupper(ch2))\n+\t\tch2 = tolower(ch2);\n+\treturn (ch1 == ch2);\n+}\n+\n int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)\n {\n \tint i1, i2;\n@@ -192,7 +205,7 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)\n \tif (flags & XDF_IGNORE_WHITESPACE) {\n \t\tgoto skip_ws;\n \t\twhile (i1 < s1 && i2 < s2) {\n-\t\t\tif (l1[i1++] != l2[i2++])\n+\t\t\tif (!match_a_byte(l1[i1++], l2[i2++], flags))\n \t\t\t\treturn 0;\n \t\tskip_ws:\n \t\t\twhile (i1 < s1 && XDL_ISSPACE(l1[i1]))\n@@ -210,15 +223,28 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)\n \t\t\t\t\ti2++;\n \t\t\t\tcontinue;\n \t\t\t}\n-\t\t\tif (l1[i1++] != l2[i2++])\n+\t\t\tif (!match_a_byte(l1[i1++], l2[i2++], flags))\n \t\t\t\treturn 0;\n \t\t}\n-\t} else if (flags & XDF_IGNORE_WHITESPACE_AT_EOL) {\n-\t\twhile (i1 < s1 && i2 < s2 && l1[i1++] == l2[i2++])\n+\t} else {\n+\t\t/*\n+\t\t * Either XDF_IGNORE_WHITESPACE_AT_EOL is set, or\n+\t\t * no whitespace is ignored, but INEXACT_MATCH is\n+\t\t * in effect for other reasons.\n+\t\t */\n+\t\twhile (i1 < s1 && i2 < s2 &&\n+\t\t       match_a_byte(l1[i1++], l2[i2++], flags))\n \t\t\t; /* keep going */\n \t}\n \n \t/*\n+\t * If we are not ignoring any whitespace, we must have consumed\n+\t * everything for the lines to match.\n+\t */\n+\tif (!(flags & XDF_WHITESPACE_FLAGS))\n+\t\treturn i1 == s1 && i2 == s2;\n+\n+\t/*\n \t * After running out of one side, the remaining side must have\n \t * nothing but whitespace for the lines to match.  Note that\n \t * ignore-whitespace-at-eol case may break out of the loop\n@@ -238,6 +264,14 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)\n \treturn 1;\n }\n \n+static inline unsigned long hash_a_byte(const char ch_, long flags)\n+{\n+\tunsigned long ch = ch_ & 0xFF;\n+\tif ((flags & XDF_IGNORE_CASE) && !(ch & 0x80) && isupper(ch))\n+\t\tch = tolower(ch);\n+\treturn ch;\n+}\n+\n static unsigned long xdl_hash_record_with_whitespace(char const **data,\n \t\tchar const *top, long flags) {\n \tunsigned long ha = 5381;\n@@ -256,20 +290,20 @@ static unsigned long xdl_hash_record_with_whitespace(char const **data,\n \t\t\telse if (flags & XDF_IGNORE_WHITESPACE_CHANGE\n \t\t\t\t && !at_eol) {\n \t\t\t\tha += (ha << 5);\n-\t\t\t\tha ^= (unsigned long) ' ';\n+\t\t\t\tha ^= hash_a_byte(' ', flags);\n \t\t\t}\n \t\t\telse if (flags & XDF_IGNORE_WHITESPACE_AT_EOL\n \t\t\t\t && !at_eol) {\n \t\t\t\twhile (ptr2 != ptr + 1) {\n \t\t\t\t\tha += (ha << 5);\n-\t\t\t\t\tha ^= (unsigned long) *ptr2;\n+\t\t\t\t\tha ^= hash_a_byte(*ptr2, flags);\n \t\t\t\t\tptr2++;\n \t\t\t\t}\n \t\t\t}\n \t\t\tcontinue;\n \t\t}\n \t\tha += (ha << 5);\n-\t\tha ^= (unsigned long) *ptr;\n+\t\tha ^= hash_a_byte(*ptr, flags);\n \t}\n \t*data = ptr < top ? ptr + 1: ptr;\n \n@@ -286,7 +320,7 @@ unsigned long xdl_hash_record(char const **data, char const *top, long flags) {\n \n \tfor (; ptr < top && *ptr != '\\n'; ptr++) {\n \t\tha += (ha << 5);\n-\t\tha ^= (unsigned long) *ptr;\n+\t\tha ^= hash_a_byte(*ptr, flags);\n \t}\n \t*data = ptr < top ? ptr + 1: ptr;\n \n-- \n1.7.9.1.265.g25f75\n"},{"id":"184961","messageId":"1329704188-9955-6-git-send-email-gitster@pobox.com","threadId":"29670","inReplyTo":"1329704188-9955-1-git-send-email-gitster@pobox.com","subject":"[PATCH 5/5] diff: --ignore-case","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-20T02:16:28Z","receivedAt":"2012-02-20T02:16:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Teach the front-end to flip XDF_IGNORE_CASE bit with the options GNU diff\nuses.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/diff-options.txt |    4 ++++\n diff.c                         |    2 ++\n t/lib-diff-alternative.sh      |   45 ++++++++++++++++++++++++++++++++++++++--\n t/t4033-diff-patience.sh       |    6 ++++++\n t/t4050-diff-histogram.sh      |    2 ++\n 5 files changed, 57 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt\nindex 9f7cba2..791e07f 100644\n--- a/Documentation/diff-options.txt\n+++ b/Documentation/diff-options.txt\n@@ -404,6 +404,10 @@ endif::git-format-patch[]\n \tdifferences even if one line has whitespace where the other\n \tline has none.\n \n+--ignore-case::\n+\tIgnore changes in case only; only ASCII alphabet is supported for\n+\tnow.\n+\n --inter-hunk-context=<lines>::\n \tShow the context between diff hunks, up to the specified number\n \tof lines, thereby fusing hunks that are close to each other.\ndiff --git a/diff.c b/diff.c\nindex 87b2ec1..d7604b7 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -3399,6 +3399,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)\n \t\tDIFF_XDL_SET(options, IGNORE_WHITESPACE_CHANGE);\n \telse if (!strcmp(arg, \"--ignore-space-at-eol\"))\n \t\tDIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL);\n+\telse if (!strcmp(arg, \"--ignore-case\"))\n+\t\tDIFF_XDL_SET(options, IGNORE_CASE);\n \telse if (!strcmp(arg, \"--patience\"))\n \t\toptions->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);\n \telse if (!strcmp(arg, \"--histogram\"))\ndiff --git a/t/lib-diff-alternative.sh b/t/lib-diff-alternative.sh\nindex 75ffd91..45c665e 100644\n--- a/t/lib-diff-alternative.sh\n+++ b/t/lib-diff-alternative.sh\n@@ -104,8 +104,9 @@ EOF\n \n \tSTRATEGY=$1\n \n+\tcmd='git diff --no-index'\n \ttest_expect_success \"$STRATEGY diff\" '\n-\t\ttest_must_fail git diff --no-index \"--$STRATEGY\" file1 file2 > output &&\n+\t\ttest_must_fail $cmd ${STRATEGY:+\"--$STRATEGY\"} file1 file2 >output &&\n \t\ttest_cmp expect output\n \t'\n \n@@ -157,9 +158,49 @@ EOF\n \n \tSTRATEGY=$1\n \n+\tcmd='git diff --no-index'\n \ttest_expect_success 'completely different files' '\n-\t\ttest_must_fail git diff --no-index \"--$STRATEGY\" uniq1 uniq2 > output &&\n+\n+\t\ttest_must_fail $cmd  ${STRATEGY:+\"--$STRATEGY\"} uniq1 uniq2 >output &&\n \t\ttest_cmp expect output\n \t'\n }\n \n+test_diff_ignore () {\n+\n+\tSTRATEGY=$1\n+\n+\techo \"A quick brown fox\" >test.0\n+\techo \"A  quick brown fox\" >test-b\n+\techo \" A quick brownfox\" >test-w\n+\techo \"A quick brown fox \" >test--ignore-space-at-eol\n+\techo \"A Quick Brown Fox\" >test--ignore-case\n+\techo \"A Quick  Brown Fox\" >test--ignore-case-b\n+\techo \"A quick brown fox jumps\" >test\n+\tcases=\"-b -w --ignore-space-at-eol --ignore-case\"\n+\n+\tif test -z \"$STRATEGY\"\n+\tthen\n+\t\tlabel=baseline\n+\telse\n+\t\tlabel=$STRATEGY\n+\tfi\n+\n+\tcmd=\"git diff --no-index ${STRATEGY:+--$STRATEGY}\"\n+\n+\ttest_expect_success \"$label diff\" '\n+\t\ttest_must_fail $cmd test.0 test\n+\t'\n+\tfor case in $cases\n+\tdo\n+\t\ttest_expect_success \"$label diff $case\" '\n+\t\t\t$cmd $case test.0 test$case &&\n+\t\t\ttest_must_fail $cmd test.0 test\n+\t\t'\n+\tdone\n+\n+\ttest_expect_success \"$label diff -b --ignore-case\" '\n+\t\t$cmd -b --ignore-case test.0 test--ignore-case-b\n+\t'\n+\n+}\ndiff --git a/t/t4033-diff-patience.sh b/t/t4033-diff-patience.sh\nindex 3c9932e..c7f8c6c 100755\n--- a/t/t4033-diff-patience.sh\n+++ b/t/t4033-diff-patience.sh\n@@ -5,8 +5,14 @@ test_description='patience diff algorithm'\n . ./test-lib.sh\n . \"$TEST_DIRECTORY\"/lib-diff-alternative.sh\n \n+# baseline\n+test_diff_unique \"\"\n+test_diff_ignore \"\"\n+\n test_diff_frobnitz \"patience\"\n \n test_diff_unique \"patience\"\n \n+test_diff_ignore \"patience\"\n+\n test_done\ndiff --git a/t/t4050-diff-histogram.sh b/t/t4050-diff-histogram.sh\nindex fd3e86a..98c6686 100755\n--- a/t/t4050-diff-histogram.sh\n+++ b/t/t4050-diff-histogram.sh\n@@ -9,4 +9,6 @@ test_diff_frobnitz \"histogram\"\n \n test_diff_unique \"histogram\"\n \n+test_diff_ignore \"histogram\"\n+\n test_done\n-- \n1.7.9.1.265.g25f75\n"},{"id":"184969","messageId":"7vzkcelzw9.fsf@alter.siamese.dyndns.org","threadId":"29670","inReplyTo":"1329704188-9955-1-git-send-email-gitster@pobox.com","subject":"[PATCH 6/5] diff -i","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-20T07:36:38Z","receivedAt":"2012-02-20T07:36:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The previous patch to teach \"--ignore-case\" option to our \"diff\" machinery\ndeliberately omitted a short-and-sweet \"-i\" that GNU diff uses to ask for\n\"--ignore-case\".  This is because our diff machinery are often used by and\nshares the command line options with the commands in the \"git log\" family,\nwhere the short option already means something entirely different. Namely,\nit instructs to use case-insensitive match when looking for commits that\nmatch information that appear in the commit object itself, e.g. --author\nand --grep.\n\nTweak the option parser so that \"-i\" means both, so that\n\n\t$ git log --grep=frotz -i -p\n\nfirst picks commits that have string \"frotz\" in any combination of cases,\nand then shows patches that ignore case-only changes for the chosen\ncommits, while \"--ignore-case\" and \"--regexp-ignore-case\" can be used to\nmean only one, i.e.\n\n\t$ git log --grep=frotz --regexp-ignore-case -p\n\nwould pick the same set of commits, but the patches shown by it does not\nignore case-only changes while\n\n\t$ git log --grep=frotz --ignore-case -p\n\nwould pick commits that has \"frotz\" in all lowercase, but shows patches\nthat ignore case-only changes for the chosen commits.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/diff-options.txt |    1 +\n diff.c                         |    2 +-\n revision.c                     |    6 +++++-\n t/lib-diff-alternative.sh      |    3 ++-\n 4 files changed, 9 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt\nindex 791e07f..9ed78c9 100644\n--- a/Documentation/diff-options.txt\n+++ b/Documentation/diff-options.txt\n@@ -404,6 +404,7 @@ endif::git-format-patch[]\n \tdifferences even if one line has whitespace where the other\n \tline has none.\n \n+-i::\n --ignore-case::\n \tIgnore changes in case only; only ASCII alphabet is supported for\n \tnow.\ndiff --git a/diff.c b/diff.c\nindex d7604b7..9d1584e 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -3399,7 +3399,7 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)\n \t\tDIFF_XDL_SET(options, IGNORE_WHITESPACE_CHANGE);\n \telse if (!strcmp(arg, \"--ignore-space-at-eol\"))\n \t\tDIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL);\n-\telse if (!strcmp(arg, \"--ignore-case\"))\n+\telse if (!strcmp(arg, \"--ignore-case\") || !strcmp(arg, \"-i\"))\n \t\tDIFF_XDL_SET(options, IGNORE_CASE);\n \telse if (!strcmp(arg, \"--patience\"))\n \t\toptions->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);\ndiff --git a/revision.c b/revision.c\nindex 8764dde..f1a1354 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -13,6 +13,7 @@\n #include \"decorate.h\"\n #include \"log-tree.h\"\n #include \"string-list.h\"\n+#include \"xdiff-interface.h\"\n \n volatile show_early_output_fn_t show_early_output;\n \n@@ -1557,7 +1558,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\treturn argcount;\n \t} else if (!strcmp(arg, \"--extended-regexp\") || !strcmp(arg, \"-E\")) {\n \t\trevs->grep_filter.regflags |= REG_EXTENDED;\n-\t} else if (!strcmp(arg, \"--regexp-ignore-case\") || !strcmp(arg, \"-i\")) {\n+\t} else if (!strcmp(arg, \"-i\")) {\n+\t\tDIFF_XDL_SET(&revs->diffopt, IGNORE_CASE);\n+\t\trevs->grep_filter.regflags |= REG_ICASE;\n+\t} else if (!strcmp(arg, \"--regexp-ignore-case\")) {\n \t\trevs->grep_filter.regflags |= REG_ICASE;\n \t} else if (!strcmp(arg, \"--fixed-strings\") || !strcmp(arg, \"-F\")) {\n \t\trevs->grep_filter.fixed = 1;\ndiff --git a/t/lib-diff-alternative.sh b/t/lib-diff-alternative.sh\nindex 45c665e..81609f8 100644\n--- a/t/lib-diff-alternative.sh\n+++ b/t/lib-diff-alternative.sh\n@@ -175,9 +175,10 @@ test_diff_ignore () {\n \techo \" A quick brownfox\" >test-w\n \techo \"A quick brown fox \" >test--ignore-space-at-eol\n \techo \"A Quick Brown Fox\" >test--ignore-case\n+\techo \"A Quick Brown FoX\" >test-i\n \techo \"A Quick  Brown Fox\" >test--ignore-case-b\n \techo \"A quick brown fox jumps\" >test\n-\tcases=\"-b -w --ignore-space-at-eol --ignore-case\"\n+\tcases=\"-b -w --ignore-space-at-eol --ignore-case -i\"\n \n \tif test -z \"$STRATEGY\"\n \tthen\n"},{"id":"184976","messageId":"4F420749.9010206@kdbg.org","threadId":"29670","inReplyTo":"1329704188-9955-1-git-send-email-gitster@pobox.com","subject":"Re: [PATCH 0/5] diff --ignore-case","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2012-02-20T08:41:45Z","receivedAt":"2012-02-20T08:41:45Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 20.02.2012 03:16, schrieb Junio C Hamano:\n> This teaches our \"diff\" machinery to optionally consider lines that are\n> different only in upper/lower-cases to be equivalent.\n\nWhen would I want to use --ignore-case? And how useful is it that it\ndoes not obey the current locale, as in your implementation?\n\n-- Hannes\n"},{"id":"184978","messageId":"7v8vjxnayn.fsf@alter.siamese.dyndns.org","threadId":"29670","inReplyTo":"4F420749.9010206@kdbg.org","subject":"Re: [PATCH 0/5] diff --ignore-case","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-20T08:52:16Z","receivedAt":"2012-02-20T08:52:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j6t@kdbg.org> writes:\n\n> Am 20.02.2012 03:16, schrieb Junio C Hamano:\n>> This teaches our \"diff\" machinery to optionally consider lines that are\n>> different only in upper/lower-cases to be equivalent.\n>\n> When would I want to use --ignore-case?\n\nI wouldn't myself; it was just I saw somebody asked if -G can be used to\ndo case insensitive and then I realized we do not even support such in the\ndiff machinery to begin with, but now this opens a way to do so by copying\nthe xdl options when the pickaxe-grep codepath runs a subdiff.\n\nYou can update the hash and recmatch to be locale-aware, which would be an\ninternal update to xdiff/ directory that is independent of the rest of the\nseries, and/or the change to plug the machinery to -G.\n"},{"id":"184990","messageId":"871upp4n15.fsf@thomas.inf.ethz.ch","threadId":"29670","inReplyTo":"7v8vjxnayn.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 0/5] diff --ignore-case","fromName":"Thomas Rast","fromEmail":"trast@inf.ethz.ch","sentAt":"2012-02-20T14:06:30Z","receivedAt":"2012-02-20T14:06:30Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Johannes Sixt <j6t@kdbg.org> writes:\n>\n>> Am 20.02.2012 03:16, schrieb Junio C Hamano:\n>>> This teaches our \"diff\" machinery to optionally consider lines that are\n>>> different only in upper/lower-cases to be equivalent.\n>>\n>> When would I want to use --ignore-case?\n>\n> I wouldn't myself; it was just I saw somebody asked if -G can be used to\n> do case insensitive and then I realized we do not even support such in the\n> diff machinery to begin with, but now this opens a way to do so by copying\n> the xdl options when the pickaxe-grep codepath runs a subdiff.\n\nI wonder which one of us misunderstood the original request ;-)\n\nIt was\n\n} Is there any way to run diff -G with a case insensitivity flag?\n\nand I took that to mean \"I want to find addition/removal of a string\nlike -G does, but I don't know how it was capitalized\".  OTOH you\ninterpreted it as \"I want to run -G but ignore changes in case while\ndiffing\".\n\nSo maybe Chris can comment on what was intended?\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"185011","messageId":"7vvcn1l21d.fsf@alter.siamese.dyndns.org","threadId":"29670","inReplyTo":"871upp4n15.fsf@thomas.inf.ethz.ch","subject":"Re: [PATCH 0/5] diff --ignore-case","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-20T19:47:58Z","receivedAt":"2012-02-20T19:47:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Rast <trast@inf.ethz.ch> writes:\n\n> I wonder which one of us misunderstood the original request ;-)\n\nHeh, I did ;-)\n\n> It was\n>\n> } Is there any way to run diff -G with a case insensitivity flag?\n>\n> and I took that to mean \"I want to find addition/removal of a string\n> like -G does, but I don't know how it was capitalized\".\n\nI think it is just the matter of checking REG_ICASE that may be set in\nrevs->grep_filter.regflags, and propagating it down to the regcomp at the\nbeginning of diffcore_pickaxe_grep().\n\nWant to try and see how well it works?\n"},{"id":"185040","messageId":"CAJ6vYjfrRxh9A6Tvp=9y87WkjGapj4vQE-6++bSgC+rT5sDBJg@mail.gmail.com","threadId":"29670","inReplyTo":"7vvcn1l21d.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 0/5] diff --ignore-case","fromName":"Chris Leong","fromEmail":"walkraft@gmail.com","sentAt":"2012-02-20T22:10:37Z","receivedAt":"2012-02-20T22:10:37Z","isPatch":true,"sender":{"key":"walkraft@gmail.com","avatar":"https://gravatar.com/avatar/b652eca2f2121a90d994b41963e2b6bd9546a39e26dba0f06c8ccb478fceef3d?d=mp&s=160"},"body":"It was about not worrying about the exact case of matches.\n\nOn Tue, Feb 21, 2012 at 6:47 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Want to try and see how well it works?\n>\n"},{"id":"185062","messageId":"7vwr7gh83t.fsf_-_@alter.siamese.dyndns.org","threadId":"29670","inReplyTo":"7vvcn1l21d.fsf@alter.siamese.dyndns.org","subject":"Re* [PATCH 0/5] diff --ignore-case","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-21T09:02:46Z","receivedAt":"2012-02-21T09:02:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Thomas Rast <trast@inf.ethz.ch> writes:\n>\n>> I wonder which one of us misunderstood the original request ;-)\n>\n> Heh, I did ;-)\n>\n>> It was\n>>\n>> } Is there any way to run diff -G with a case insensitivity flag?\n>>\n>> and I took that to mean \"I want to find addition/removal of a string\n>> like -G does, but I don't know how it was capitalized\".\n>\n> I think it is just the matter of checking REG_ICASE that may be set in\n> revs->grep_filter.regflags, and propagating it down to the regcomp at the\n> beginning of diffcore_pickaxe_grep().\n>\n> Want to try and see how well it works?\n\nThe gist of the patch should look like this.\n\nEven though I haven't done anything more than just to compile and run \"git\nlog -p -i -G search 233054d\", it looks obviously correct ;-)\n\nNote that this does not depend on any of the \"diff --ignore-case\" topic,\nand it may conflict with [PATCH 6/5].  Among the two \"else if\" that flips\nthe REG_ICASE in revision.c, it needs to be decided if only one of them,\nor both of them should set the new option. I haven't thought things through\nto decide which.\n\n diff.h             |    1 +\n diffcore-pickaxe.c |    6 +++++-\n revision.c         |    1 +\n 3 files changed, 7 insertions(+), 1 deletion(-)\n\ndiff --git a/diff.h b/diff.h\nindex 7af5f1e..182cb0e 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -82,6 +82,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)\n #define DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG (1 << 27)\n #define DIFF_OPT_DIRSTAT_BY_LINE     (1 << 28)\n #define DIFF_OPT_FUNCCONTEXT         (1 << 29)\n+#define DIFF_OPT_PICKAXE_IGNORE_CASE (1 << 30)\n \n #define DIFF_OPT_TST(opts, flag)    ((opts)->flags & DIFF_OPT_##flag)\n #define DIFF_OPT_SET(opts, flag)    ((opts)->flags |= DIFF_OPT_##flag)\ndiff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c\nindex 380a837..8ffb741 100644\n--- a/diffcore-pickaxe.c\n+++ b/diffcore-pickaxe.c\n@@ -138,8 +138,12 @@ static void diffcore_pickaxe_grep(struct diff_options *o)\n {\n \tint err;\n \tregex_t regex;\n+\tint cflags = REG_EXTENDED | REG_NEWLINE;\n \n-\terr = regcomp(&regex, o->pickaxe, REG_EXTENDED | REG_NEWLINE);\n+\tif (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE))\n+\t\tcflags |= REG_ICASE;\n+\n+\terr = regcomp(&regex, o->pickaxe, cflags);\n \tif (err) {\n \t\tchar errbuf[1024];\n \t\tregerror(err, &regex, errbuf, 1024);\ndiff --git a/revision.c b/revision.c\nindex 819ff01..b3554ed 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1582,6 +1582,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->grep_filter.regflags |= REG_EXTENDED;\n \t} else if (!strcmp(arg, \"--regexp-ignore-case\") || !strcmp(arg, \"-i\")) {\n \t\trevs->grep_filter.regflags |= REG_ICASE;\n+\t\tDIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);\n \t} else if (!strcmp(arg, \"--fixed-strings\") || !strcmp(arg, \"-F\")) {\n \t\trevs->grep_filter.fixed = 1;\n \t} else if (!strcmp(arg, \"--all-match\")) {\n"},{"id":"185184","messageId":"m3ehtmeo7c.fsf@localhost.localdomain","threadId":"29670","inReplyTo":"1329704188-9955-5-git-send-email-gitster@pobox.com","subject":"Re: [PATCH 4/5] xdiff: introduce XDF_IGNORE_CASE","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2012-02-22T18:07:56Z","receivedAt":"2012-02-22T18:07:56Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Teach the hash function and per-line comparison logic to compare lines\n> while ignoring the differences in case.  It is not an ignore-whitespace\n> option but still needs to trigger the inexact match logic, and that is\n> why the previous step introduced XDF_INEXACT_MATCH mask.\n\nNb. how it compares with ignore case in filesystem paths?\n \n> Assign the 7th bit for this option, and move the bits to select diff\n> algorithms out of the way in order to leave room for a few bits to add\n> more variants of ignore-whitespace, such as --ignore-tab-expansion, if\n> somebody else is inclined to do so later.\n\nOr do a proper Unicode sorting / collation algorithm, with different\nlevels \n\n  (4.3 Form a sort key for each string, UTS #10.):\n\n     Level 1: alphabetic ordering\n     Level 2: diacritic ordering\n     Level 3: case ordering\n     Level 4: tie-breaking (e.g. in the case when variable is 'shifted')\n\n> We would still need to teach the front-end to flip this bit, for this\n> change to be any useful.\n> \n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n\n> +static inline int match_a_byte(char ch1, char ch2, long flags)\n> +{\n> +\tif (ch1 == ch2)\n> +\t\treturn 1;\n> +\tif (!(flags & XDF_IGNORE_CASE) || ((ch1 | ch2) & 0x80))\n> +\t\treturn 0;\n> +\tif (isupper(ch1))\n> +\t\tch1 = tolower(ch1);\n> +\tif (isupper(ch2))\n> +\t\tch2 = tolower(ch2);\n> +\treturn (ch1 == ch2);\n> +}\n\n<del>\nWouldn't a better solution be a collate algorithm rather than changing\na sorting function?  Or is it a performance hack on typical body of\ntext under version control (mainly lowercase)?\n</del>\n\n\"(libc.info)Collation Fuctions\" says:\n\n     The functions `strcoll' and `wcscoll' perform this translation\n  implicitly, in order to do one comparison.  By contrast, `strxfrm' and\n  `wcsxfrm' perform the mapping explicitly.  If you are making multiple\n  comparisons using the same string or set of strings, it is likely to be\n  more efficient to use `strxfrm' or `wcsxfrm' to transform all the\n  strings just once, and subsequently compare the transformed strings\n  with `strcmp' or `wcscmp'.\n\nThe function match_a_byte (memcoll?) defined here is similar to strcoll;\ndo we compare single line with more than one other line?\n\n> +static inline unsigned long hash_a_byte(const char ch_, long flags)\n> +{\n> +\tunsigned long ch = ch_ & 0xFF;\n> +\tif ((flags & XDF_IGNORE_CASE) && !(ch & 0x80) && isupper(ch))\n> +\t\tch = tolower(ch);\n> +\treturn ch;\n> +}\n> +\n\nHmmm... hash_a_byte (memxfrm?) is similar to strxfrm, so you do use\none or the other...\n\n-- \nJakub Narebski\n"}]}