Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
Documentation/git.txt | 8
Documentation/glossary-content.txt | 3 ++
builtin/add.c | 6 ++-
builtin/ls-tree.c | 2 +-
cache.h| 1 +
dir.c | 74 -
git.c | 4 ++
pathspec.c | 9 +++-
pathspec.h | 22 -
t/t6131-pathspec-icase.sh (new +x) | 97 ++
tree-walk.c| 59 ++-
11 files changed, 257 insertions(+), 28 deletions(-)
create mode 100755 t/t6131-pathspec-icase.sh
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 3571a1b..546eea4 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -466,6 +466,10 @@ help ...`.
globbing on individual pathspecs can be done using pathspec
magic :(glob)
+--icase-pathspecs:
+ Add icase magic to all pathspec. This is equivalent to setting
+ the `GIT_ICASE_PATHSPECS` environment variable to `1`.
+
GIT COMMANDS
@@ -879,6 +883,10 @@ GIT_NOGLOB_PATHSPECS::
Setting this variable to `1` will cause Git to treat all
pathspecs as literal (aka literal magic).
+GIT_ICASE_PATHSPECS::
+ Setting this variable to `1` will cause Git to treat all
+ pathspeccs as case-insensitive.
+
Discussion[[Discussion]]
diff --git a/Documentation/glossary-content.txt
b/Documentation/glossary-content.txt
index a3d9029..13a64d3 100644
--- a/Documentation/glossary-content.txt
+++ b/Documentation/glossary-content.txt
@@ -334,6 +334,9 @@ literal;;
Wildcards in the pattern such as `*` or `?` are treated
as literal characters.
+icase;;
+ Case insensitive match.
+
glob;;
Git treats the pattern as a shell glob suitable for
consumption by fnmatch(3) with the FNM_PATHNAME flag:
diff --git a/builtin/add.c b/builtin/add.c
index 1dab246..9d52fc7 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -544,12 +544,14 @@ int cmd_add(int argc, const char **argv, const char
*prefix)
GUARD_PATHSPEC(pathspec,
PATHSPEC_FROMTOP |
PATHSPEC_LITERAL |
- PATHSPEC_GLOB);
+ PATHSPEC_GLOB |
+ PATHSPEC_ICASE);
for (i = 0; i pathspec.nr; i++) {
const char *path = pathspec.items[i].match;
if (!seen[i]
- ((pathspec.items[i].magic PATHSPEC_GLOB) ||
+ ((pathspec.items[i].magic
+ (PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
!file_exists(path))) {
if (ignore_missing) {
int dtype = DT_UNKNOWN;
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 7882352..f6d8215 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -173,7 +173,7 @@ int cmd_ls_tree(int argc, const char **argv, const char
*prefix)
* cannot be lifted until it is converted to use
* match_pathspec_depth() or tree_entry_interesting()
*/
- parse_pathspec(pathspec, PATHSPEC_GLOB,
+ parse_pathspec(pathspec, PATHSPEC_GLOB | PATHSPEC_ICASE,
PATHSPEC_PREFER_CWD,
prefix, argv + 1);
for (i = 0; i pathspec.nr; i++)
diff --git a/cache.h b/cache.h
index dc4d2ee..3cff825 100644
--- a/cache.h
+++ b/cache.h
@@ -369,6 +369,7 @@ static inline enum object_type object_type(unsigned int
mode)
#define GIT_LITERAL_PATHSPECS_ENVIRONMENT GIT_LITERAL_PATHSPECS
#define GIT_GLOB_PATHSPECS_ENVIRONMENT GIT_GLOB_PATHSPECS
#define GIT_NOGLOB_PATHSPECS_ENVIRONMENT GIT_NOGLOB_PATHSPECS
+#define GIT_ICASE_PATHSPECS_ENVIRONMENT GIT_ICASE_PATHSPECS
/*
* This environment variable is expected to contain a boolean indicating
diff --git a/dir.c b/dir.c
index 076bd46..8543736 100644
--- a/dir.c
+++ b/dir.c
@@ -57,7 +57,7 @@ inline int git_fnmatch(const struct pathspec_item *item,
int prefix)
{
if (prefix 0) {
- if (strncmp(pattern, string, prefix))
+ if (ps_strncmp(item, pattern, string, prefix))
return FNM_NOMATCH;
pattern += prefix;
string += prefix;
@@ -66,14 +66,18 @@ inline int git_fnmatch(const struct pathspec_item *item,
int pattern_len = strlen(++pattern);
int string_len = strlen(string);
return string_len pattern_len ||
- strcmp(pattern,
- string + string_len - pattern_len);
+ ps_strcmp(item, pattern,
+