115
const char *setto;
116
};
117
118
+struct pattern {
119
+ const char *pattern;
120
+ int patternlen;
121
+ int nowildcardlen;
122
+ int flags; /* EXC_FLAG_* */
123
+};
124
+
125
/*
126
* One rule, as from a .gitattributes file.
127
*
138
*/
139
struct match_attr {
140
union {
134
- char *pattern;
141
+ struct pattern pat;
142
struct git_attr *attr;
143
} u;
144
char is_macro;
248
if (is_macro)
249
res->u.attr = git_attr_internal(name, namelen);
250
else {
244
- res->u.pattern = (char *)&(res->state[num_attr]);
245
- memcpy(res->u.pattern, name, namelen);
246
- res->u.pattern[namelen] = 0;
251
+ char *p = (char *)&(res->state[num_attr]);
252
+ memcpy(p, name, namelen);
253
+ res->u.pat.pattern = p;
254
+ parse_exclude_pattern(&res->u.pat.pattern,
255
+ &res->u.pat.patternlen,
256
+ &res->u.pat.flags,
257
+ &res->u.pat.nowildcardlen);
258
+ if (res->u.pat.flags & EXC_FLAG_NEGATIVE)
259
+ die(_("Negative patterns are forbidden in git attributes\n"
260
+ "Use '\\!' for literal leading exclamation."));
261
}
262
res->is_macro = is_macro;
263
res->num_attr = num_attr;
654
655
static int path_matches(const char *pathname, int pathlen,
656
const char *basename,
643
- const char *pattern,
657
+ const struct pattern *pat,
658
const char *base, int baselen)
659
{
646
- if (!strchr(pattern, '/')) {
647
- return (fnmatch_icase(pattern, basename, 0) == 0);
660
+ const char *pattern = pat->pattern;
661
+ int prefix = pat->nowildcardlen;
662
+
663
+ if (pat->flags & EXC_FLAG_NODIR) {
664
+ return match_basename(basename,
665
+ pathlen - (basename - pathname),
666
+ pattern, prefix,
667
+ pat->patternlen, pat->flags);
668
}
649
- /*
650
- * match with FNM_PATHNAME; the pattern has base implicitly
651
- * in front of it.
652
- */
653
- if (*pattern == '/')
654
- pattern++;
655
- if (pathlen < baselen ||
656
- (baselen && pathname[baselen] != '/') ||
657
- strncmp(pathname, base, baselen))
658
- return 0;
659
- if (baselen != 0)
660
- baselen++;
661
- return fnmatch_icase(pattern, pathname + baselen, FNM_PATHNAME) == 0;
669
+ return match_pathname(pathname, pathlen,
670
+ base, baselen,
671
+ pattern, prefix, pat->patternlen, pat->flags);
672
}
673
674
static int macroexpand_one(int attr_nr, int rem);
706
if (a->is_macro)
707
continue;
708
if (path_matches(path, pathlen, basename,
699
- a->u.pattern, base, stk->originlen))
709
+ &a->u.pat, base, stk->originlen))
710
rem = fill_one("fill", a, rem);
711
}
712
return rem;