Skip to content

Commit 61cf282

Browse files
pcloudsgitster
authored andcommitted
pathspec: add match_pathspec_depth()
match_pathspec_depth() is a clone of match_pathspec() except that it can take depth limit. Computation is a bit lighter compared to match_pathspec() because it's usually precomputed and stored in struct pathspec. In long term, match_pathspec() and match_one() should be removed in favor of this function. Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f1a2ddb commit 61cf282

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

dir.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,95 @@ int match_pathspec(const char **pathspec, const char *name, int namelen,
199199
return retval;
200200
}
201201

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+
202291
static int no_wildcard(const char *string)
203292
{
204293
return string[strcspn(string, "*?[{\\")] == '\0';

dir.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ struct dir_struct {
6565
#define MATCHED_FNMATCH 2
6666
#define MATCHED_EXACTLY 3
6767
extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
68+
extern int match_pathspec_depth(const struct pathspec *pathspec,
69+
const char *name, int namelen,
70+
int prefix, char *seen);
6871
extern int within_depth(const char *name, int namelen, int depth, int max_depth);
6972

7073
extern int fill_directory(struct dir_struct *dir, const char **pathspec);

0 commit comments

Comments
 (0)