* do_match_pathspec() is meant to ONLY be called by * match_pathspec_with_flags(); calling it directly risks pathspecs * like ':!unwanted_path' being ignored. * * 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[] a
| 511 | * user mistyped the nth pathspec. |
| 512 | */ |
| 513 | static int do_match_pathspec(struct index_state *istate, |
| 514 | const struct pathspec *ps, |
| 515 | const char *name, int namelen, |
| 516 | int prefix, char *seen, |
| 517 | unsigned flags) |
| 518 | { |
| 519 | int i, retval = 0, exclude = flags & DO_MATCH_EXCLUDE; |
| 520 | |
| 521 | GUARD_PATHSPEC(ps, |
| 522 | PATHSPEC_FROMTOP | |
| 523 | PATHSPEC_MAXDEPTH | |
| 524 | PATHSPEC_LITERAL | |
| 525 | PATHSPEC_GLOB | |
| 526 | PATHSPEC_ICASE | |
| 527 | PATHSPEC_EXCLUDE | |
| 528 | PATHSPEC_ATTR); |
| 529 | |
| 530 | if (!ps->nr) { |
| 531 | if (!ps->recursive || |
| 532 | !(ps->magic & PATHSPEC_MAXDEPTH) || |
| 533 | ps->max_depth == -1) |
| 534 | return MATCHED_RECURSIVELY; |
| 535 | |
| 536 | if (within_depth(name, namelen, 0, ps->max_depth)) |
| 537 | return MATCHED_EXACTLY; |
| 538 | else |
| 539 | return 0; |
| 540 | } |
| 541 | |
| 542 | name += prefix; |
| 543 | namelen -= prefix; |
| 544 | |
| 545 | for (i = ps->nr - 1; i >= 0; i--) { |
| 546 | int how; |
| 547 | |
| 548 | if ((!exclude && ps->items[i].magic & PATHSPEC_EXCLUDE) || |
| 549 | ( exclude && !(ps->items[i].magic & PATHSPEC_EXCLUDE))) |
| 550 | continue; |
| 551 | |
| 552 | if (seen && seen[i] == MATCHED_EXACTLY && |
| 553 | ps->items[i].nowildcard_len == ps->items[i].len) |
| 554 | continue; |
| 555 | /* |
| 556 | * Make exclude patterns optional and never report |
| 557 | * "pathspec ':(exclude)foo' matches no files" |
| 558 | */ |
| 559 | if (seen && ps->items[i].magic & PATHSPEC_EXCLUDE) |
| 560 | seen[i] = MATCHED_FNMATCH; |
| 561 | how = match_pathspec_item(istate, ps->items+i, prefix, name, |
| 562 | namelen, flags); |
| 563 | if (ps->recursive && |
| 564 | (ps->magic & PATHSPEC_MAXDEPTH) && |
| 565 | ps->max_depth != -1 && |
| 566 | how && how != MATCHED_FNMATCH) { |
| 567 | int len = ps->items[i].len; |
| 568 | if (name[len] == '/') |
| 569 | len++; |
| 570 | if (within_depth(name+len, namelen-len, 0, ps->max_depth)) |
no test coverage detected