Commit 90997e40 by Edward Thomson

attr: less path mangling during attribute matching

When handling attr matching, simply compare the directory path where the
attribute file resides to the path being matched.  Skip over commonality
to allow us to compare the contents of the attribute file to the remainder
of the path.

This allows us to more easily compare the pattern directly to the path,
instead of trying to guess whether we want to compare the path's basename
or the full path based on whether the match was inside a containing
directory or not.

This also allows us to do fewer translations on the pattern (trying to
re-prefix it.)
parent 9465bedb
......@@ -359,6 +359,7 @@ bool git_attr_fnmatch__match(
git_attr_fnmatch *match,
git_attr_path *path)
{
const char *relpath = path->path;
const char *filename;
int flags = 0;
......@@ -375,6 +376,8 @@ bool git_attr_fnmatch__match(
if (git__prefixcmp(path->path, match->containing_dir))
return 0;
}
relpath += match->containing_dir_length;
}
if (match->flags & GIT_ATTR_FNMATCH_ICASE)
......@@ -383,7 +386,7 @@ bool git_attr_fnmatch__match(
flags |= FNM_LEADING_DIR;
if (match->flags & GIT_ATTR_FNMATCH_FULLPATH) {
filename = path->path;
filename = relpath;
flags |= FNM_PATHNAME;
} else {
filename = path->basename;
......@@ -393,9 +396,6 @@ bool git_attr_fnmatch__match(
}
if ((match->flags & GIT_ATTR_FNMATCH_DIRECTORY) && !path->is_dir) {
int matchval;
char *matchpath;
/* for attribute checks or root ignore checks, fail match */
if (!(match->flags & GIT_ATTR_FNMATCH_IGNORE) ||
path->basename == path->path)
......@@ -403,32 +403,24 @@ bool git_attr_fnmatch__match(
flags |= FNM_LEADING_DIR;
/* for ignore checks, use container of current item for check */
if (match->containing_dir)
matchpath = path->basename;
else
matchpath = path->path;
/* fail match if this is a file with same name as ignored folder */
bool samename = (match->flags & GIT_ATTR_FNMATCH_ICASE) ?
!strcasecmp(match->pattern, matchpath) :
!strcmp(match->pattern, matchpath);
!strcasecmp(match->pattern, relpath) :
!strcmp(match->pattern, relpath);
if (samename)
return false;
matchval = p_fnmatch(match->pattern, matchpath, flags);
return (matchval != FNM_NOMATCH);
return (p_fnmatch(match->pattern, relpath, flags) != FNM_NOMATCH);
}
/* if path is a directory prefix of a negated pattern, then match */
if ((match->flags & GIT_ATTR_FNMATCH_NEGATIVE) && path->is_dir) {
size_t pathlen = strlen(path->path);
size_t pathlen = strlen(relpath);
bool prefixed = (pathlen <= match->length) &&
((match->flags & GIT_ATTR_FNMATCH_ICASE) ?
!strncasecmp(match->pattern, path->path, pathlen) :
!strncmp(match->pattern, path->path, pathlen));
!strncasecmp(match->pattern, relpath, pathlen) :
!strncmp(match->pattern, relpath, pathlen));
if (prefixed && git_path_at_end_of_segment(&match->pattern[pathlen]))
return true;
......@@ -647,7 +639,7 @@ int git_attr_fnmatch__parse(
}
if (context) {
char *slash = strchr(context, '/');
char *slash = strrchr(context, '/');
size_t len;
if (slash) {
/* include the slash for easier matching */
......@@ -657,27 +649,7 @@ int git_attr_fnmatch__parse(
}
}
if ((spec->flags & GIT_ATTR_FNMATCH_FULLPATH) != 0 &&
context != NULL && git_path_root(pattern) < 0)
{
/* use context path minus the trailing filename */
char *slash = strrchr(context, '/');
size_t contextlen = slash ? slash - context + 1 : 0;
/* given an unrooted fullpath match from a file inside a repo,
* prefix the pattern with the relative directory of the source file
*/
spec->pattern = git_pool_malloc(
pool, (uint32_t)(contextlen + spec->length + 1));
if (spec->pattern) {
memcpy(spec->pattern, context, contextlen);
memcpy(spec->pattern + contextlen, pattern, spec->length);
spec->length += contextlen;
spec->pattern[spec->length] = '\0';
}
} else {
spec->pattern = git_pool_strndup(pool, pattern, spec->length);
}
if (!spec->pattern) {
*base = git__next_line(pattern);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment