int match_pathname(const char *pathname, int pathlen, const char *base, int baselen, const char *pattern, int prefix, int patternlen, int flags) { const char *name; int namelen; /* * match with FNM_PATHNAME; the pattern has base implicitly * in front of it. */ if (*pattern == '/') { pattern++; patternlen--; prefix--; } /* * baselen does not count the trailing slash. base[] may or * may not end with a trailing slash though. */ if (pathlen < baselen + 1 || (baselen && pathname[baselen] != '/') || strncmp_icase(pathname, base, baselen)) return 0; namelen = baselen ? pathlen - baselen - 1 : pathlen; name = pathname + pathlen - namelen; if (prefix) { /* * if the non-wildcard part is longer than the * remaining pathname, surely it cannot match. */ if (prefix > namelen) return 0; if (strncmp_icase(pattern, name, prefix)) return 0; pattern += prefix; patternlen -= prefix; name += prefix; namelen -= prefix; /* * If the whole pattern did not have a wildcard, * then our prefix match is all we need; we * do not need to call fnmatch at all. */ if (!patternlen && !namelen) return 1; } return fnmatch_icase_mem(pattern, patternlen, name, namelen, WM_PATHNAME) == 0; }
/* Scan the list and let the last match determine the fate. * Return 1 for exclude, 0 for include and -1 for undecided. */ int excluded_from_list(const char *pathname, int pathlen, const char *basename, int *dtype, struct exclude_list *el) { int i; if (el->nr) { for (i = el->nr - 1; 0 <= i; i--) { struct exclude *x = el->excludes[i]; const char *exclude = x->pattern; int to_exclude = x->to_exclude; if (x->flags & EXC_FLAG_MUSTBEDIR) { if (*dtype == DT_UNKNOWN) *dtype = get_dtype(NULL, pathname, pathlen); if (*dtype != DT_DIR) continue; } if (x->flags & EXC_FLAG_NODIR) { /* match basename */ if (x->flags & EXC_FLAG_NOWILDCARD) { if (!strcmp_icase(exclude, basename)) return to_exclude; } else if (x->flags & EXC_FLAG_ENDSWITH) { if (x->patternlen - 1 <= pathlen && !strcmp_icase(exclude + 1, pathname + pathlen - x->patternlen + 1)) return to_exclude; } else { if (fnmatch_icase(exclude, basename, 0) == 0) return to_exclude; } } else { /* match with FNM_PATHNAME: * exclude has base (baselen long) implicitly * in front of it. */ int baselen = x->baselen; if (*exclude == '/') exclude++; if (pathlen < baselen || (baselen && pathname[baselen-1] != '/') || strncmp_icase(pathname, x->base, baselen)) continue; if (x->flags & EXC_FLAG_NOWILDCARD) { if (!strcmp_icase(exclude, pathname + baselen)) return to_exclude; } else { if (fnmatch_icase(exclude, pathname+baselen, FNM_PATHNAME) == 0) return to_exclude; } } } } return -1; /* undecided */ }
/* * Does 'match' match the given name? * A match is found if * * (1) the 'match' string is leading directory of 'name', or * (2) the 'match' string is a wildcard and matches 'name', or * (3) the 'match' string is exactly the same as 'name'. * * and the return value tells which case it was. * * It returns 0 when there is no match. */ static int match_one(const char *match, const char *name, int namelen) { int matchlen; int literal = limit_pathspec_to_literal(); /* If the match was just the prefix, we matched */ if (!*match) return MATCHED_RECURSIVELY; if (ignore_case) { for (;;) { unsigned char c1 = tolower(*match); unsigned char c2 = tolower(*name); if (c1 == '\0' || (!literal && is_glob_special(c1))) break; if (c1 != c2) return 0; match++; name++; namelen--; } } else { for (;;) { unsigned char c1 = *match; unsigned char c2 = *name; if (c1 == '\0' || (!literal && is_glob_special(c1))) break; if (c1 != c2) return 0; match++; name++; namelen--; } } /* * If we don't match the matchstring exactly, * we need to match by fnmatch */ matchlen = strlen(match); if (strncmp_icase(match, name, matchlen)) { if (literal) return 0; return !fnmatch_icase(match, name, 0) ? MATCHED_FNMATCH : 0; } if (namelen == matchlen) return MATCHED_EXACTLY; if (match[matchlen-1] == '/' || name[matchlen] == '/') return MATCHED_RECURSIVELY; return 0; }
static void update_callback(struct diff_queue_struct *q, struct diff_options *opt, void *cbdata) { int i; struct update_callback_data *data = cbdata; const char *implicit_dot = data->implicit_dot; size_t implicit_dot_len = data->implicit_dot_len; for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; const char *path = p->one->path; /* * Check if "git add -A" or "git add -u" was run from a * subdirectory with a modified file outside that directory, * and warn if so. * * "git add -u" will behave like "git add -u :/" instead of * "git add -u ." in the future. This warning prepares for * that change. */ if (implicit_dot && strncmp_icase(path, implicit_dot, implicit_dot_len)) { warn_pathless_add(); continue; } switch (fix_unmerged_status(p, data)) { default: die(_("unexpected diff status %c"), p->status); case DIFF_STATUS_MODIFIED: case DIFF_STATUS_TYPE_CHANGED: if (add_file_to_index(&the_index, path, data->flags)) { if (!(data->flags & ADD_CACHE_IGNORE_ERRORS)) die(_("updating files failed")); data->add_errors++; } break; case DIFF_STATUS_DELETED: if (data->warn_add_would_remove) { warn_add_would_remove(path); data->warn_add_would_remove = 0; } if (data->flags & ADD_CACHE_IGNORE_REMOVAL) break; if (!(data->flags & ADD_CACHE_PRETEND)) remove_file_from_index(&the_index, path); if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE)) printf(_("remove '%s'\n"), path); break; } } }
int match_basename(const char *basename, int basenamelen, const char *pattern, int prefix, int patternlen, int flags) { if (prefix == patternlen) { if (patternlen == basenamelen && !strncmp_icase(pattern, basename, basenamelen)) return 1; } else if (flags & EXC_FLAG_ENDSWITH) { /* "*literal" matching against "fooliteral" */ if (patternlen - 1 <= basenamelen && !strncmp_icase(pattern + 1, basename + basenamelen - (patternlen - 1), patternlen - 1)) return 1; } else { if (fnmatch_icase_mem(pattern, patternlen, basename, basenamelen, 0) == 0) return 1; } return 0; }