@@ -57,7 +57,7 @@ inline int git_fnmatch(const struct pathspec_item *item,
5757 int prefix )
5858{
5959 if (prefix > 0 ) {
60- if (strncmp ( pattern , string , prefix ))
60+ if (ps_strncmp ( item , pattern , string , prefix ))
6161 return FNM_NOMATCH ;
6262 pattern += prefix ;
6363 string += prefix ;
@@ -66,14 +66,18 @@ inline int git_fnmatch(const struct pathspec_item *item,
6666 int pattern_len = strlen (++ pattern );
6767 int string_len = strlen (string );
6868 return string_len < pattern_len ||
69- strcmp ( pattern ,
70- string + string_len - pattern_len );
69+ ps_strcmp ( item , pattern ,
70+ string + string_len - pattern_len );
7171 }
7272 if (item -> magic & PATHSPEC_GLOB )
73- return wildmatch (pattern , string , WM_PATHNAME , NULL );
73+ return wildmatch (pattern , string ,
74+ WM_PATHNAME |
75+ (item -> magic & PATHSPEC_ICASE ? WM_CASEFOLD : 0 ),
76+ NULL );
7477 else
7578 /* wildmatch has not learned no FNM_PATHNAME mode yet */
76- return fnmatch (pattern , string , 0 );
79+ return fnmatch (pattern , string ,
80+ item -> magic & PATHSPEC_ICASE ? FNM_CASEFOLD : 0 );
7781}
7882
7983static int fnmatch_icase_mem (const char * pattern , int patternlen ,
@@ -110,16 +114,27 @@ static size_t common_prefix_len(const struct pathspec *pathspec)
110114 int n ;
111115 size_t max = 0 ;
112116
117+ /*
118+ * ":(icase)path" is treated as a pathspec full of
119+ * wildcard. In other words, only prefix is considered common
120+ * prefix. If the pathspec is abc/foo abc/bar, running in
121+ * subdir xyz, the common prefix is still xyz, not xuz/abc as
122+ * in non-:(icase).
123+ */
113124 GUARD_PATHSPEC (pathspec ,
114125 PATHSPEC_FROMTOP |
115126 PATHSPEC_MAXDEPTH |
116127 PATHSPEC_LITERAL |
117- PATHSPEC_GLOB );
128+ PATHSPEC_GLOB |
129+ PATHSPEC_ICASE );
118130
119131 for (n = 0 ; n < pathspec -> nr ; n ++ ) {
120- size_t i = 0 , len = 0 ;
121- while (i < pathspec -> items [n ].nowildcard_len &&
122- (n == 0 || i < max )) {
132+ size_t i = 0 , len = 0 , item_len ;
133+ if (pathspec -> items [n ].magic & PATHSPEC_ICASE )
134+ item_len = pathspec -> items [n ].prefix ;
135+ else
136+ item_len = pathspec -> items [n ].nowildcard_len ;
137+ while (i < item_len && (n == 0 || i < max )) {
123138 char c = pathspec -> items [n ].match [i ];
124139 if (c != pathspec -> items [0 ].match [i ])
125140 break ;
@@ -196,11 +211,44 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
196211 const char * match = item -> match + prefix ;
197212 int matchlen = item -> len - prefix ;
198213
214+ /*
215+ * The normal call pattern is:
216+ * 1. prefix = common_prefix_len(ps);
217+ * 2. prune something, or fill_directory
218+ * 3. match_pathspec_depth()
219+ *
220+ * 'prefix' at #1 may be shorter than the command's prefix and
221+ * it's ok for #2 to match extra files. Those extras will be
222+ * trimmed at #3.
223+ *
224+ * Suppose the pathspec is 'foo' and '../bar' running from
225+ * subdir 'xyz'. The common prefix at #1 will be empty, thanks
226+ * to "../". We may have xyz/foo _and_ XYZ/foo after #2. The
227+ * user does not want XYZ/foo, only the "foo" part should be
228+ * case-insensitive. We need to filter out XYZ/foo here. In
229+ * other words, we do not trust the caller on comparing the
230+ * prefix part when :(icase) is involved. We do exact
231+ * comparison ourselves.
232+ *
233+ * Normally the caller (common_prefix_len() in fact) does
234+ * _exact_ matching on name[-prefix+1..-1] and we do not need
235+ * to check that part. Be defensive and check it anyway, in
236+ * case common_prefix_len is changed, or a new caller is
237+ * introduced that does not use common_prefix_len.
238+ *
239+ * If the penalty turns out too high when prefix is really
240+ * long, maybe change it to
241+ * strncmp(match, name, item->prefix - prefix)
242+ */
243+ if (item -> prefix && (item -> magic & PATHSPEC_ICASE ) &&
244+ strncmp (item -> match , name - prefix , item -> prefix ))
245+ return 0 ;
246+
199247 /* If the match was just the prefix, we matched */
200248 if (!* match )
201249 return MATCHED_RECURSIVELY ;
202250
203- if (matchlen <= namelen && !strncmp ( match , name , matchlen )) {
251+ if (matchlen <= namelen && !ps_strncmp ( item , match , name , matchlen )) {
204252 if (matchlen == namelen )
205253 return MATCHED_EXACTLY ;
206254
@@ -241,7 +289,8 @@ int match_pathspec_depth(const struct pathspec *ps,
241289 PATHSPEC_FROMTOP |
242290 PATHSPEC_MAXDEPTH |
243291 PATHSPEC_LITERAL |
244- PATHSPEC_GLOB );
292+ PATHSPEC_GLOB |
293+ PATHSPEC_ICASE );
245294
246295 if (!ps -> nr ) {
247296 if (!ps -> recursive ||
@@ -1301,7 +1350,8 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const stru
13011350 PATHSPEC_FROMTOP |
13021351 PATHSPEC_MAXDEPTH |
13031352 PATHSPEC_LITERAL |
1304- PATHSPEC_GLOB );
1353+ PATHSPEC_GLOB |
1354+ PATHSPEC_ICASE );
13051355
13061356 if (has_symlink_leading_path (path , len ))
13071357 return dir -> nr ;
0 commit comments