{"thread":{"id":"38147","subject":"fast-import should not care about core.ignorecase","startedAt":"2014-12-09T00:12:11Z","lastAt":"2015-04-24T09:42:14Z","messageCount":12,"participants":["Mike Hommey","Joshua Jensen","Jonathan Nieder","Junio C Hamano","Torsten Bögershausen","Eric Sunshine","Luke Diamand"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"253391","messageId":"20141209001211.GA13386@glandium.org","threadId":"38147","inReplyTo":null,"subject":"fast-import should not care about core.ignorecase","fromName":"Mike Hommey","fromEmail":"mh@glandium.org","sentAt":"2014-12-09T00:12:11Z","receivedAt":"2014-12-09T00:12:11Z","isPatch":false,"sender":{"key":"mh@glandium.org","avatar":"https://avatars.githubusercontent.com/u/1038527?v=4"},"body":"Hi,\n\nAs you now know, I'm working on a mercurial remote helper for git. As\nsuch, it uses fast-import.\n\nIn the mercurial history of mozilla-central, there have been various\nrenames of files with only case changes, and it so happens that my\nremote helper blows things up on case insensitive file systems. The\nreason is git clone probing the file system and setting core.ignorecase\nappropriately.\n\nWhile it makes sense for checkouts and local commits, it doesn't make\nsense to me that using git fast-import with the same import script would\nhave a different behavior depending on whether the file system is\ncase-sensitive or not.\n\nReduced testcase:\n\n$ git init\n$ git fast-import <<EOF\nblob\nmark :1\ndata 2\na\n\ncommit refs/FOO\ncommitter <foo@foo> 0 +0000\ndata 0\n\nM 644 :1 a\n\ncommit refs/FOO\ncommitter <foo@foo> 0 +0000\ndata 0\n\nR a A\nEOF\n\nThis is what you get on a case sensitive FS:\n\n$ git log refs/FOO -p -M\ncommit be1497308f30f883343eefd0da7ddf1e747133f8\nAuthor:  <foo@foo>\nDate:   Thu Jan 1 00:00:00 1970 +0000\n\ndiff --git a/a b/A\nsimilarity index 100%\nrename from a\nrename to A\n\ncommit 8d37f958cfc0702c577b918c86769a902fe109f8\nAuthor:  <foo@foo>\nDate:   Thu Jan 1 00:00:00 1970 +0000\n\ndiff --git a/a b/a\nnew file mode 100644\nindex 0000000..7898192\n--- /dev/null\n+++ b/a\n@@ -0,0 +1 @@\n+a\n\nThis is what you get on a case insensitive FS:\n\n$ git log refs/FOO -p -M\ncommit 208c0c4cf58cd54512301e0de33ccb8a78d6b226\nAuthor:  <foo@foo>\nDate:   Thu Jan 1 00:00:00 1970 +0000\n\ncommit 8d37f958cfc0702c577b918c86769a902fe109f8\nAuthor:  <foo@foo>\nDate:   Thu Jan 1 00:00:00 1970 +0000\n\ndiff --git a/a b/a\nnew file mode 100644\nindex 0000000..7898192\n--- /dev/null\n+++ b/a\n@@ -0,0 +1 @@\n+a\n\nNote, this applies equally to filerename commands or filedelete +\nfilemodify combinations.\n\nMike\n"},{"id":"253392","messageId":"20141209002245.GA14103@glandium.org","threadId":"38147","inReplyTo":"20141209001211.GA13386@glandium.org","subject":"Re: fast-import should not care about core.ignorecase","fromName":"Mike Hommey","fromEmail":"mh@glandium.org","sentAt":"2014-12-09T00:22:45Z","receivedAt":"2014-12-09T00:22:45Z","isPatch":false,"sender":{"key":"mh@glandium.org","avatar":"https://avatars.githubusercontent.com/u/1038527?v=4"},"body":"On Tue, Dec 09, 2014 at 09:12:11AM +0900, Mike Hommey wrote:\n> Hi,\n> \n> As you now know, I'm working on a mercurial remote helper for git. As\n> such, it uses fast-import.\n> \n> In the mercurial history of mozilla-central, there have been various\n> renames of files with only case changes, and it so happens that my\n> remote helper blows things up on case insensitive file systems. The\n> reason is git clone probing the file system and setting core.ignorecase\n> appropriately.\n> \n> While it makes sense for checkouts and local commits, it doesn't make\n> sense to me that using git fast-import with the same import script would\n> have a different behavior depending on whether the file system is\n> case-sensitive or not.\n\nHeh, I just found this thread:\nhttp://marc.info/?t=139134708700001&r=1&w=2\n\nIt doesn't seem to have led to something actually being committed,\nthough.\n\nMike\n"},{"id":"253393","messageId":"54864B3D.6040503@workspacewhiz.com","threadId":"38147","inReplyTo":"20141209001211.GA13386@glandium.org","subject":"Re: fast-import should not care about core.ignorecase","fromName":"Joshua Jensen","fromEmail":"jjensen@workspacewhiz.com","sentAt":"2014-12-09T01:07:09Z","receivedAt":"2014-12-09T01:07:09Z","isPatch":false,"sender":{"key":"jjensen@workspacewhiz.com","avatar":"https://avatars.githubusercontent.com/u/111687?v=4"},"body":"Mike Hommey wrote on 12/8/2014 5:12 PM:\n> While it makes sense for checkouts and local commits, it doesn't make\n> sense to me that using git fast-import with the same import script would\n> have a different behavior depending on whether the file system is\n> case-sensitive or not.\nI have used fast-import with Perforce inputs.  When you run a Windows \nPerforce server, filenames can be submitted with ANY case, but given the \ncase insensitive nature of the file system, a synced Perforce file will \nend up using whatever case happens to be on the file system at that point.\n\nThat may not be clear, so here goes:\n\nRevision 1: abc/DEF/ghi/FILE.dat\n\nRevision 2: ABC/def/GHI/file.dat\n\n^^ Yes, Perforce stores the filename internally in that manner and does \nnot fold the case.\n\nIf you happen to sync Revision 2 on an empty directory tree, you'll get \nABC/def/GHI/file.dat.  If you then sync Revision 1, the filename case \nremains ABC/def/GHI/file.dat.\n\nLikewise, if you happen to sync Revision 1 into an empty directory tree, \nyou'll get abc/DEF/ghi/FILE.dat.  If you then sync Revision 2, the \nfilename case remains as abc/DEF/ghi/FILE.dat.\n\nI was the one who originally submitted the patch for this some 4 years \nago.  It was commit 50906e04e8f48215b0b09841686709b92a2ab2e4. 'git \nfast-import' with core.ignorecase=true will fold the case of the \nfilename specified in Revision 2 to the case currently stored in the Git \nrepository from Revision 1.\n\nIf it does not do this, then Git internally stores FILE.dat and \nfile.dat, and bad things happen on case-insensitive file systems.\n\n(Further, there are still a few paths into Git where \ncore.ignorecase=true does not fold the case of the filename, and this \ncan cause 'repository corruptions' on case-insensitive file systems.  \nOne such place is in 'git update-index' directly used by 'git gui'.  I \nreally need to get this submitted, as we've been beating on it for a \nlong time now, but here is the partial patch for informational purposes \nonly.\n\nI think it has been discussed before, but maybe Git needs a \ncore.casefold in addition to core.ignorecase.)\n\n-Josh\n\n---------------------------- builtin/update-index.c \n----------------------------\nindex aaa6f78..4cfedc1 100644\n@@ -99,6 +99,7 @@ static int add_one_path(const struct cache_entry *old, \nconst char *path, int len\n      memcpy(ce->name, path, len);\n      ce->ce_flags = create_ce_flags(0);\n      ce->ce_namelen = len;\n+    fold_ce_name_case(&the_index, ce);\n      fill_stat_cache_info(ce, st);\n      ce->ce_mode = ce_mode_from_stat(old, st->st_mode);\n\n@@ -234,6 +235,7 @@ static int add_cacheinfo(unsigned int mode, const \nunsigned char *sha1,\n      memcpy(ce->name, path, len);\n      ce->ce_flags = create_ce_flags(stage);\n      ce->ce_namelen = len;\n+    fold_ce_name_case(&the_index, ce);\n      ce->ce_mode = create_ce_mode(mode);\n      if (assume_unchanged)\n          ce->ce_flags |= CE_VALID;\n"},{"id":"253394","messageId":"20141209013138.GU16345@google.com","threadId":"38147","inReplyTo":"54864B3D.6040503@workspacewhiz.com","subject":"Re: fast-import should not care about core.ignorecase","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2014-12-09T01:31:38Z","receivedAt":"2014-12-09T01:31:38Z","isPatch":false,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Joshua Jensen wrote:\n\n> I think it has been discussed before, but maybe Git needs a\n> core.casefold in addition to core.ignorecase.)\n\nWould it work for --casefold to be a commandline flag to fast-import,\ninstead of a global option affecting multiple Git commands?\n\nCurious,\nJonathan\n"},{"id":"253396","messageId":"54866A94.2040305@workspacewhiz.com","threadId":"38147","inReplyTo":"20141209013138.GU16345@google.com","subject":"Re: fast-import should not care about core.ignorecase","fromName":"Joshua Jensen","fromEmail":"jjensen@workspacewhiz.com","sentAt":"2014-12-09T03:20:52Z","receivedAt":"2014-12-09T03:20:52Z","isPatch":false,"sender":{"key":"jjensen@workspacewhiz.com","avatar":"https://avatars.githubusercontent.com/u/111687?v=4"},"body":"Jonathan Nieder wrote on 12/8/2014 6:31 PM:\n> Joshua Jensen wrote:\n>> I think it has been discussed before, but maybe Git needs a\n>> core.casefold in addition to core.ignorecase.)\n> Would it work for --casefold to be a commandline flag to fast-import,\n> instead of a global option affecting multiple Git commands?\nGiven that core.ignorecase=true means to fold filename case in quite a \nnumber of places within Git right now, I would expect the same behavior \nwithin a repository where fast-import is being run against \ncore.ignorecase=true.\n\nSo, I don't know what core.ignorecase should mean, but I'm pretty sure I \nknow what core.foldcase should mean.\n\nWould --casefold work?  Sure, but it would be a special case against the \nexisting core.ignorecase behavior that I don't think makes much sense.\n\nJosh\n"},{"id":"253443","messageId":"xmqqoarclgnr.fsf@gitster.dls.corp.google.com","threadId":"38147","inReplyTo":"54866A94.2040305@workspacewhiz.com","subject":"Re: fast-import should not care about core.ignorecase","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-12-09T20:19:52Z","receivedAt":"2014-12-09T20:19:52Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Joshua Jensen <jjensen@workspacewhiz.com> writes:\n\n> Jonathan Nieder wrote on 12/8/2014 6:31 PM:\n>> Joshua Jensen wrote:\n>>> I think it has been discussed before, but maybe Git needs a\n>>> core.casefold in addition to core.ignorecase.)\n>> Would it work for --casefold to be a commandline flag to fast-import,\n>> instead of a global option affecting multiple Git commands?\n> Given that core.ignorecase=true means to fold filename case in quite a\n> number of places within Git right now, I would expect the same\n> behavior within a repository where fast-import is being run against\n> core.ignorecase=true.\n>\n> So, I don't know what core.ignorecase should mean, but I'm pretty sure\n> I know what core.foldcase should mean.\n>\n> Would --casefold work?  Sure, but it would be a special case against\n> the existing core.ignorecase behavior that I don't think makes much\n> sense.\n\nI would recommend doing this:\n\n - Add file-scope static variable fast_import_casefold to fast-import.c\n\n - Patch fast-import.c where it calls strncmp_icase(a, b) to read\n\n    fast_import_casefold ? strcasecmp(a, b) : strcmp(a, b);\n\n - Initialize fast_import_casefold to the same value as ignore_case.\n\n - Add a new command line option \"--[no-]casefold\" to modify the\n   value of fast_import_casefold.\n\nOnce all of the above is in place, optionally do this:\n\n - Add fastImport.casefold configuration variable.  The\n   initialization logic for fast_import_casefold would then become:\n\n    1. If the configuration is set, use that value; otherwise\n    2. Use the same value as ignore_case.\n\n - Start warning when fast_import_casefold is set to true only\n   because ignore_case is set (i.e. no \"--[no-casefold]\" is given\n   from the command line or from the config), saying that this is\n   true for now only as a backward compatibility measure and in a\n   later version of Git we will flip the default _not_ to fold on\n   any system.\n\n - Wait a bit and then flip the default.\n"},{"id":"259559","messageId":"1429271526-31234-1-git-send-email-mh@glandium.org","threadId":"38147","inReplyTo":"xmqqoarclgnr.fsf@gitster.dls.corp.google.com","subject":"[PATCH] fast-import: add options to enable/disable case folding","fromName":"Mike Hommey","fromEmail":"mh@glandium.org","sentAt":"2015-04-17T11:52:06Z","receivedAt":"2015-04-17T11:52:06Z","isPatch":true,"sender":{"key":"mh@glandium.org","avatar":"https://avatars.githubusercontent.com/u/1038527?v=4"},"body":"Currently, fast-import does case folding depending on `core.ignorecase`.\n`core.ignorecase` depends on the file system where the working tree is.\nHowever, different kind of imports require different kinds of semantics,\nand they usually aren't tied with the file system, but with the data being\nimported.\n\nAdd command line options to enable or disable case folding. Also expose\nthem as features in the fast-import stream. Features instead of options,\nbecause a stream that needs case folding enabled or disabled won't work\nas expected if fast-import doesn't support the case folding options.\n---\n Documentation/git-fast-import.txt | 11 ++++++\n fast-import.c                     | 19 ++++++++--\n t/t9300-fast-import.sh            | 79 +++++++++++++++++++++++++++++++++++++++\n 3 files changed, 106 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\nindex 690fed3..22eba87 100644\n--- a/Documentation/git-fast-import.txt\n+++ b/Documentation/git-fast-import.txt\n@@ -50,6 +50,13 @@ OPTIONS\n \tmemory used by fast-import during this run.  Showing this output\n \tis currently the default, but can be disabled with \\--quiet.\n \n+--[no-]fold-case::\n+\tWhen files/directories with the same name but a different case\n+\tare detected, they are treated as the same (--fold-case) or as\n+\tbeing different (--no-fold-case). The default is --fold-case\n+\twhen `core.ignorecase` is set to `true`, and --no-fold-case when\n+\tit is `false`.\n+\n Options for Frontends\n ~~~~~~~~~~~~~~~~~~~~~\n \n@@ -1027,6 +1034,8 @@ date-format::\n export-marks::\n relative-marks::\n no-relative-marks::\n+fold-case::\n+no-fold-case::\n force::\n \tAct as though the corresponding command-line option with\n \ta leading '--' was passed on the command line\n@@ -1091,6 +1100,8 @@ not be passed as option:\n * import-marks\n * export-marks\n * cat-blob-fd\n+* fold-case\n+* no-fold-case\n * force\n \n `done`\ndiff --git a/fast-import.c b/fast-import.c\nindex 6378726..958f3da 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -371,10 +371,18 @@ static volatile sig_atomic_t checkpoint_requested;\n /* Where to write output of cat-blob commands */\n static int cat_blob_fd = STDOUT_FILENO;\n \n+/* Whether to enable case folding */\n+static int fold_case;\n+\n static void parse_argv(void);\n static void parse_cat_blob(const char *p);\n static void parse_ls(const char *p, struct branch *b);\n \n+static int strncmp_foldcase(const char *a, const char *b, size_t count)\n+{\n+\treturn fold_case ? strncasecmp(a, b, count) : strncmp(a, b, count);\n+}\n+\n static void write_branch_report(FILE *rpt, struct branch *b)\n {\n \tfprintf(rpt, \"%s:\\n\", b->name);\n@@ -1507,7 +1515,7 @@ static int tree_content_set(\n \tt = root->tree;\n \tfor (i = 0; i < t->entry_count; i++) {\n \t\te = t->entries[i];\n-\t\tif (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {\n+\t\tif (e->name->str_len == n && !strncmp_foldcase(p, e->name->str_dat, n)) {\n \t\t\tif (!*slash1) {\n \t\t\t\tif (!S_ISDIR(mode)\n \t\t\t\t\t\t&& e->versions[1].mode == mode\n@@ -1597,7 +1605,7 @@ static int tree_content_remove(\n \tt = root->tree;\n \tfor (i = 0; i < t->entry_count; i++) {\n \t\te = t->entries[i];\n-\t\tif (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {\n+\t\tif (e->name->str_len == n && !strncmp_foldcase(p, e->name->str_dat, n)) {\n \t\t\tif (*slash1 && !S_ISDIR(e->versions[1].mode))\n \t\t\t\t/*\n \t\t\t\t * If p names a file in some subdirectory, and a\n@@ -1664,7 +1672,7 @@ static int tree_content_get(\n \tt = root->tree;\n \tfor (i = 0; i < t->entry_count; i++) {\n \t\te = t->entries[i];\n-\t\tif (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {\n+\t\tif (e->name->str_len == n && !strncmp_foldcase(p, e->name->str_dat, n)) {\n \t\t\tif (!*slash1)\n \t\t\t\tgoto found_entry;\n \t\t\tif (!S_ISDIR(e->versions[1].mode))\n@@ -3246,6 +3254,10 @@ static int parse_one_feature(const char *feature, int from_stream)\n \t\trelative_marks_paths = 1;\n \t} else if (!strcmp(feature, \"no-relative-marks\")) {\n \t\trelative_marks_paths = 0;\n+\t} else if (!strcmp(feature, \"fold-case\")) {\n+\t\tfold_case = 1;\n+\t} else if (!strcmp(feature, \"no-fold-case\")) {\n+\t\tfold_case = 0;\n \t} else if (!strcmp(feature, \"done\")) {\n \t\trequire_explicit_termination = 1;\n \t} else if (!strcmp(feature, \"force\")) {\n@@ -3372,6 +3384,7 @@ int main(int argc, char **argv)\n \tavail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));\n \tmarks = pool_calloc(1, sizeof(struct mark_set));\n \n+\tfold_case = ignore_case;\n \tglobal_argc = argc;\n \tglobal_argv = argv;\n \ndiff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\nindex aac126f..7057c26 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -3088,4 +3088,83 @@ test_expect_success 'U: validate root delete result' '\n \tcompare_diff_raw expect actual\n '\n \n+cat >input <<INPUT_END\n+blob\n+mark :1\n+data 2\n+a\n+\n+commit refs/heads/V\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+data 0\n+\n+M 644 :1 a\n+\n+commit refs/heads/V\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+data 0\n+\n+R a A\n+INPUT_END\n+\n+test_expect_success 'V: default case folding with ignorecase=true' '\n+\tgit config core.ignorecase true &&\n+\tgit fast-import <input &&\n+\tgit ls-tree refs/heads/V >actual &&\n+\tgit update-ref -d refs/heads/V &&\n+\tcat >expected <<\\EOF &&\n+100644 blob 78981922613b2afb6025042ff6bd878ac1994e85\ta\n+EOF\n+\ttest_cmp expected actual'\n+\n+test_expect_success 'V: default case folding with ignorecase=false' '\n+\tgit config core.ignorecase false &&\n+\tgit fast-import <input &&\n+\tgit ls-tree refs/heads/V >actual &&\n+\tgit update-ref -d refs/heads/V &&\n+\tcat >expected <<\\EOF &&\n+100644 blob 78981922613b2afb6025042ff6bd878ac1994e85\tA\n+EOF\n+\ttest_cmp expected actual'\n+\n+test_expect_success 'V: forced case folding with ignorecase=true' '\n+\tgit config core.ignorecase true &&\n+\tgit fast-import --fold-case <input &&\n+\tgit ls-tree refs/heads/V >actual &&\n+\tgit update-ref -d refs/heads/V &&\n+\tcat >expected <<\\EOF &&\n+100644 blob 78981922613b2afb6025042ff6bd878ac1994e85\ta\n+EOF\n+\ttest_cmp expected actual'\n+\n+test_expect_success 'V: forced case folding with ignorecase=false' '\n+\tgit config core.ignorecase false &&\n+\tgit fast-import --fold-case <input &&\n+\tgit ls-tree refs/heads/V >actual &&\n+\tgit update-ref -d refs/heads/V &&\n+\tcat >expected <<\\EOF &&\n+100644 blob 78981922613b2afb6025042ff6bd878ac1994e85\ta\n+EOF\n+\ttest_cmp expected actual'\n+\n+test_expect_success 'V: forced no case folding with ignorecase=true' '\n+\tgit config core.ignorecase true &&\n+\tgit fast-import --no-fold-case <input &&\n+\tgit ls-tree refs/heads/V >actual &&\n+\tgit update-ref -d refs/heads/V &&\n+\tcat >expected <<\\EOF &&\n+100644 blob 78981922613b2afb6025042ff6bd878ac1994e85\tA\n+EOF\n+\ttest_cmp expected actual'\n+\n+test_expect_success 'V: forced no case folding with ignorecase=false' '\n+\tgit config core.ignorecase false &&\n+\tgit fast-import --no-fold-case <input &&\n+\tgit ls-tree refs/heads/V >actual &&\n+\tgit update-ref -d refs/heads/V &&\n+\tcat >expected <<\\EOF &&\n+100644 blob 78981922613b2afb6025042ff6bd878ac1994e85\tA\n+EOF\n+\ttest_cmp expected actual'\n+\n test_done\n-- \n2.3.5.1.g2355df5\n"},{"id":"259572","messageId":"55313B4B.3030106@web.de","threadId":"38147","inReplyTo":"1429271526-31234-1-git-send-email-mh@glandium.org","subject":"Re: [PATCH] fast-import: add options to enable/disable case folding","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2015-04-17T16:56:43Z","receivedAt":"2015-04-17T16:56:43Z","isPatch":true,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"\n\n\nOn 04/17/2015 01:52 PM, Mike Hommey wrote:\n> Currently, fast-import does case folding depending on `core.ignorecase`.\n> `core.ignorecase` depends on the file system where the working tree is.\n> However, different kind of imports require different kinds of semantics,\n> and they usually aren't tied with the file system, but with the data being\n> imported.\nGood that you take up this issue, thanks for the patch\nMore comments inline.\n> Add command line options to enable or disable case folding. Also expose\n> them as features in the fast-import stream. Features instead of options,\n> because a stream that needs case folding enabled or disabled won't work\n> as expected if fast-import doesn't support the case folding options.\n> ---\n>  Documentation/git-fast-import.txt | 11 ++++++\n>  fast-import.c                     | 19 ++++++++--\n>  t/t9300-fast-import.sh            | 79 +++++++++++++++++++++++++++++++++++++++\n>  3 files changed, 106 insertions(+), 3 deletions(-)\n>\n> diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\n> index 690fed3..22eba87 100644\n> --- a/Documentation/git-fast-import.txt\n> +++ b/Documentation/git-fast-import.txt\n> @@ -50,6 +50,13 @@ OPTIONS\n>  \tmemory used by fast-import during this run.  Showing this output\n>  \tis currently the default, but can be disabled with \\--quiet.\n>  \n> +--[no-]fold-case::\n> +\tWhen files/directories with the same name but a different case\n> +\tare detected, they are treated as the same (--fold-case) or as\n> +\tbeing different (--no-fold-case). The default is --fold-case\n> +\twhen `core.ignorecase` is set to `true`, and --no-fold-case when\n> +\tit is `false`.\n> +\nMost often the we use the term \"ignore-case\", could that be a better name ?\nOther opinions, pros/cons  ?\n\n>  Options for Frontends\n>  ~~~~~~~~~~~~~~~~~~~~~\n>  \n> @@ -1027,6 +1034,8 @@ date-format::\n>  export-marks::\n>  relative-marks::\n>  no-relative-marks::\n> +fold-case::\n> +no-fold-case::\n>  force::\n>  \tAct as though the corresponding command-line option with\n>  \ta leading '--' was passed on the command line\n> @@ -1091,6 +1100,8 @@ not be passed as option:\n>  * import-marks\n>  * export-marks\n>  * cat-blob-fd\n> +* fold-case\n> +* no-fold-case\n>  * force\n>  \n>  `done`\n> diff --git a/fast-import.c b/fast-import.c\n> index 6378726..958f3da 100644\n> --- a/fast-import.c\n> +++ b/fast-import.c\n> @@ -371,10 +371,18 @@ static volatile sig_atomic_t checkpoint_requested;\n>  /* Where to write output of cat-blob commands */\n>  static int cat_blob_fd = STDOUT_FILENO;\n>  \n> +/* Whether to enable case folding */\n> +static int fold_case;\n> +\n>  static void parse_argv(void);\n>  static void parse_cat_blob(const char *p);\n>  static void parse_ls(const char *p, struct branch *b);\n>  \n> +static int strncmp_foldcase(const char *a, const char *b, size_t count)\n> +{\n> +\treturn fold_case ? strncasecmp(a, b, count) : strncmp(a, b, count);\n> +}\n> +\n>  static void write_branch_report(FILE *rpt, struct branch *b)\n>  {\n>  \tfprintf(rpt, \"%s:\\n\", b->name);\n> @@ -1507,7 +1515,7 @@ static int tree_content_set(\n>  \tt = root->tree;\n>  \tfor (i = 0; i < t->entry_count; i++) {\n>  \t\te = t->entries[i];\n> -\t\tif (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {\n> +\t\tif (e->name->str_len == n && !strncmp_foldcase(p, e->name->str_dat, n)) {\n>  \t\t\tif (!*slash1) {\n>  \t\t\t\tif (!S_ISDIR(mode)\n>  \t\t\t\t\t\t&& e->versions[1].mode == mode\n> @@ -1597,7 +1605,7 @@ static int tree_content_remove(\n>  \tt = root->tree;\n>  \tfor (i = 0; i < t->entry_count; i++) {\n>  \t\te = t->entries[i];\n> -\t\tif (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {\n> +\t\tif (e->name->str_len == n && !strncmp_foldcase(p, e->name->str_dat, n)) {\n>  \t\t\tif (*slash1 && !S_ISDIR(e->versions[1].mode))\n>  \t\t\t\t/*\n>  \t\t\t\t * If p names a file in some subdirectory, and a\n> @@ -1664,7 +1672,7 @@ static int tree_content_get(\n>  \tt = root->tree;\n>  \tfor (i = 0; i < t->entry_count; i++) {\n>  \t\te = t->entries[i];\n> -\t\tif (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {\n> +\t\tif (e->name->str_len == n && !strncmp_foldcase(p, e->name->str_dat, n)) {\n>  \t\t\tif (!*slash1)\n>  \t\t\t\tgoto found_entry;\n>  \t\t\tif (!S_ISDIR(e->versions[1].mode))\n> @@ -3246,6 +3254,10 @@ static int parse_one_feature(const char *feature, int from_stream)\n>  \t\trelative_marks_paths = 1;\n>  \t} else if (!strcmp(feature, \"no-relative-marks\")) {\n>  \t\trelative_marks_paths = 0;\n> +\t} else if (!strcmp(feature, \"fold-case\")) {\n> +\t\tfold_case = 1;\n> +\t} else if (!strcmp(feature, \"no-fold-case\")) {\n> +\t\tfold_case = 0;\n>  \t} else if (!strcmp(feature, \"done\")) {\n>  \t\trequire_explicit_termination = 1;\n>  \t} else if (!strcmp(feature, \"force\")) {\n> @@ -3372,6 +3384,7 @@ int main(int argc, char **argv)\n>  \tavail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));\n>  \tmarks = pool_calloc(1, sizeof(struct mark_set));\n>  \n> +\tfold_case = ignore_case;\nA complete different question:\nAccording to my understanding,\n\n\"git -c core.ignorecase=false fast-import\"\n\nshould already do what you want to do.\n(I haven't tested it, but it should work, otherwise there is probably a bug somewhere)\n\nBut that option is probably \"hidden\" under the general git options :\nhttp://git-htmldocs.googlecode.com/git/git.html\n\n\n\n>  \tglobal_argc = argc;\n>  \tglobal_argv = argv;\n>  \n> diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\n> index aac126f..7057c26 100755\n> --- a/t/t9300-fast-import.sh\n> +++ b/t/t9300-fast-import.sh\n> @@ -3088,4 +3088,83 @@ test_expect_success 'U: validate root delete result' '\n>  \tcompare_diff_raw expect actual\n>  '\n>  \n> +cat >input <<INPUT_END\n> +blob\n> +mark :1\n> +data 2\n> +a\n> +\n> +commit refs/heads/V\n> +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n> +data 0\n> +\n> +M 644 :1 a\n> +\n> +commit refs/heads/V\n> +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n> +data 0\n> +\n> +R a A\n> +INPUT_END\n> +\n> +test_expect_success 'V: default case folding with ignorecase=true' '\n> +\tgit config core.ignorecase true &&\n> +\tgit fast-import <input &&\n> +\tgit ls-tree refs/heads/V >actual &&\n> +\tgit update-ref -d refs/heads/V &&\n> +\tcat >expected <<\\EOF &&\n> +100644 blob 78981922613b2afb6025042ff6bd878ac1994e85\ta\n> +EOF\n> +\ttest_cmp expected actual'\n> +\n> +test_expect_success 'V: default case folding with ignorecase=false' '\n> +\tgit config core.ignorecase false &&\n> +\tgit fast-import <input &&\n> +\tgit ls-tree refs/heads/V >actual &&\n> +\tgit update-ref -d refs/heads/V &&\n> +\tcat >expected <<\\EOF &&\n> +100644 blob 78981922613b2afb6025042ff6bd878ac1994e85\tA\n> +EOF\n> +\ttest_cmp expected actual'\n> +\n> +test_expect_success 'V: forced case folding with ignorecase=true' '\n> +\tgit config core.ignorecase true &&\n> +\tgit fast-import --fold-case <input &&\n> +\tgit ls-tree refs/heads/V >actual &&\n> +\tgit update-ref -d refs/heads/V &&\n> +\tcat >expected <<\\EOF &&\n> +100644 blob 78981922613b2afb6025042ff6bd878ac1994e85\ta\n> +EOF\n> +\ttest_cmp expected actual'\n> +\nIf you want to make it shorter (and try to avoid repetition):\nThe forced true cases could be collected in a loop.\n(and the same for forced=false)\n[snip]\n"},{"id":"259588","messageId":"xmqqwq1appcf.fsf@gitster.dls.corp.google.com","threadId":"38147","inReplyTo":"55313B4B.3030106@web.de","subject":"Re: [PATCH] fast-import: add options to enable/disable case folding","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-04-17T18:44:00Z","receivedAt":"2015-04-17T18:44:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Torsten Bögershausen <tboegi@web.de> writes:\n\n>> +--[no-]fold-case::\n>> +\tWhen files/directories with the same name but a different case\n>> +\tare detected, they are treated as the same (--fold-case) or as\n>> +\tbeing different (--no-fold-case). The default is --fold-case\n>> +\twhen `core.ignorecase` is set to `true`, and --no-fold-case when\n>> +\tit is `false`.\n>> +\n> Most often the we use the term \"ignore-case\", could that be a better name ?\n> Other opinions, pros/cons  ?\n\nYeah, --[no-]ignore-case sounds more in line with how other\ncommands' options are spelled.\n\nBut I somehow thought this \"case-folding\" was deliberately done as\nan improvement against the original that did not have a way to do\nthe \"ignore-case\"?\n\nhttp://thread.gmane.org/gmane.comp.version-control.git/200597/focus=200625\n\nI am not sure why not until now I did not find the original\njustification dubious, but I think fast-export should never do case\nfolding---Joshua talks about working trees on a file system that is\nincapable of expressing different cases, but \"export\" is about\nreading in-repository histories, whose trees are fully capable of\nexpressing paths in different cases just fine, and spitting out a\nfile that can be processed by fast-import.  I do not see why it\nshould collapse two different paths that differ in case at export\ntime.\n\nIf the original history is broken by Perforce or whatever and\nrecording the history of the same path in different case\ncombinations in different commits, perhaps the right thing to do is\nto fix the original history in Git repository before exporting in\nthe first place.\n\nI do not see how such a corruption is related to the characteristics\nof the filesystem where \"export\" is run.  Perhaps a case-insensitive\nfilesystem may helped Perforce to corrupt the history when initial\nimport of the history into Git was done, but core.ignorecase of the\ncurrent repository does not help us decide if that was actually the\ncase---the import may have been done on a completely different\nmachine.\n\nSo perhaps we should rip the case folding out altogether instead?\nThe entry for the change in the Release Notes may say:\n\n * \"git fast-import\" incorrectly case-folded the paths recorded in\n   the history when core.ignorease is set (i.e. the repository's\n   working tree is incapable of expressing paths that differ only in\n   their cases); this old bug was reported in 2012 and was finally\n   corrected.\n\nor something like that?\n"},{"id":"259591","messageId":"20150417195705.GA36902@flurp.local","threadId":"38147","inReplyTo":"55313B4B.3030106@web.de","subject":"Re: [PATCH] fast-import: add options to enable/disable case folding","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-04-17T19:57:05Z","receivedAt":"2015-04-17T19:57:05Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 17, 2015 at 06:56:43PM +0200, Torsten Bögershausen wrote:\n> On 04/17/2015 01:52 PM, Mike Hommey wrote:\n> > +test_expect_success 'V: default case folding with ignorecase=true' '\n> > +\tgit config core.ignorecase true &&\n> > +\tgit fast-import <input &&\n> > +\tgit ls-tree refs/heads/V >actual &&\n> > +\tgit update-ref -d refs/heads/V &&\n> > +\tcat >expected <<\\EOF &&\n> > +100644 blob 78981922613b2afb6025042ff6bd878ac1994e85\ta\n> > +EOF\n> > +\ttest_cmp expected actual'\n> > +\n> > +test_expect_success 'V: default case folding with ignorecase=false' '\n> > +\tgit config core.ignorecase false &&\n> > +\tgit fast-import <input &&\n> > +\tgit ls-tree refs/heads/V >actual &&\n> > +\tgit update-ref -d refs/heads/V &&\n> > +\tcat >expected <<\\EOF &&\n> > +100644 blob 78981922613b2afb6025042ff6bd878ac1994e85\tA\n> > +EOF\n> > +\ttest_cmp expected actual'\n> > +\n> > +test_expect_success 'V: forced case folding with ignorecase=true' '\n> > +\tgit config core.ignorecase true &&\n> > +\tgit fast-import --fold-case <input &&\n> > +\tgit ls-tree refs/heads/V >actual &&\n> > +\tgit update-ref -d refs/heads/V &&\n> > +\tcat >expected <<\\EOF &&\n> > +100644 blob 78981922613b2afb6025042ff6bd878ac1994e85\ta\n> > +EOF\n> > +\ttest_cmp expected actual'\n>\n> If you want to make it shorter (and try to avoid repetition):\n> The forced true cases could be collected in a loop.\n> (and the same for forced=false)\n\nI was also going to suggest squashing the repetition. Here's what I\nhad in mind:\n\n--- >8 ---\ntest_foldcase() {\n\tignore=$1 &&\n\tcase \"$2\" in\n\ttrue) fold=--fold-case folded=true ;;\n\tfalse) fold=--no-fold-case folded=false ;;\n\t*) fold= folded=$ignore ;;\n\tesac &&\n\tcase $folded in true) folded=a ;; false) folded=A ;; esac &&\n\n\ttest_expect_success \"V: case folding: ignorecase=$ignore${fold:+ $fold}\" \"\n\t\tgit -c core.ignorecase=$ignore fast-import $fold <input &&\n\t\tgit ls-tree refs/heads/V >actual &&\n\t\tgit update-ref -d refs/heads/V &&\n\t\tcat >expect <<-EOF &&\n\t\t100644 blob 78981922613b2afb6025042ff6bd878ac1994e85\t$folded\n\t\tEOF\n\t\ttest_cmp expect actual\n\t\"\n}\n\nfor o in '' true false\ndo\n\tfor c in true false\n\tdo\n\t\ttest_foldcase $c \"$o\"\n\tdone\ndone\n--- >8 ---\n\nwhich outputs:\n\n--- >8 ---\nok 176 - V: case folding: ignorecase=true\nok 177 - V: case folding: ignorecase=false\nok 178 - V: case folding: ignorecase=true --fold-case\nok 179 - V: case folding: ignorecase=false --fold-case\nok 180 - V: case folding: ignorecase=true --no-fold-case\nok 181 - V: case folding: ignorecase=false --no-fold-case\n--- >8 ---\n"},{"id":"259614","messageId":"20150418073611.GA13410@glandium.org","threadId":"38147","inReplyTo":"xmqqwq1appcf.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] fast-import: add options to enable/disable case folding","fromName":"Mike Hommey","fromEmail":"mh@glandium.org","sentAt":"2015-04-18T07:36:11Z","receivedAt":"2015-04-18T07:36:11Z","isPatch":true,"sender":{"key":"mh@glandium.org","avatar":"https://avatars.githubusercontent.com/u/1038527?v=4"},"body":"On Fri, Apr 17, 2015 at 11:44:00AM -0700, Junio C Hamano wrote:\n> So perhaps we should rip the case folding out altogether instead?\n> The entry for the change in the Release Notes may say:\n> \n>  * \"git fast-import\" incorrectly case-folded the paths recorded in\n>    the history when core.ignorease is set (i.e. the repository's\n>    working tree is incapable of expressing paths that differ only in\n>    their cases); this old bug was reported in 2012 and was finally\n>    corrected.\n> \n> or something like that?\n\nIs anything else then git-p4 known to rely on case folding? If not, I\nguess that's a reasonable plan. We could even add an option to\nfast-import that would allow to turn case folding back on, and make\ngit-p4 use it, so that its expectations are fulfilled. Although at some\npoint, it could (should?) do case folding itself(?)\n\nMike\n"},{"id":"259934","messageId":"553A0FF6.6070700@diamand.org","threadId":"38147","inReplyTo":"20150418073611.GA13410@glandium.org","subject":"Re: [PATCH] fast-import: add options to enable/disable case folding","fromName":"Luke Diamand","fromEmail":"luke@diamand.org","sentAt":"2015-04-24T09:42:14Z","receivedAt":"2015-04-24T09:42:14Z","isPatch":true,"sender":{"key":"luke@diamand.org","avatar":"https://avatars.githubusercontent.com/u/5330967?v=4"},"body":"On 18/04/15 08:36, Mike Hommey wrote:\n> On Fri, Apr 17, 2015 at 11:44:00AM -0700, Junio C Hamano wrote:\n>> So perhaps we should rip the case folding out altogether instead?\n>> The entry for the change in the Release Notes may say:\n>>\n>>   * \"git fast-import\" incorrectly case-folded the paths recorded in\n>>     the history when core.ignorease is set (i.e. the repository's\n>>     working tree is incapable of expressing paths that differ only in\n>>     their cases); this old bug was reported in 2012 and was finally\n>>     corrected.\n>>\n>> or something like that?\n>\n> Is anything else then git-p4 known to rely on case folding? If not, I\n> guess that's a reasonable plan. We could even add an option to\n> fast-import that would allow to turn case folding back on, and make\n> git-p4 use it, so that its expectations are fulfilled. Although at some\n> point, it could (should?) do case folding itself(?)\n\ngit-p4 has a single line of code that checks if core.ignorecase is \nturned on, and uses this to decide whether to skip files that are \noutside the depot being tracked and I *think* is not really related to \nfast-import.\n\nI don't know to what extent though git-p4 relies on the current \nbehaviour of git fast-import to fold case for it.\n\nThere's a 'p4 info' command which tells you what the server thinks it's \ndoing:\n\n$ p4 info | grep Case\nCase Handling: sensitive\n\nI don't know how long that support has been present (it might not work \non older servers that some people are still using).\n\nIt's also possible to force the server to be case-insensitive on the \nLinux version. That's useful, as it we could construct some test cases \nto see what we're likely to break without having to force people to \ninstall a case-insensitive OS in order to run the git regression tests.\n\nLuke\n\n\n>\n> Mike\n> --\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n>\n"}]}