@@ -199,6 +199,95 @@ int match_pathspec(const char **pathspec, const char *name, int namelen,
199
199
return retval ;
200
200
}
201
201
202
+ /*
203
+ * Does 'match' match the given name?
204
+ * A match is found if
205
+ *
206
+ * (1) the 'match' string is leading directory of 'name', or
207
+ * (2) the 'match' string is a wildcard and matches 'name', or
208
+ * (3) the 'match' string is exactly the same as 'name'.
209
+ *
210
+ * and the return value tells which case it was.
211
+ *
212
+ * It returns 0 when there is no match.
213
+ */
214
+ static int match_pathspec_item (const struct pathspec_item * item , int prefix ,
215
+ const char * name , int namelen )
216
+ {
217
+ /* name/namelen has prefix cut off by caller */
218
+ const char * match = item -> match + prefix ;
219
+ int matchlen = item -> len - prefix ;
220
+
221
+ /* If the match was just the prefix, we matched */
222
+ if (!* match )
223
+ return MATCHED_RECURSIVELY ;
224
+
225
+ if (matchlen <= namelen && !strncmp (match , name , matchlen )) {
226
+ if (matchlen == namelen )
227
+ return MATCHED_EXACTLY ;
228
+
229
+ if (match [matchlen - 1 ] == '/' || name [matchlen ] == '/' )
230
+ return MATCHED_RECURSIVELY ;
231
+ }
232
+
233
+ if (item -> has_wildcard && !fnmatch (match , name , 0 ))
234
+ return MATCHED_FNMATCH ;
235
+
236
+ return 0 ;
237
+ }
238
+
239
+ /*
240
+ * Given a name and a list of pathspecs, see if the name matches
241
+ * any of the pathspecs. The caller is also interested in seeing
242
+ * all pathspec matches some names it calls this function with
243
+ * (otherwise the user could have mistyped the unmatched pathspec),
244
+ * and a mark is left in seen[] array for pathspec element that
245
+ * actually matched anything.
246
+ */
247
+ int match_pathspec_depth (const struct pathspec * ps ,
248
+ const char * name , int namelen ,
249
+ int prefix , char * seen )
250
+ {
251
+ int i , retval = 0 ;
252
+
253
+ if (!ps -> nr ) {
254
+ if (!ps -> recursive || ps -> max_depth == -1 )
255
+ return MATCHED_RECURSIVELY ;
256
+
257
+ if (within_depth (name , namelen , 0 , ps -> max_depth ))
258
+ return MATCHED_EXACTLY ;
259
+ else
260
+ return 0 ;
261
+ }
262
+
263
+ name += prefix ;
264
+ namelen -= prefix ;
265
+
266
+ for (i = ps -> nr - 1 ; i >= 0 ; i -- ) {
267
+ int how ;
268
+ if (seen && seen [i ] == MATCHED_EXACTLY )
269
+ continue ;
270
+ how = match_pathspec_item (ps -> items + i , prefix , name , namelen );
271
+ if (ps -> recursive && ps -> max_depth != -1 &&
272
+ how && how != MATCHED_FNMATCH ) {
273
+ int len = ps -> items [i ].len ;
274
+ if (name [len ] == '/' )
275
+ len ++ ;
276
+ if (within_depth (name + len , namelen - len , 0 , ps -> max_depth ))
277
+ how = MATCHED_EXACTLY ;
278
+ else
279
+ how = 0 ;
280
+ }
281
+ if (how ) {
282
+ if (retval < how )
283
+ retval = how ;
284
+ if (seen && seen [i ] < how )
285
+ seen [i ] = how ;
286
+ }
287
+ }
288
+ return retval ;
289
+ }
290
+
202
291
static int no_wildcard (const char * string )
203
292
{
204
293
return string [strcspn (string , "*?[{\\" )] == '\0' ;
0 commit comments