/* * Given a name and a list of pathspecs, returns the nature of the * closest (i.e. most specific) match of the name to any of the * pathspecs. * * The caller typically calls this multiple times with the same * pathspec and seen[] array but with different name/namelen * (e.g. entries from the index) and is interested in seeing if and * how each pathspec matches all the names it calls this function * with. A mark is left in the seen[] array for each pathspec element * indicating the closest type of match that element achieved, so if * seen[n] remains zero after multiple invocations, that means the nth * pathspec did not match any names, which could indicate that the * user mistyped the nth pathspec. */ int match_pathspec_depth(const struct pathspec *ps, const char *name, int namelen, int prefix, char *seen) { int i, retval = 0; GUARD_PATHSPEC(ps, PATHSPEC_FROMTOP | PATHSPEC_MAXDEPTH | PATHSPEC_LITERAL | PATHSPEC_GLOB | PATHSPEC_ICASE); if (!ps->nr) { if (!ps->recursive || !(ps->magic & PATHSPEC_MAXDEPTH) || ps->max_depth == -1) return MATCHED_RECURSIVELY; if (within_depth(name, namelen, 0, ps->max_depth)) return MATCHED_EXACTLY; else return 0; } name += prefix; namelen -= prefix; for (i = ps->nr - 1; i >= 0; i--) { int how; if (seen && seen[i] == MATCHED_EXACTLY) continue; how = match_pathspec_item(ps->items+i, prefix, name, namelen); if (ps->recursive && (ps->magic & PATHSPEC_MAXDEPTH) && ps->max_depth != -1 && how && how != MATCHED_FNMATCH) { int len = ps->items[i].len; if (name[len] == '/') len++; if (within_depth(name+len, namelen-len, 0, ps->max_depth)) how = MATCHED_EXACTLY; else how = 0; } if (how) { if (retval < how) retval = how; if (seen && seen[i] < how) seen[i] = how; } } return retval; }
/* * Given a name and a list of pathspecs, returns the nature of the * closest (i.e. most specific) match of the name to any of the * pathspecs. * * The caller typically calls this multiple times with the same * pathspec and seen[] array but with different name/namelen * (e.g. entries from the index) and is interested in seeing if and * how each pathspec matches all the names it calls this function * with. A mark is left in the seen[] array for each pathspec element * indicating the closest type of match that element achieved, so if * seen[n] remains zero after multiple invocations, that means the nth * pathspec did not match any names, which could indicate that the * user mistyped the nth pathspec. */ static int do_match_pathspec(const struct pathspec *ps, const char *name, int namelen, int prefix, char *seen, unsigned flags) { int i, retval = 0, exclude = flags & DO_MATCH_EXCLUDE; GUARD_PATHSPEC(ps, PATHSPEC_FROMTOP | PATHSPEC_MAXDEPTH | PATHSPEC_LITERAL | PATHSPEC_GLOB | PATHSPEC_ICASE | PATHSPEC_EXCLUDE); if (!ps->nr) { if (!ps->recursive || !(ps->magic & PATHSPEC_MAXDEPTH) || ps->max_depth == -1) return MATCHED_RECURSIVELY; if (within_depth(name, namelen, 0, ps->max_depth)) return MATCHED_EXACTLY; else return 0; } name += prefix; namelen -= prefix; for (i = ps->nr - 1; i >= 0; i--) { int how; if ((!exclude && ps->items[i].magic & PATHSPEC_EXCLUDE) || ( exclude && !(ps->items[i].magic & PATHSPEC_EXCLUDE))) continue; if (seen && seen[i] == MATCHED_EXACTLY) continue; /* * Make exclude patterns optional and never report * "pathspec ':(exclude)foo' matches no files" */ if (seen && ps->items[i].magic & PATHSPEC_EXCLUDE) seen[i] = MATCHED_FNMATCH; how = match_pathspec_item(ps->items+i, prefix, name, namelen, flags); if (ps->recursive && (ps->magic & PATHSPEC_MAXDEPTH) && ps->max_depth != -1 && how && how != MATCHED_FNMATCH) { int len = ps->items[i].len; if (name[len] == '/') len++; if (within_depth(name+len, namelen-len, 0, ps->max_depth)) how = MATCHED_EXACTLY; else how = 0; } if (how) { if (retval < how) retval = how; if (seen && seen[i] < how) seen[i] = how; } } return retval; }