if (!slash)
return 0;
+ /*
+ * The first 'prefix' characters of 'path' are common leading
+ * path components among the pathspecs we have seen so far,
+ * including the trailing slash.
+ */
prefix = slash - path + 1;
while ((next = *++pathspec) != NULL) {
- int len = strlen(next);
- if (len >= prefix && !memcmp(path, next, prefix))
+ int len, last_matching_slash = -1;
+ for (len = 0; len < prefix && next[len] == path[len]; len++)
+ if (next[len] == '/')
+ last_matching_slash = len;
+ if (len == prefix)
continue;
- len = prefix - 1;
- for (;;) {
- if (!len)
- return 0;
- if (next[--len] != '/')
- continue;
- if (memcmp(path, next, len+1))
- continue;
- prefix = len + 1;
- break;
- }
+ if (last_matching_slash < 0)
+ return 0;
+ prefix = last_matching_slash + 1;
}
return prefix;
}
enum exist_status {
index_nonexistent = 0,
index_directory,
- index_gitdir,
+ index_gitdir
};
/*
enum directory_treatment {
show_directory,
ignore_directory,
- recurse_into_directory,
+ recurse_into_directory
};
static enum directory_treatment treat_directory(struct dir_struct *dir,
return 0;
}
-static int in_pathspec(const char *path, int len, const struct path_simplify *simplify)
+/*
+ * This function tells us whether an excluded path matches a
+ * list of "interesting" pathspecs. That is, whether a path matched
+ * by any of the pathspecs could possibly be ignored by excluding
+ * the specified path. This can happen if:
+ *
+ * 1. the path is mentioned explicitly in the pathspec
+ *
+ * 2. the path is a directory prefix of some element in the
+ * pathspec
+ */
+static int exclude_matches_pathspec(const char *path, int len,
+ const struct path_simplify *simplify)
{
if (simplify) {
for (; simplify->path; simplify++) {
if (len == simplify->len
&& !memcmp(path, simplify->path, len))
return 1;
+ if (len < simplify->len
+ && simplify->path[len] == '/'
+ && !memcmp(path, simplify->path, len))
+ return 1;
}
}
return 0;
enum path_treatment {
path_ignored,
path_handled,
- path_recurse,
+ path_recurse
};
static enum path_treatment treat_one_path(struct dir_struct *dir,
{
int exclude = excluded(dir, path, &dtype);
if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
- && in_pathspec(path, *len, simplify))
+ && exclude_matches_pathspec(path, *len, simplify))
dir_add_ignored(dir, path, *len);
/*
}
if (*dir)
return NULL;
- if (*cwd == '/')
+ switch (*cwd) {
+ case '\0':
+ return cwd;
+ case '/':
return cwd + 1;
- return cwd;
+ default:
+ return NULL;
+ }
}
int is_inside_dir(const char *dir)