mirror of
https://git.proxmox.com/git/libgit2
synced 2025-06-24 15:59:01 +00:00
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.)
This commit is contained in:
parent
9465bedb09
commit
90997e405d
@ -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);
|
||||
}
|
||||
spec->pattern = git_pool_strndup(pool, pattern, spec->length);
|
||||
|
||||
if (!spec->pattern) {
|
||||
*base = git__next_line(pattern);
|
||||
|
Loading…
Reference in New Issue
Block a user