{"thread":{"id":"32614","subject":"[PATCH/WIP 01/10] pathspec: allow to use alternate char for quoting long magic mnemonic","startedAt":"2013-01-13T12:49:29Z","lastAt":"2013-01-13T12:49:39Z","messageCount":11,"participants":["Nguyễn Thái Ngọc Duy"],"isPatch":true,"patchVersion":1,"patchTotal":10},"messages":[{"id":"206685","messageId":"1358081379-17752-1-git-send-email-pclouds@gmail.com","threadId":"32614","inReplyTo":null,"subject":"[PATCH/WIP 00/10] Fancy pathspec stuff","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-13T12:49:29Z","receivedAt":"2013-01-13T12:49:29Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"I wanted to see how new pathspec feature can be implemented after\nnd/parse-pathspec, mainly to see if nd/parse-pathspec needs fixing.\nIt's nowhere near 'pu' quality but may be interesting for some people.\n\nIt does:\n\n- introduce :q/.../ syntax in addition to :(...), which always\n  requires quoting in bash\n\n- separate prefix part from the rest of pathspec, allowing it to be\n  treated differently (e.g. prefix is matched exactly regardless\n  pathspec magic)\n\n- implement :(glob) using wildmatch (i.e. incompatible with the\n  wildcards that current pathspec uses)\n\n- implement :(icase) -- with bugs\n\n- implement :(literal), similar to --literal-pathspecs\n\nThat's all my spam for today.\n\nNguyễn Thái Ngọc Duy (10):\n  pathspec: allow to use alternate char for quoting long magic mnemonic\n  parse_pathspec: make sure the prefix part is wildcard-free\n  pathspec: support :(literal) syntax for noglob pathspec\n  parse_pathspec: save prefix information\n  pathspec: prepare for :(glob)path syntax\n  Enable :(glob)path syntax for a lot of commands\n  parse_pathspec: accept :(icase)path syntax\n  common_prefix/read_directory: treat PATHSPEC_ICASE like wildcards\n  pathspec: support icase in match_pathspec_depth and\n    tree_entry_interesting\n  Enable ls-files and ls-tree for testing PATHSPEC_ICASE\n\n archive.c                  |  4 ++-\n builtin/add.c              | 19 +++++++++++---\n builtin/checkout.c         |  6 ++++-\n builtin/clean.c            |  6 ++++-\n builtin/commit.c           | 10 +++++--\n builtin/diff.c             |  2 +-\n builtin/grep.c             |  6 ++++-\n builtin/ls-files.c         |  6 ++++-\n builtin/ls-tree.c          |  7 ++++-\n builtin/rerere.c           |  6 ++++-\n builtin/reset.c            |  6 ++++-\n builtin/rm.c               |  6 ++++-\n builtin/update-index.c     |  6 ++++-\n cache.h                    | 23 +++++++++++++++-\n dir.c                      | 60 ++++++++++++++++++++++++++++--------------\n dir.h                      |  8 +++---\n path.c                     | 15 ++++++++++-\n revision.c                 |  7 +++--\n setup.c                    | 65 +++++++++++++++++++++++++++++++++-------------\n t/t6130-pathspec-noglob.sh | 18 +++++++++++++\n t/t6131-pathspec-prefix.sh | 47 +++++++++++++++++++++++++++++++++\n tree-diff.c                |  2 +-\n tree-walk.c                | 39 +++++++++++++++++-----------\n 23 files changed, 295 insertions(+), 79 deletions(-)\n create mode 100755 t/t6131-pathspec-prefix.sh\n\n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206684","messageId":"1358081379-17752-2-git-send-email-pclouds@gmail.com","threadId":"32614","inReplyTo":"1358081379-17752-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 01/10] pathspec: allow to use alternate char for quoting long magic mnemonic","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-13T12:49:30Z","receivedAt":"2013-01-13T12:49:30Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Currently use parentheses, e.g. \":(icase,literal)path\", but they do\nnot play well with unix shells because they have special meaning and\nwe need to quote them. Allow an alternate syntax \":q/icase,literal/path\".\n\nSimilar to ed's s/// syntax, '/' can be replaced with anything. If the\nopening quote has a closing counterpart, e.g. () [] <> {}, then it'll\nbe quoted as such.\n\nIt may even be a good thing to kill ':(...)' syntax, which can easily\nbe replaced with ':q(...)'. It's unlikely that anybody is used to it\nyet.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n setup.c | 30 ++++++++++++++++++++++++------\n 1 file changed, 24 insertions(+), 6 deletions(-)\n\ndiff --git a/setup.c b/setup.c\nindex 69ca047..9db6093 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -196,14 +196,32 @@ static unsigned prefix_pathspec(struct pathspec_item *item,\n \n \tif (elt[0] != ':') {\n \t\t; /* nothing to do */\n-\t} else if (elt[1] == '(') {\n+\t} else if (elt[1] == '(' || elt[1] == 'q') {\n \t\t/* longhand */\n \t\tconst char *nextat;\n-\t\tfor (copyfrom = elt + 2;\n-\t\t     *copyfrom && *copyfrom != ')';\n+\t\tchar close = ')';\n+\t\tchar sep[3] = \",)\";\n+\t\tif (elt[1] == '(')\n+\t\t\tcopyfrom = elt + 2;\n+\t\telse {\n+\t\t\tcopyfrom = elt + 3;\n+\t\t\tswitch (elt[2]) {\n+\t\t\tcase '(': close = ')'; break;\n+\t\t\tcase '[': close = ']'; break;\n+\t\t\tcase '{': close = '}'; break;\n+\t\t\tcase '<': close = '>'; break;\n+\t\t\tcase '\\0':\n+\t\t\t\tdie(\"Invalid pathspec '%s'\", elt);\n+\t\t\tdefault:\n+\t\t\t\tclose = elt[2];\n+\t\t\t}\n+\t\t\tsep[1] = close;\n+\t\t}\n+\t\tfor (;\n+\t\t     *copyfrom && *copyfrom != close;\n \t\t     copyfrom = nextat) {\n-\t\t\tsize_t len = strcspn(copyfrom, \",)\");\n-\t\t\tif (copyfrom[len] == ')')\n+\t\t\tsize_t len = strcspn(copyfrom, sep);\n+\t\t\tif (copyfrom[len] == close)\n \t\t\t\tnextat = copyfrom + len;\n \t\t\telse\n \t\t\t\tnextat = copyfrom + len + 1;\n@@ -219,7 +237,7 @@ static unsigned prefix_pathspec(struct pathspec_item *item,\n \t\t\t\tdie(\"Invalid pathspec magic '%.*s' in '%s'\",\n \t\t\t\t    (int) len, copyfrom, elt);\n \t\t}\n-\t\tif (*copyfrom == ')')\n+\t\tif (*copyfrom == close)\n \t\t\tcopyfrom++;\n \t} else {\n \t\t/* shorthand */\n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206686","messageId":"1358081379-17752-3-git-send-email-pclouds@gmail.com","threadId":"32614","inReplyTo":"1358081379-17752-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 02/10] parse_pathspec: make sure the prefix part is wildcard-free","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-13T12:49:31Z","receivedAt":"2013-01-13T12:49:31Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache.h                    |  1 +\n path.c                     | 15 ++++++++++++++-\n setup.c                    | 24 +++++++++++++++--------\n t/t6131-pathspec-prefix.sh | 47 ++++++++++++++++++++++++++++++++++++++++++++++\n 4 files changed, 78 insertions(+), 9 deletions(-)\n create mode 100755 t/t6131-pathspec-prefix.sh\n\ndiff --git a/cache.h b/cache.h\nindex c7a8d28..f3de28d 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -747,6 +747,7 @@ const char *real_path(const char *path);\n const char *real_path_if_valid(const char *path);\n const char *absolute_path(const char *path);\n const char *relative_path(const char *abs, const char *base);\n+int normalize_path_copy_len(char *dst, const char *src, int *prefix_len);\n int normalize_path_copy(char *dst, const char *src);\n int longest_ancestor_length(const char *path, struct string_list *prefixes);\n char *strip_path_suffix(const char *path, const char *suffix);\ndiff --git a/path.c b/path.c\nindex d3d3f8b..7baf334 100644\n--- a/path.c\n+++ b/path.c\n@@ -487,8 +487,14 @@ const char *relative_path(const char *abs, const char *base)\n  *\n  * Note that this function is purely textual.  It does not follow symlinks,\n  * verify the existence of the path, or make any system calls.\n+ *\n+ * prefix_len != NULL is for a specific case of prefix_pathspec():\n+ * assume that src == dst and src[0..prefix_len-1] is already\n+ * normalized, any time \"../\" eats up to the prefix_len part,\n+ * prefix_len is reduced. In the end prefix_len is the remaining\n+ * prefix that has not been overridden by user pathspec.\n  */\n-int normalize_path_copy(char *dst, const char *src)\n+int normalize_path_copy_len(char *dst, const char *src, int *prefix_len)\n {\n \tchar *dst0;\n \n@@ -563,11 +569,18 @@ int normalize_path_copy(char *dst, const char *src)\n \t\t/* Windows: dst[-1] cannot be backslash anymore */\n \t\twhile (dst0 < dst && dst[-1] != '/')\n \t\t\tdst--;\n+\t\tif (prefix_len && *prefix_len > dst - dst0)\n+\t\t\t*prefix_len = dst - dst0;\n \t}\n \t*dst = '\\0';\n \treturn 0;\n }\n \n+int normalize_path_copy(char *dst, const char *src)\n+{\n+\treturn normalize_path_copy_len(dst, src, NULL);\n+}\n+\n /*\n  * path = Canonical absolute path\n  * prefixes = string_list containing normalized, absolute paths without\ndiff --git a/setup.c b/setup.c\nindex 9db6093..c5e97c9 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -5,10 +5,11 @@\n static int inside_git_dir = -1;\n static int inside_work_tree = -1;\n \n-static char *prefix_path_gently(const char *prefix, int len, const char *path)\n+static char *prefix_path_gently(const char *prefix, int *p_len, const char *path)\n {\n \tconst char *orig = path;\n \tchar *sanitized;\n+\tint len = *p_len;\n \tif (is_absolute_path(orig)) {\n \t\tconst char *temp = real_path(path);\n \t\tsanitized = xmalloc(len + strlen(temp) + 1);\n@@ -19,7 +20,7 @@ static char *prefix_path_gently(const char *prefix, int len, const char *path)\n \t\t\tmemcpy(sanitized, prefix, len);\n \t\tstrcpy(sanitized + len, path);\n \t}\n-\tif (normalize_path_copy(sanitized, sanitized))\n+\tif (normalize_path_copy_len(sanitized, sanitized, p_len))\n \t\tgoto error_out;\n \tif (is_absolute_path(orig)) {\n \t\tsize_t root_len, len, total;\n@@ -44,7 +45,7 @@ static char *prefix_path_gently(const char *prefix, int len, const char *path)\n \n char *prefix_path(const char *prefix, int len, const char *path)\n {\n-\tchar *r = prefix_path_gently(prefix, len, path);\n+\tchar *r = prefix_path_gently(prefix, &len, path);\n \tif (!r)\n \t\tdie(\"'%s' is outside repository\", path);\n \treturn r;\n@@ -53,7 +54,7 @@ char *prefix_path(const char *prefix, int len, const char *path)\n int path_inside_repo(const char *prefix, const char *path)\n {\n \tint len = prefix ? strlen(prefix) : 0;\n-\tchar *r = prefix_path_gently(prefix, len, path);\n+\tchar *r = prefix_path_gently(prefix, &len, path);\n \tif (r) {\n \t\tfree(r);\n \t\treturn 1;\n@@ -261,10 +262,14 @@ static unsigned prefix_pathspec(struct pathspec_item *item,\n \t\t\tcopyfrom++;\n \t}\n \n-\tif (magic & PATHSPEC_FROMTOP)\n+\tif (magic & PATHSPEC_FROMTOP) {\n \t\tmatch = xstrdup(copyfrom);\n-\telse\n-\t\tmatch = prefix_path(prefix, prefixlen, copyfrom);\n+\t\tprefixlen = 0;\n+\t} else {\n+\t\tmatch = prefix_path_gently(prefix, &prefixlen, copyfrom);\n+\t\tif (!match)\n+\t\t\tdie(\"%s: '%s' is outside repository\", elt, copyfrom);\n+\t}\n \t*raw = item->match = match;\n \titem->original = elt;\n \titem->len = strlen(item->match);\n@@ -300,8 +305,11 @@ static unsigned prefix_pathspec(struct pathspec_item *item,\n \titem->flags = 0;\n \tif (limit_pathspec_to_literal())\n \t\titem->nowildcard_len = item->len;\n-\telse\n+\telse {\n \t\titem->nowildcard_len = simple_length(item->match);\n+\t\tif (item->nowildcard_len < prefixlen)\n+\t\t\titem->nowildcard_len = prefixlen;\n+\t}\n \tif (item->nowildcard_len < item->len &&\n \t    item->match[item->nowildcard_len] == '*' &&\n \t    no_wildcard(item->match + item->nowildcard_len + 1))\ndiff --git a/t/t6131-pathspec-prefix.sh b/t/t6131-pathspec-prefix.sh\nnew file mode 100755\nindex 0000000..db59091\n--- /dev/null\n+++ b/t/t6131-pathspec-prefix.sh\n@@ -0,0 +1,47 @@\n+#!/bin/sh\n+\n+test_description='Verify the exact matching of prefix part in pathspec'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+\tmkdir a\\* ab &&\n+\t: >a\\*/foo &&\n+\t: >ab/foo &&\n+\tgit add .\n+'\n+\n+test_expect_success 'prefix has wildcards but treated as literal' '\n+\t(\n+\t\tcd a\\* &&\n+\t\tgit ls-files --cached foo\n+\t) >actual &&\n+\techo foo >expected &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'prefix is reduced to empty' '\n+\t(\n+\t\tcd a\\* &&\n+\t\tgit ls-files --cached ../a\\*/foo\n+\t) >actual &&\n+\tcat <<\\EOF >expected &&\n+foo\n+../ab/foo\n+EOF\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'prefix is reduced to empty (2)' '\n+\t(\n+\t\tcd a\\* &&\n+\t\tgit ls-files --cached non-existing//../fancy/.//../../a\\*/foo\n+\t) >actual &&\n+\tcat <<\\EOF >expected &&\n+foo\n+../ab/foo\n+EOF\n+\ttest_cmp expected actual\n+'\n+\n+test_done\n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206687","messageId":"1358081379-17752-4-git-send-email-pclouds@gmail.com","threadId":"32614","inReplyTo":"1358081379-17752-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 03/10] pathspec: support :(literal) syntax for noglob pathspec","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-13T12:49:32Z","receivedAt":"2013-01-13T12:49:32Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n archive.c                  |  4 +++-\n builtin/add.c              |  8 +++++---\n builtin/checkout.c         |  4 +++-\n builtin/clean.c            |  4 +++-\n builtin/commit.c           |  6 ++++--\n builtin/diff.c             |  2 +-\n builtin/grep.c             |  4 +++-\n builtin/ls-files.c         |  3 ++-\n builtin/ls-tree.c          |  4 +++-\n builtin/rerere.c           |  4 +++-\n builtin/reset.c            |  4 +++-\n builtin/rm.c               |  4 +++-\n builtin/update-index.c     |  4 +++-\n cache.h                    |  1 +\n dir.c                      |  6 +++---\n revision.c                 |  5 +++--\n setup.c                    |  7 ++++---\n t/t6130-pathspec-noglob.sh | 18 ++++++++++++++++++\n tree-diff.c                |  2 +-\n tree-walk.c                |  2 +-\n 20 files changed, 70 insertions(+), 26 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex d9da58b..d3b6969 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -234,7 +234,9 @@ static void parse_pathspec_arg(const char **pathspec,\n \t * mark \"used\" pathspec. The magic mask cannot be lifted until\n \t * it does.\n \t */\n-\tparse_pathspec(&ar_args->pathspec, PATHSPEC_FROMTOP, 0, \"\", pathspec);\n+\tparse_pathspec(&ar_args->pathspec,\n+\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       0, \"\", pathspec);\n \tif (ar_args->pathspec.nr) {\n \t\tpathspec = ar_args->pathspec._raw;\n \t\twhile (*pathspec) {\ndiff --git a/builtin/add.c b/builtin/add.c\nindex a7840c8..d09a07a 100644\n--- a/builtin/add.c\n+++ b/builtin/add.c\n@@ -202,7 +202,8 @@ int interactive_add(int argc, const char **argv, const char *prefix, int patch)\n \t * Do not enable fancy magic here.  git-add--interactive may\n \t * not be able to handle it.\n \t */\n-\tparse_pathspec(&pathspec, PATHSPEC_FROMTOP,\n+\tparse_pathspec(&pathspec,\n+\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n \t\t       PATHSPEC_EMPTY_MATCH_ALL |\n \t\t       PATHSPEC_SYMLINK_LEADING_PATH,\n \t\t       prefix, argv);\n@@ -377,7 +378,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t * Check the \"pathspec '%s' did not match any files\" block\n \t * below before enabling new magic.\n \t */\n-\tparse_pathspec(&pathspec, PATHSPEC_FROMTOP,\n+\tparse_pathspec(&pathspec,\n+\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n \t\t       PATHSPEC_SYMLINK_LEADING_PATH |\n \t\t       PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE,\n \t\t       prefix, argv);\n@@ -414,7 +416,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t\t/*\n \t\t * file_exists() assumes exact match\n \t\t */\n-\t\tGUARD_PATHSPEC(&pathspec, PATHSPEC_FROMTOP);\n+\t\tGUARD_PATHSPEC(&pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);\n \n \t\tfor (i = 0; i < pathspec.nr; i++) {\n \t\t\tconst char *path = pathspec.items[i].match;\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 1b413e2..90f4a01 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -1112,7 +1112,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \t\t * cannot handle. Magic mask is pretty safe to be\n \t\t * lifted for new magic when opts.patch_mode == 0.\n \t\t */\n-\t\tparse_pathspec(&opts.pathspec, PATHSPEC_FROMTOP, 0, prefix, argv);\n+\t\tparse_pathspec(&opts.pathspec,\n+\t\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t\t       0, prefix, argv);\n \n \t\tif (!opts.pathspec.nr)\n \t\t\tdie(_(\"invalid path specification\"));\ndiff --git a/builtin/clean.c b/builtin/clean.c\nindex 1d8ff5f..b4ffa2b 100644\n--- a/builtin/clean.c\n+++ b/builtin/clean.c\n@@ -100,7 +100,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)\n \t\tadd_exclude(exclude_list.items[i].string, \"\", 0,\n \t\t\t    &dir.exclude_list[EXC_CMDL]);\n \n-\tparse_pathspec(&pathspec, PATHSPEC_FROMTOP, 0, prefix, argv);\n+\tparse_pathspec(&pathspec,\n+\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       0, prefix, argv);\n \n \tfill_directory(&dir, &pathspec);\n \ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 2011f98..433fdb9 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -281,7 +281,8 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,\n \n \tif (is_status)\n \t\trefresh_flags |= REFRESH_UNMERGED;\n-\tparse_pathspec(&pathspec, PATHSPEC_FROMTOP,\n+\tparse_pathspec(&pathspec,\n+\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n \t\t       PATHSPEC_EMPTY_MATCH_ALL,\n \t\t       prefix, argv);\n \n@@ -1203,7 +1204,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)\n \thandle_untracked_files_arg(&s);\n \tif (show_ignored_in_status)\n \t\ts.show_ignored_files = 1;\n-\tparse_pathspec(&s.pathspec, PATHSPEC_FROMTOP,\n+\tparse_pathspec(&s.pathspec,\n+\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n \t\t       PATHSPEC_EMPTY_MATCH_ALL,\n \t\t       prefix, argv);\n \ndiff --git a/builtin/diff.c b/builtin/diff.c\nindex 6b4e3f9..b78435f 100644\n--- a/builtin/diff.c\n+++ b/builtin/diff.c\n@@ -372,7 +372,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n \t}\n \tif (rev.prune_data.nr) {\n \t\t/* builtin_diff_b_f() */\n-\t\tGUARD_PATHSPEC(&rev.prune_data, PATHSPEC_FROMTOP);\n+\t\tGUARD_PATHSPEC(&rev.prune_data, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);\n \t\tif (!path)\n \t\t\tpath = rev.prune_data.items[0].match;\n \t\tpaths += rev.prune_data.nr;\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex f370bad..4d8e82c 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -856,7 +856,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\t\tverify_filename(prefix, argv[j], j == i);\n \t}\n \n-\tparse_pathspec(&pathspec, PATHSPEC_FROMTOP, 0, prefix, argv + i);\n+\tparse_pathspec(&pathspec,\n+\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       0, prefix, argv + i);\n \tpathspec.max_depth = opt.max_depth;\n \tpathspec.recursive = 1;\n \ndiff --git a/builtin/ls-files.c b/builtin/ls-files.c\nindex e3ccf50..1cbd211 100644\n--- a/builtin/ls-files.c\n+++ b/builtin/ls-files.c\n@@ -535,7 +535,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)\n \tif (require_work_tree && !is_inside_work_tree())\n \t\tsetup_work_tree();\n \n-\tparse_pathspec(&pathspec, PATHSPEC_FROMTOP,\n+\tparse_pathspec(&pathspec,\n+\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n \t\t       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,\n \t\t       prefix, argv);\n \ndiff --git a/builtin/ls-tree.c b/builtin/ls-tree.c\nindex 58899a5..4764683 100644\n--- a/builtin/ls-tree.c\n+++ b/builtin/ls-tree.c\n@@ -172,7 +172,9 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)\n \t * cannot be lifted until it is converted to use\n \t * match_pathspec_depth() or tree_entry_interesting()\n \t */\n-\tparse_pathspec(&pathspec, PATHSPEC_FROMTOP, 0, prefix, argv + 1);\n+\tparse_pathspec(&pathspec,\n+\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       0, prefix, argv + 1);\n \tfor (i = 0; i < pathspec.nr; i++)\n \t\tpathspec.items[i].nowildcard_len = pathspec.items[i].len;\n \tpathspec.has_wildcard = 0;\ndiff --git a/builtin/rerere.c b/builtin/rerere.c\nindex a573c4a..779fc77 100644\n--- a/builtin/rerere.c\n+++ b/builtin/rerere.c\n@@ -71,7 +71,9 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)\n \t\tstruct pathspec pathspec;\n \t\tif (argc < 2)\n \t\t\twarning(\"'git rerere forget' without paths is deprecated\");\n-\t\tparse_pathspec(&pathspec, PATHSPEC_FROMTOP, 0, prefix, argv + 1);\n+\t\tparse_pathspec(&pathspec,\n+\t\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t\t       0, prefix, argv + 1);\n \t\treturn rerere_forget(&pathspec);\n \t}\n \ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex 0185bb0..69ce164 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -183,7 +183,9 @@ static int read_from_tree(const char *prefix, const char **argv,\n \tstruct diff_options opt;\n \n \tmemset(&opt, 0, sizeof(opt));\n-\tparse_pathspec(&opt.pathspec, PATHSPEC_FROMTOP, 0, prefix, argv);\n+\tparse_pathspec(&opt.pathspec,\n+\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       0, prefix, argv);\n \topt.output_format = DIFF_FORMAT_CALLBACK;\n \topt.format_callback = update_index_from_diff;\n \topt.format_callback_data = &index_was_discarded;\ndiff --git a/builtin/rm.c b/builtin/rm.c\nindex b2a99c2..d46f1aa 100644\n--- a/builtin/rm.c\n+++ b/builtin/rm.c\n@@ -249,7 +249,9 @@ int cmd_rm(int argc, const char **argv, const char *prefix)\n \t\t}\n \t}\n \n-\tparse_pathspec(&pathspec, PATHSPEC_FROMTOP, 0, prefix, argv);\n+\tparse_pathspec(&pathspec,\n+\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       0, prefix, argv);\n \trefresh_index(&the_index, REFRESH_QUIET, &pathspec, NULL, NULL);\n \n \tseen = NULL;\ndiff --git a/builtin/update-index.c b/builtin/update-index.c\nindex 6728e59..1dd6178 100644\n--- a/builtin/update-index.c\n+++ b/builtin/update-index.c\n@@ -548,7 +548,9 @@ static int do_reupdate(int ac, const char **av,\n \tint has_head = 1;\n \tstruct pathspec pathspec;\n \n-\tparse_pathspec(&pathspec, PATHSPEC_FROMTOP, 0, prefix, av + 1);\n+\tparse_pathspec(&pathspec,\n+\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       0, prefix, av + 1);\n \n \tif (read_ref(\"HEAD\", head_sha1))\n \t\t/* If there is no HEAD, that means it is an initial\ndiff --git a/cache.h b/cache.h\nindex f3de28d..900b81a 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -478,6 +478,7 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct\n \n /* Pathspec magic */\n #define PATHSPEC_FROMTOP    (1<<0)\n+#define PATHSPEC_LITERAL    (1<<1)\n \n #define PATHSPEC_ONESTAR 1\t/* the pathspec pattern sastisfies GFNM_ONESTAR */\n \ndiff --git a/dir.c b/dir.c\nindex efc676c..63d07cd 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -64,7 +64,7 @@ static size_t common_prefix_len(const struct pathspec *pathspec)\n \tint n;\n \tsize_t max = 0;\n \n-\tGUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP);\n+\tGUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);\n \n \tfor (n = 0; n < pathspec->nr; n++) {\n \t\tsize_t i = 0, len = 0;\n@@ -181,7 +181,7 @@ int match_pathspec_depth(const struct pathspec *ps,\n {\n \tint i, retval = 0;\n \n-\tGUARD_PATHSPEC(ps, PATHSPEC_FROMTOP);\n+\tGUARD_PATHSPEC(ps, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);\n \n \tif (!ps->nr) {\n \t\tif (!ps->recursive || ps->max_depth == -1)\n@@ -1230,7 +1230,7 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const stru\n \t * Check out create_simplify()\n \t */\n \tif (pathspec)\n-\t\tGUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP);\n+\t\tGUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);\n \n \tif (has_symlink_leading_path(path, len))\n \t\treturn dir->nr;\ndiff --git a/revision.c b/revision.c\nindex 231f53b..079955f 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1851,8 +1851,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n \t\t */\n \t\tALLOC_GROW(prune_data.path, prune_data.nr+1, prune_data.alloc);\n \t\tprune_data.path[prune_data.nr++] = NULL;\n-\t\tparse_pathspec(&revs->prune_data, PATHSPEC_FROMTOP, 0,\n-\t\t\t       revs->prefix, prune_data.path);\n+\t\tparse_pathspec(&revs->prune_data,\n+\t\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t\t       0, revs->prefix, prune_data.path);\n \t}\n \n \tif (revs->def == NULL)\ndiff --git a/setup.c b/setup.c\nindex c5e97c9..6b48f1b 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -157,7 +157,6 @@ void verify_non_filename(const char *prefix, const char *arg)\n  *\n  * Possible future magic semantics include stuff like:\n  *\n- *\t{ PATHSPEC_NOGLOB, '!', \"noglob\" },\n  *\t{ PATHSPEC_ICASE, '\\0', \"icase\" },\n  *\t{ PATHSPEC_RECURSIVE, '*', \"recursive\" },\n  *\t{ PATHSPEC_REGEXP, '\\0', \"regexp\" },\n@@ -170,6 +169,7 @@ static struct pathspec_magic {\n \tconst char *name;\n } pathspec_magic[] = {\n \t{ PATHSPEC_FROMTOP, '/', \"top\" },\n+\t{ PATHSPEC_LITERAL,   0, \"literal\" },\n };\n \n /*\n@@ -303,7 +303,7 @@ static unsigned prefix_pathspec(struct pathspec_item *item,\n \t\t}\n \n \titem->flags = 0;\n-\tif (limit_pathspec_to_literal())\n+\tif (limit_pathspec_to_literal() || (magic & PATHSPEC_LITERAL))\n \t\titem->nowildcard_len = item->len;\n \telse {\n \t\titem->nowildcard_len = simple_length(item->match);\n@@ -397,7 +397,8 @@ void parse_pathspec(struct pathspec *pathspec,\n const char **get_pathspec(const char *prefix, const char **pathspec)\n {\n \tstruct pathspec ps;\n-\tparse_pathspec(&ps, PATHSPEC_FROMTOP, 0, prefix, pathspec);\n+\tparse_pathspec(&ps, PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       0, prefix, pathspec);\n \treturn ps._raw;\n }\n \ndiff --git a/t/t6130-pathspec-noglob.sh b/t/t6130-pathspec-noglob.sh\nindex 39ef619..49c148e 100755\n--- a/t/t6130-pathspec-noglob.sh\n+++ b/t/t6130-pathspec-noglob.sh\n@@ -47,18 +47,36 @@ test_expect_success 'no-glob option matches literally (vanilla)' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'no-glob option matches literally (vanilla)' '\n+\techo vanilla >expect &&\n+\tgit log --format=%s -- \":(literal)foo\" >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'no-glob option matches literally (star)' '\n \techo star >expect &&\n \tgit --literal-pathspecs log --format=%s -- \"f*\" >actual &&\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'no-glob option matches literally (star)' '\n+\techo star >expect &&\n+\tgit log --format=%s -- \":(literal)f*\" >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'no-glob option matches literally (bracket)' '\n \techo bracket >expect &&\n \tgit --literal-pathspecs log --format=%s -- \"f[o][o]\" >actual &&\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'no-glob option matches literally (bracket)' '\n+\techo bracket >expect &&\n+\tgit log --format=%s -- \":(literal)f[o][o]\" >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'no-glob environment variable works' '\n \techo star >expect &&\n \tGIT_LITERAL_PATHSPECS=1 git log --format=%s -- \"f*\" >actual &&\ndiff --git a/tree-diff.c b/tree-diff.c\nindex 718f938..0e2e138 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -203,7 +203,7 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co\n \t * path. Magic that matches more than one path is not\n \t * supported.\n \t */\n-\tGUARD_PATHSPEC(&opt->pathspec, PATHSPEC_FROMTOP);\n+\tGUARD_PATHSPEC(&opt->pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);\n #if 0\n \t/*\n \t * We should reject wildcards as well. Unfortunately we\ndiff --git a/tree-walk.c b/tree-walk.c\nindex dd03750..d4ed51f 100644\n--- a/tree-walk.c\n+++ b/tree-walk.c\n@@ -635,7 +635,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,\n \tenum interesting never_interesting = ps->has_wildcard ?\n \t\tentry_not_interesting : all_entries_not_interesting;\n \n-\tGUARD_PATHSPEC(ps, PATHSPEC_FROMTOP);\n+\tGUARD_PATHSPEC(ps, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);\n \n \tif (!ps->nr) {\n \t\tif (!ps->recursive || ps->max_depth == -1)\n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206688","messageId":"1358081379-17752-5-git-send-email-pclouds@gmail.com","threadId":"32614","inReplyTo":"1358081379-17752-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 04/10] parse_pathspec: save prefix information","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-13T12:49:33Z","receivedAt":"2013-01-13T12:49:33Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache.h | 2 +-\n setup.c | 1 +\n 2 files changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/cache.h b/cache.h\nindex 900b81a..fb54876 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -493,7 +493,7 @@ struct pathspec {\n \t\tconst char *match;\n \t\tconst char *original;\n \t\tunsigned magic;\n-\t\tint len;\n+\t\tint len, prefix;\n \t\tint nowildcard_len;\n \t\tint flags;\n \t} *items;\ndiff --git a/setup.c b/setup.c\nindex 6b48f1b..c4af05e 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -310,6 +310,7 @@ static unsigned prefix_pathspec(struct pathspec_item *item,\n \t\tif (item->nowildcard_len < prefixlen)\n \t\t\titem->nowildcard_len = prefixlen;\n \t}\n+\titem->prefix = prefixlen;\n \tif (item->nowildcard_len < item->len &&\n \t    item->match[item->nowildcard_len] == '*' &&\n \t    no_wildcard(item->match + item->nowildcard_len + 1))\n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206689","messageId":"1358081379-17752-6-git-send-email-pclouds@gmail.com","threadId":"32614","inReplyTo":"1358081379-17752-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 05/10] pathspec: prepare for :(glob)path syntax","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-13T12:49:34Z","receivedAt":"2013-01-13T12:49:34Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":":(glob)path differs from path that it uses wildmatch with\nFNM_PATHNAME while plain \"path\" uses fnmatch without FNM_PATHNAME.\n\ngit_fnmatch() was probably ill-designed. It was intended to cover\nother use of fnmatch besides pathspec. But so far it's only used by\npathspec code.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/add.c |  9 +++++++--\n cache.h       |  1 +\n dir.c         | 34 ++++++++++++++++++++++------------\n dir.h         |  8 +++-----\n setup.c       |  1 +\n tree-walk.c   | 11 ++++++-----\n 6 files changed, 40 insertions(+), 24 deletions(-)\n\ndiff --git a/builtin/add.c b/builtin/add.c\nindex d09a07a..1b99e2b 100644\n--- a/builtin/add.c\n+++ b/builtin/add.c\n@@ -416,11 +416,16 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t\t/*\n \t\t * file_exists() assumes exact match\n \t\t */\n-\t\tGUARD_PATHSPEC(&pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);\n+\t\tGUARD_PATHSPEC(&pathspec,\n+\t\t\t       PATHSPEC_FROMTOP |\n+\t\t\t       PATHSPEC_LITERAL |\n+\t\t\t       PATHSPEC_GLOB);\n \n \t\tfor (i = 0; i < pathspec.nr; i++) {\n \t\t\tconst char *path = pathspec.items[i].match;\n-\t\t\tif (!seen[i] && !file_exists(path)) {\n+\t\t\tif (!seen[i] &&\n+\t\t\t    ((pathspec.items[i].magic & PATHSPEC_GLOB) ||\n+\t\t\t     !file_exists(path))) {\n \t\t\t\tif (ignore_missing) {\n \t\t\t\t\tint dtype = DT_UNKNOWN;\n \t\t\t\t\tif (is_path_excluded(&check, path, -1, &dtype))\ndiff --git a/cache.h b/cache.h\nindex fb54876..9c27f18 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -479,6 +479,7 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct\n /* Pathspec magic */\n #define PATHSPEC_FROMTOP    (1<<0)\n #define PATHSPEC_LITERAL    (1<<1)\n+#define PATHSPEC_GLOB       (1<<2)\n \n #define PATHSPEC_ONESTAR 1\t/* the pathspec pattern sastisfies GFNM_ONESTAR */\n \ndiff --git a/dir.c b/dir.c\nindex 63d07cd..760b776 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -37,26 +37,28 @@ int fnmatch_icase(const char *pattern, const char *string, int flags)\n \treturn fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0));\n }\n \n-inline int git_fnmatch(const char *pattern, const char *string,\n-\t\t       int flags, int prefix)\n+inline int git_fnmatch(const struct pathspec_item *item,\n+\t\t       const char *pattern, const char *string,\n+\t\t       int prefix)\n {\n-\tint fnm_flags = 0;\n-\tif (flags & GFNM_PATHNAME)\n-\t\tfnm_flags |= FNM_PATHNAME;\n \tif (prefix > 0) {\n \t\tif (strncmp(pattern, string, prefix))\n \t\t\treturn FNM_NOMATCH;\n \t\tpattern += prefix;\n \t\tstring += prefix;\n \t}\n-\tif (flags & GFNM_ONESTAR) {\n+\tif (item->flags & PATHSPEC_ONESTAR) {\n \t\tint pattern_len = strlen(++pattern);\n \t\tint string_len = strlen(string);\n \t\treturn string_len < pattern_len ||\n \t\t       strcmp(pattern,\n \t\t\t      string + string_len - pattern_len);\n \t}\n-\treturn fnmatch(pattern, string, fnm_flags);\n+\tif (item->magic & PATHSPEC_GLOB)\n+\t\treturn wildmatch(pattern, string, 0);\n+\telse\n+\t\t/* wildmatch has not learned no FNM_PATHNAME mode yet */\n+\t\treturn fnmatch(pattern, string, 0);\n }\n \n static size_t common_prefix_len(const struct pathspec *pathspec)\n@@ -64,7 +66,10 @@ static size_t common_prefix_len(const struct pathspec *pathspec)\n \tint n;\n \tsize_t max = 0;\n \n-\tGUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);\n+\tGUARD_PATHSPEC(pathspec,\n+\t\t       PATHSPEC_FROMTOP |\n+\t\t       PATHSPEC_LITERAL |\n+\t\t       PATHSPEC_GLOB);\n \n \tfor (n = 0; n < pathspec->nr; n++) {\n \t\tsize_t i = 0, len = 0;\n@@ -159,8 +164,7 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,\n \t}\n \n \tif (item->nowildcard_len < item->len &&\n-\t    !git_fnmatch(match, name,\n-\t\t\t item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,\n+\t    !git_fnmatch(item, match, name,\n \t\t\t item->nowildcard_len - prefix))\n \t\treturn MATCHED_FNMATCH;\n \n@@ -181,7 +185,10 @@ int match_pathspec_depth(const struct pathspec *ps,\n {\n \tint i, retval = 0;\n \n-\tGUARD_PATHSPEC(ps, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);\n+\tGUARD_PATHSPEC(ps,\n+\t\t       PATHSPEC_FROMTOP |\n+\t\t       PATHSPEC_LITERAL |\n+\t\t       PATHSPEC_GLOB);\n \n \tif (!ps->nr) {\n \t\tif (!ps->recursive || ps->max_depth == -1)\n@@ -1230,7 +1237,10 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const stru\n \t * Check out create_simplify()\n \t */\n \tif (pathspec)\n-\t\tGUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);\n+\t\tGUARD_PATHSPEC(pathspec,\n+\t\t\t       PATHSPEC_FROMTOP |\n+\t\t\t       PATHSPEC_LITERAL |\n+\t\t\t       PATHSPEC_GLOB);\n \n \tif (has_symlink_leading_path(path, len))\n \t\treturn dir->nr;\ndiff --git a/dir.h b/dir.h\nindex a03af80..b6da4b7 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -168,10 +168,8 @@ extern int fnmatch_icase(const char *pattern, const char *string, int flags);\n /*\n  * The prefix part of pattern must not contains wildcards.\n  */\n-#define GFNM_PATHNAME 1\t\t/* similar to FNM_PATHNAME */\n-#define GFNM_ONESTAR  2\t\t/* there is only _one_ wildcard, a star */\n-\n-extern int git_fnmatch(const char *pattern, const char *string,\n-\t\t       int flags, int prefix);\n+extern int git_fnmatch(const struct pathspec_item *item,\n+\t\t       const char *pattern, const char *string,\n+\t\t       int prefix);\n \n #endif\ndiff --git a/setup.c b/setup.c\nindex c4af05e..b3e146d 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -170,6 +170,7 @@ static struct pathspec_magic {\n } pathspec_magic[] = {\n \t{ PATHSPEC_FROMTOP, '/', \"top\" },\n \t{ PATHSPEC_LITERAL,   0, \"literal\" },\n+\t{ PATHSPEC_GLOB,   '\\0', \"glob\" },\n };\n \n /*\ndiff --git a/tree-walk.c b/tree-walk.c\nindex d4ed51f..1679ce7 100644\n--- a/tree-walk.c\n+++ b/tree-walk.c\n@@ -635,7 +635,10 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,\n \tenum interesting never_interesting = ps->has_wildcard ?\n \t\tentry_not_interesting : all_entries_not_interesting;\n \n-\tGUARD_PATHSPEC(ps, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);\n+\tGUARD_PATHSPEC(ps,\n+\t\t       PATHSPEC_FROMTOP |\n+\t\t       PATHSPEC_LITERAL |\n+\t\t       PATHSPEC_GLOB);\n \n \tif (!ps->nr) {\n \t\tif (!ps->recursive || ps->max_depth == -1)\n@@ -677,8 +680,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,\n \t\t\t\treturn entry_interesting;\n \n \t\t\tif (item->nowildcard_len < item->len) {\n-\t\t\t\tif (!git_fnmatch(match + baselen, entry->path,\n-\t\t\t\t\t\t item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,\n+\t\t\t\tif (!git_fnmatch(item, match + baselen, entry->path,\n \t\t\t\t\t\t item->nowildcard_len - baselen))\n \t\t\t\t\treturn entry_interesting;\n \n@@ -719,8 +721,7 @@ match_wildcards:\n \n \t\tstrbuf_add(base, entry->path, pathlen);\n \n-\t\tif (!git_fnmatch(match, base->buf + base_offset,\n-\t\t\t\t item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,\n+\t\tif (!git_fnmatch(item, match, base->buf + base_offset,\n \t\t\t\t item->nowildcard_len)) {\n \t\t\tstrbuf_setlen(base, base_offset + baselen);\n \t\t\treturn entry_interesting;\n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206690","messageId":"1358081379-17752-7-git-send-email-pclouds@gmail.com","threadId":"32614","inReplyTo":"1358081379-17752-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 06/10] Enable :(glob)path syntax for a lot of commands","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-13T12:49:35Z","receivedAt":"2013-01-13T12:49:35Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/add.c          | 4 +++-\n builtin/checkout.c     | 4 +++-\n builtin/clean.c        | 4 +++-\n builtin/commit.c       | 8 ++++++--\n builtin/grep.c         | 4 +++-\n builtin/ls-files.c     | 4 +++-\n builtin/ls-tree.c      | 4 +++-\n builtin/rerere.c       | 4 +++-\n builtin/reset.c        | 4 +++-\n builtin/rm.c           | 4 +++-\n builtin/update-index.c | 4 +++-\n revision.c             | 4 +++-\n 12 files changed, 39 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/add.c b/builtin/add.c\nindex 1b99e2b..a3ffa9d 100644\n--- a/builtin/add.c\n+++ b/builtin/add.c\n@@ -379,7 +379,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t * below before enabling new magic.\n \t */\n \tparse_pathspec(&pathspec,\n-\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_FROMTOP |\n+\t\t       PATHSPEC_LITERAL |\n+\t\t       PATHSPEC_GLOB,\n \t\t       PATHSPEC_SYMLINK_LEADING_PATH |\n \t\t       PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE,\n \t\t       prefix, argv);\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 90f4a01..cb5d548 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -1113,7 +1113,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \t\t * lifted for new magic when opts.patch_mode == 0.\n \t\t */\n \t\tparse_pathspec(&opts.pathspec,\n-\t\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t\t       PATHSPEC_FROMTOP |\n+\t\t\t       PATHSPEC_LITERAL |\n+\t\t\t       (opts.patch_mode ? PATHSPEC_GLOB : 0),\n \t\t\t       0, prefix, argv);\n \n \t\tif (!opts.pathspec.nr)\ndiff --git a/builtin/clean.c b/builtin/clean.c\nindex b4ffa2b..f675d5a 100644\n--- a/builtin/clean.c\n+++ b/builtin/clean.c\n@@ -101,7 +101,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)\n \t\t\t    &dir.exclude_list[EXC_CMDL]);\n \n \tparse_pathspec(&pathspec,\n-\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_FROMTOP |\n+\t\t       PATHSPEC_LITERAL |\n+\t\t       PATHSPEC_GLOB,\n \t\t       0, prefix, argv);\n \n \tfill_directory(&dir, &pathspec);\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 433fdb9..743a3ea 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -282,7 +282,9 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,\n \tif (is_status)\n \t\trefresh_flags |= REFRESH_UNMERGED;\n \tparse_pathspec(&pathspec,\n-\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_FROMTOP |\n+\t\t       PATHSPEC_LITERAL |\n+\t\t       PATHSPEC_GLOB,\n \t\t       PATHSPEC_EMPTY_MATCH_ALL,\n \t\t       prefix, argv);\n \n@@ -1205,7 +1207,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)\n \tif (show_ignored_in_status)\n \t\ts.show_ignored_files = 1;\n \tparse_pathspec(&s.pathspec,\n-\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_FROMTOP |\n+\t\t       PATHSPEC_LITERAL |\n+\t\t       PATHSPEC_GLOB,\n \t\t       PATHSPEC_EMPTY_MATCH_ALL,\n \t\t       prefix, argv);\n \ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 4d8e82c..9f1b029 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -857,7 +857,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t}\n \n \tparse_pathspec(&pathspec,\n-\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_FROMTOP |\n+\t\t       PATHSPEC_LITERAL |\n+\t\t       PATHSPEC_GLOB,\n \t\t       0, prefix, argv + i);\n \tpathspec.max_depth = opt.max_depth;\n \tpathspec.recursive = 1;\ndiff --git a/builtin/ls-files.c b/builtin/ls-files.c\nindex 1cbd211..feb4220 100644\n--- a/builtin/ls-files.c\n+++ b/builtin/ls-files.c\n@@ -536,7 +536,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)\n \t\tsetup_work_tree();\n \n \tparse_pathspec(&pathspec,\n-\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_FROMTOP |\n+\t\t       PATHSPEC_LITERAL |\n+\t\t       PATHSPEC_GLOB,\n \t\t       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,\n \t\t       prefix, argv);\n \ndiff --git a/builtin/ls-tree.c b/builtin/ls-tree.c\nindex 4764683..25d0590 100644\n--- a/builtin/ls-tree.c\n+++ b/builtin/ls-tree.c\n@@ -173,7 +173,9 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)\n \t * match_pathspec_depth() or tree_entry_interesting()\n \t */\n \tparse_pathspec(&pathspec,\n-\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_FROMTOP |\n+\t\t       PATHSPEC_LITERAL |\n+\t\t       PATHSPEC_GLOB,\n \t\t       0, prefix, argv + 1);\n \tfor (i = 0; i < pathspec.nr; i++)\n \t\tpathspec.items[i].nowildcard_len = pathspec.items[i].len;\ndiff --git a/builtin/rerere.c b/builtin/rerere.c\nindex 779fc77..d64d010 100644\n--- a/builtin/rerere.c\n+++ b/builtin/rerere.c\n@@ -72,7 +72,9 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)\n \t\tif (argc < 2)\n \t\t\twarning(\"'git rerere forget' without paths is deprecated\");\n \t\tparse_pathspec(&pathspec,\n-\t\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t\t       PATHSPEC_FROMTOP |\n+\t\t\t       PATHSPEC_LITERAL |\n+\t\t\t       PATHSPEC_GLOB,\n \t\t\t       0, prefix, argv + 1);\n \t\treturn rerere_forget(&pathspec);\n \t}\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex 69ce164..f71af9c 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -184,7 +184,9 @@ static int read_from_tree(const char *prefix, const char **argv,\n \n \tmemset(&opt, 0, sizeof(opt));\n \tparse_pathspec(&opt.pathspec,\n-\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_FROMTOP |\n+\t\t       PATHSPEC_LITERAL |\n+\t\t       PATHSPEC_GLOB,\n \t\t       0, prefix, argv);\n \topt.output_format = DIFF_FORMAT_CALLBACK;\n \topt.format_callback = update_index_from_diff;\ndiff --git a/builtin/rm.c b/builtin/rm.c\nindex d46f1aa..ff0fd5b 100644\n--- a/builtin/rm.c\n+++ b/builtin/rm.c\n@@ -250,7 +250,9 @@ int cmd_rm(int argc, const char **argv, const char *prefix)\n \t}\n \n \tparse_pathspec(&pathspec,\n-\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_FROMTOP |\n+\t\t       PATHSPEC_LITERAL |\n+\t\t       PATHSPEC_GLOB,\n \t\t       0, prefix, argv);\n \trefresh_index(&the_index, REFRESH_QUIET, &pathspec, NULL, NULL);\n \ndiff --git a/builtin/update-index.c b/builtin/update-index.c\nindex 1dd6178..c456e1b 100644\n--- a/builtin/update-index.c\n+++ b/builtin/update-index.c\n@@ -549,7 +549,9 @@ static int do_reupdate(int ac, const char **av,\n \tstruct pathspec pathspec;\n \n \tparse_pathspec(&pathspec,\n-\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_FROMTOP |\n+\t\t       PATHSPEC_LITERAL |\n+\t\t       PATHSPEC_GLOB,\n \t\t       0, prefix, av + 1);\n \n \tif (read_ref(\"HEAD\", head_sha1))\ndiff --git a/revision.c b/revision.c\nindex 079955f..5ac480b 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1852,7 +1852,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n \t\tALLOC_GROW(prune_data.path, prune_data.nr+1, prune_data.alloc);\n \t\tprune_data.path[prune_data.nr++] = NULL;\n \t\tparse_pathspec(&revs->prune_data,\n-\t\t\t       PATHSPEC_FROMTOP | PATHSPEC_LITERAL,\n+\t\t\t       PATHSPEC_FROMTOP |\n+\t\t\t       PATHSPEC_LITERAL |\n+\t\t\t       PATHSPEC_GLOB,\n \t\t\t       0, revs->prefix, prune_data.path);\n \t}\n \n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206691","messageId":"1358081379-17752-8-git-send-email-pclouds@gmail.com","threadId":"32614","inReplyTo":"1358081379-17752-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 07/10] parse_pathspec: accept :(icase)path syntax","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-13T12:49:36Z","receivedAt":"2013-01-13T12:49:36Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache.h | 1 +\n setup.c | 2 +-\n 2 files changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/cache.h b/cache.h\nindex 9c27f18..c3b5585 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -480,6 +480,7 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct\n #define PATHSPEC_FROMTOP    (1<<0)\n #define PATHSPEC_LITERAL    (1<<1)\n #define PATHSPEC_GLOB       (1<<2)\n+#define PATHSPEC_ICASE      (1<<3)\n \n #define PATHSPEC_ONESTAR 1\t/* the pathspec pattern sastisfies GFNM_ONESTAR */\n \ndiff --git a/setup.c b/setup.c\nindex b3e146d..e22abf1 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -157,7 +157,6 @@ void verify_non_filename(const char *prefix, const char *arg)\n  *\n  * Possible future magic semantics include stuff like:\n  *\n- *\t{ PATHSPEC_ICASE, '\\0', \"icase\" },\n  *\t{ PATHSPEC_RECURSIVE, '*', \"recursive\" },\n  *\t{ PATHSPEC_REGEXP, '\\0', \"regexp\" },\n  *\n@@ -171,6 +170,7 @@ static struct pathspec_magic {\n \t{ PATHSPEC_FROMTOP, '/', \"top\" },\n \t{ PATHSPEC_LITERAL,   0, \"literal\" },\n \t{ PATHSPEC_GLOB,   '\\0', \"glob\" },\n+\t{ PATHSPEC_ICASE,  '\\0', \"icase\" },\n };\n \n /*\n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206692","messageId":"1358081379-17752-9-git-send-email-pclouds@gmail.com","threadId":"32614","inReplyTo":"1358081379-17752-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 08/10] common_prefix/read_directory: treat PATHSPEC_ICASE like wildcards","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-13T12:49:37Z","receivedAt":"2013-01-13T12:49:37Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n dir.c | 18 +++++++++++++-----\n 1 file changed, 13 insertions(+), 5 deletions(-)\n\ndiff --git a/dir.c b/dir.c\nindex 760b776..d0e7ca8 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -66,15 +66,22 @@ static size_t common_prefix_len(const struct pathspec *pathspec)\n \tint n;\n \tsize_t max = 0;\n \n+\t/*\n+\t * \":(icase)path\" is treated as a pathspec full of wildcard\n+\t */\n \tGUARD_PATHSPEC(pathspec,\n \t\t       PATHSPEC_FROMTOP |\n \t\t       PATHSPEC_LITERAL |\n-\t\t       PATHSPEC_GLOB);\n+\t\t       PATHSPEC_GLOB |\n+\t\t       PATHSPEC_ICASE);\n \n \tfor (n = 0; n < pathspec->nr; n++) {\n-\t\tsize_t i = 0, len = 0;\n-\t\twhile (i < pathspec->items[n].nowildcard_len &&\n-\t\t       (n == 0 || i < max)) {\n+\t\tsize_t i = 0, len = 0, item_len;\n+\t\tif (pathspec->items[n].magic & PATHSPEC_ICASE)\n+\t\t\titem_len = pathspec->items[n].prefix;\n+\t\telse\n+\t\t\titem_len = pathspec->items[n].nowildcard_len;\n+\t\twhile (i < item_len && (n == 0 || i < max)) {\n \t\t\tchar c = pathspec->items[n].match[i];\n \t\t\tif (c != pathspec->items[0].match[i])\n \t\t\t\tbreak;\n@@ -1240,7 +1247,8 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const stru\n \t\tGUARD_PATHSPEC(pathspec,\n \t\t\t       PATHSPEC_FROMTOP |\n \t\t\t       PATHSPEC_LITERAL |\n-\t\t\t       PATHSPEC_GLOB);\n+\t\t\t       PATHSPEC_GLOB |\n+\t\t\t       PATHSPEC_ICASE);\n \n \tif (has_symlink_leading_path(path, len))\n \t\treturn dir->nr;\n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206694","messageId":"1358081379-17752-10-git-send-email-pclouds@gmail.com","threadId":"32614","inReplyTo":"1358081379-17752-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 09/10] pathspec: support icase in match_pathspec_depth and tree_entry_interesting","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-13T12:49:38Z","receivedAt":"2013-01-13T12:49:38Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache.h     | 17 +++++++++++++++++\n dir.c       | 18 +++++++++++-------\n tree-walk.c | 30 +++++++++++++++++++-----------\n 3 files changed, 47 insertions(+), 18 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex c3b5585..216f87c 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -522,6 +522,23 @@ extern void free_pathspec(struct pathspec *);\n extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec);\n \n extern int limit_pathspec_to_literal(void);\n+static inline int ps_strncmp(const struct pathspec_item *item,\n+\t\t\t     const char *s1, const char *s2, size_t n)\n+{\n+\tif (item->magic & PATHSPEC_ICASE)\n+\t\treturn strncasecmp(s1, s2, n);\n+\telse\n+\t\treturn strncmp(s1, s2, n);\n+}\n+\n+static inline int ps_strcmp(const struct pathspec_item *item,\n+\t\t\t    const char *s1, const char *s2)\n+{\n+\tif (item->magic & PATHSPEC_ICASE)\n+\t\treturn strcasecmp(s1, s2);\n+\telse\n+\t\treturn strcmp(s1, s2);\n+}\n \n #define HASH_WRITE_OBJECT 1\n #define HASH_FORMAT_CHECK 2\ndiff --git a/dir.c b/dir.c\nindex d0e7ca8..e9edb65 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -42,7 +42,7 @@ inline int git_fnmatch(const struct pathspec_item *item,\n \t\t       int prefix)\n {\n \tif (prefix > 0) {\n-\t\tif (strncmp(pattern, string, prefix))\n+\t\tif (ps_strncmp(item, pattern, string, prefix))\n \t\t\treturn FNM_NOMATCH;\n \t\tpattern += prefix;\n \t\tstring += prefix;\n@@ -51,14 +51,16 @@ inline int git_fnmatch(const struct pathspec_item *item,\n \t\tint pattern_len = strlen(++pattern);\n \t\tint string_len = strlen(string);\n \t\treturn string_len < pattern_len ||\n-\t\t       strcmp(pattern,\n-\t\t\t      string + string_len - pattern_len);\n+\t\t\tps_strcmp(item, pattern,\n+\t\t\t\t  string + string_len - pattern_len);\n \t}\n \tif (item->magic & PATHSPEC_GLOB)\n-\t\treturn wildmatch(pattern, string, 0);\n+\t\treturn wildmatch(pattern, string,\n+\t\t\t\t item->magic & PATHSPEC_ICASE ? FNM_CASEFOLD : 0);\n \telse\n \t\t/* wildmatch has not learned no FNM_PATHNAME mode yet */\n-\t\treturn fnmatch(pattern, string, 0);\n+\t\treturn fnmatch(pattern, string,\n+\t\t\t       item->magic & PATHSPEC_ICASE ? FNM_CASEFOLD : 0);\n }\n \n static size_t common_prefix_len(const struct pathspec *pathspec)\n@@ -162,7 +164,7 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,\n \tif (!*match)\n \t\treturn MATCHED_RECURSIVELY;\n \n-\tif (matchlen <= namelen && !strncmp(match, name, matchlen)) {\n+\tif (matchlen <= namelen && !ps_strncmp(item, match, name, matchlen)) {\n \t\tif (matchlen == namelen)\n \t\t\treturn MATCHED_EXACTLY;\n \n@@ -192,10 +194,12 @@ int match_pathspec_depth(const struct pathspec *ps,\n {\n \tint i, retval = 0;\n \n+\t/* BUG: we should not match icase on the prefix part */\n \tGUARD_PATHSPEC(ps,\n \t\t       PATHSPEC_FROMTOP |\n \t\t       PATHSPEC_LITERAL |\n-\t\t       PATHSPEC_GLOB);\n+\t\t       PATHSPEC_GLOB |\n+\t\t       PATHSPEC_ICASE);\n \n \tif (!ps->nr) {\n \t\tif (!ps->recursive || ps->max_depth == -1)\ndiff --git a/tree-walk.c b/tree-walk.c\nindex 1679ce7..3d9c2ba 100644\n--- a/tree-walk.c\n+++ b/tree-walk.c\n@@ -488,7 +488,8 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch\n \treturn retval;\n }\n \n-static int match_entry(const struct name_entry *entry, int pathlen,\n+static int match_entry(const struct pathspec_item *item,\n+\t\t       const struct name_entry *entry, int pathlen,\n \t\t       const char *match, int matchlen,\n \t\t       enum interesting *never_interesting)\n {\n@@ -504,8 +505,8 @@ static int match_entry(const struct name_entry *entry, int pathlen,\n \t\t * Does match sort strictly earlier than path\n \t\t * with their common parts?\n \t\t */\n-\t\tm = strncmp(match, entry->path,\n-\t\t\t    (matchlen < pathlen) ? matchlen : pathlen);\n+\t\tm = ps_strncmp(item, match, entry->path,\n+\t\t\t       (matchlen < pathlen) ? matchlen : pathlen);\n \t\tif (m < 0)\n \t\t\treturn 0;\n \n@@ -540,7 +541,7 @@ static int match_entry(const struct name_entry *entry, int pathlen,\n \t\t * we cheated and did not do strncmp(), so we do\n \t\t * that here.\n \t\t */\n-\t\tm = strncmp(match, entry->path, pathlen);\n+\t\tm = ps_strncmp(item, match, entry->path, pathlen);\n \n \t/*\n \t * If common part matched earlier then it is a hit,\n@@ -553,10 +554,11 @@ static int match_entry(const struct name_entry *entry, int pathlen,\n \treturn 0;\n }\n \n-static int match_dir_prefix(const char *base,\n+static int match_dir_prefix(const struct pathspec_item *item,\n+\t\t\t    const char *base,\n \t\t\t    const char *match, int matchlen)\n {\n-\tif (strncmp(base, match, matchlen))\n+\tif (ps_strncmp(item, base, match, matchlen))\n \t\treturn 0;\n \n \t/*\n@@ -593,7 +595,7 @@ static int match_wildcard_base(const struct pathspec_item *item,\n \t\t */\n \t\tif (baselen >= matchlen) {\n \t\t\t*matched = matchlen;\n-\t\t\treturn !strncmp(base, match, matchlen);\n+\t\t\treturn !ps_strncmp(item, base, match, matchlen);\n \t\t}\n \n \t\tdirlen = matchlen;\n@@ -606,7 +608,7 @@ static int match_wildcard_base(const struct pathspec_item *item,\n \t\t * base ends with '/' so we are sure it really matches\n \t\t * directory\n \t\t */\n-\t\tif (strncmp(base, match, baselen))\n+\t\tif (ps_strncmp(item, base, match, baselen))\n \t\t\treturn 0;\n \t\t*matched = baselen;\n \t} else\n@@ -635,10 +637,16 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,\n \tenum interesting never_interesting = ps->has_wildcard ?\n \t\tentry_not_interesting : all_entries_not_interesting;\n \n+\t/*\n+\t * BUG: we should not match icase on the prefix part. The\n+\t * prefix length is in 'ps'. Although using it won't be easy\n+\t * as the pattern is cut into pieces...\n+\t */\n \tGUARD_PATHSPEC(ps,\n \t\t       PATHSPEC_FROMTOP |\n \t\t       PATHSPEC_LITERAL |\n-\t\t       PATHSPEC_GLOB);\n+\t\t       PATHSPEC_GLOB |\n+\t\t       PATHSPEC_ICASE);\n \n \tif (!ps->nr) {\n \t\tif (!ps->recursive || ps->max_depth == -1)\n@@ -659,7 +667,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,\n \n \t\tif (baselen >= matchlen) {\n \t\t\t/* If it doesn't match, move along... */\n-\t\t\tif (!match_dir_prefix(base_str, match, matchlen))\n+\t\t\tif (!match_dir_prefix(item, base_str, match, matchlen))\n \t\t\t\tgoto match_wildcards;\n \n \t\t\tif (!ps->recursive || ps->max_depth == -1)\n@@ -674,7 +682,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,\n \n \t\t/* Either there must be no base, or the base must match. */\n \t\tif (baselen == 0 || !strncmp(base_str, match, baselen)) {\n-\t\t\tif (match_entry(entry, pathlen,\n+\t\t\tif (match_entry(item, entry, pathlen,\n \t\t\t\t\tmatch + baselen, matchlen - baselen,\n \t\t\t\t\t&never_interesting))\n \t\t\t\treturn entry_interesting;\n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206693","messageId":"1358081379-17752-11-git-send-email-pclouds@gmail.com","threadId":"32614","inReplyTo":"1358081379-17752-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 10/10] Enable ls-files and ls-tree for testing PATHSPEC_ICASE","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-13T12:49:39Z","receivedAt":"2013-01-13T12:49:39Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/add.c      | 6 ++++--\n builtin/ls-files.c | 3 ++-\n builtin/ls-tree.c  | 3 ++-\n 3 files changed, 8 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/add.c b/builtin/add.c\nindex a3ffa9d..b9a5432 100644\n--- a/builtin/add.c\n+++ b/builtin/add.c\n@@ -421,12 +421,14 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t\tGUARD_PATHSPEC(&pathspec,\n \t\t\t       PATHSPEC_FROMTOP |\n \t\t\t       PATHSPEC_LITERAL |\n-\t\t\t       PATHSPEC_GLOB);\n+\t\t\t       PATHSPEC_GLOB |\n+\t\t\t       PATHSPEC_ICASE);\n \n \t\tfor (i = 0; i < pathspec.nr; i++) {\n \t\t\tconst char *path = pathspec.items[i].match;\n \t\t\tif (!seen[i] &&\n-\t\t\t    ((pathspec.items[i].magic & PATHSPEC_GLOB) ||\n+\t\t\t    ((pathspec.items[i].magic &\n+\t\t\t      (PATHSPEC_GLOB | PATHSPEC_ICASE)) ||\n \t\t\t     !file_exists(path))) {\n \t\t\t\tif (ignore_missing) {\n \t\t\t\t\tint dtype = DT_UNKNOWN;\ndiff --git a/builtin/ls-files.c b/builtin/ls-files.c\nindex feb4220..53b222d 100644\n--- a/builtin/ls-files.c\n+++ b/builtin/ls-files.c\n@@ -538,7 +538,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)\n \tparse_pathspec(&pathspec,\n \t\t       PATHSPEC_FROMTOP |\n \t\t       PATHSPEC_LITERAL |\n-\t\t       PATHSPEC_GLOB,\n+\t\t       PATHSPEC_GLOB |\n+\t\t       PATHSPEC_ICASE,\n \t\t       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,\n \t\t       prefix, argv);\n \ndiff --git a/builtin/ls-tree.c b/builtin/ls-tree.c\nindex 25d0590..cf943dd 100644\n--- a/builtin/ls-tree.c\n+++ b/builtin/ls-tree.c\n@@ -175,7 +175,8 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)\n \tparse_pathspec(&pathspec,\n \t\t       PATHSPEC_FROMTOP |\n \t\t       PATHSPEC_LITERAL |\n-\t\t       PATHSPEC_GLOB,\n+\t\t       PATHSPEC_GLOB |\n+\t\t       PATHSPEC_ICASE,\n \t\t       0, prefix, argv + 1);\n \tfor (i = 0; i < pathspec.nr; i++)\n \t\tpathspec.items[i].nowildcard_len = pathspec.items[i].len;\n-- \n1.8.0.rc2.23.g1fb49df\n"}]}