summaryrefslogtreecommitdiff
path: root/src/attr_file.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2012-04-26 10:51:45 -0700
committerRussell Belfer <rb@github.com>2012-04-26 10:51:45 -0700
commitd58336dda873704f8d12a8b78c3191deefa4ec14 (patch)
tree84137abc698a572015d41975ced985fc0bd77e61 /src/attr_file.c
parenteb3d71a5bcd78cb4840e62194e8998141508af88 (diff)
downloadlibgit2-d58336dda873704f8d12a8b78c3191deefa4ec14.tar.gz
Fix leading slash behavior in attrs/ignores
We were not following the git behavior for leading slashes in path names when matching git ignores and git attribute file patterns. This should fix issue #638.
Diffstat (limited to 'src/attr_file.c')
-rw-r--r--src/attr_file.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/src/attr_file.c b/src/attr_file.c
index e34053fc3..650b58fcc 100644
--- a/src/attr_file.c
+++ b/src/attr_file.c
@@ -251,27 +251,50 @@ git_attr_assignment *git_attr_rule__lookup_assignment(
int git_attr_path__init(
git_attr_path *info, const char *path, const char *base)
{
- assert(info && path);
- info->path = path;
- info->basename = strrchr(path, '/');
- if (info->basename)
- info->basename++;
- if (!info->basename || !*info->basename)
- info->basename = path;
+ /* build full path as best we can */
+ git_buf_init(&info->full, 0);
if (base != NULL && git_path_root(path) < 0) {
- git_buf full_path = GIT_BUF_INIT;
- if (git_buf_joinpath(&full_path, base, path) < 0)
+ if (git_buf_joinpath(&info->full, base, path) < 0)
+ return -1;
+ info->path = info->full.ptr + strlen(base);
+ } else {
+ if (git_buf_sets(&info->full, path) < 0)
return -1;
- info->is_dir = (int)git_path_isdir(full_path.ptr);
- git_buf_free(&full_path);
- return 0;
+ info->path = info->full.ptr;
}
- info->is_dir = (int)git_path_isdir(path);
+
+ /* remove trailing slashes */
+ while (info->full.size > 0) {
+ if (info->full.ptr[info->full.size - 1] != '/')
+ break;
+ info->full.size--;
+ }
+ info->full.ptr[info->full.size] = '\0';
+
+ /* skip leading slashes in path */
+ while (*info->path == '/')
+ info->path++;
+
+ /* find trailing basename component */
+ info->basename = strrchr(info->path, '/');
+ if (info->basename)
+ info->basename++;
+ if (!info->basename || !*info->basename)
+ info->basename = info->path;
+
+ info->is_dir = (int)git_path_isdir(info->full.ptr);
return 0;
}
+void git_attr_path__free(git_attr_path *info)
+{
+ git_buf_free(&info->full);
+ info->path = NULL;
+ info->basename = NULL;
+}
+
/*
* From gitattributes(5):
@@ -353,6 +376,8 @@ int git_attr_fnmatch__parse(
if (*scan == '/') {
spec->flags = spec->flags | GIT_ATTR_FNMATCH_FULLPATH;
slash_count++;
+ if (pattern == scan)
+ pattern++;
}
/* remember if we see an unescaped wildcard in pattern */
else if ((*scan == '*' || *scan == '.' || *scan == '[') &&