consolidate pathspec_prefix and common_prefix
The implementation from pathspec_prefix (slightly modified) replaces the current common_prefix, because it also respects glob characters. Based on a patch by Clemens Buchacher. Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
5879f5684c
commit
4a085b16f4
52
dir.c
52
dir.c
@ -34,49 +34,43 @@ int fnmatch_icase(const char *pattern, const char *string, int flags)
|
||||
return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0));
|
||||
}
|
||||
|
||||
static int common_prefix(const char **pathspec)
|
||||
size_t common_prefix_len(const char **pathspec)
|
||||
{
|
||||
const char *path, *slash, *next;
|
||||
int prefix;
|
||||
const char *n, *first;
|
||||
size_t max = 0;
|
||||
|
||||
if (!pathspec)
|
||||
return 0;
|
||||
return max;
|
||||
|
||||
path = *pathspec;
|
||||
slash = strrchr(path, '/');
|
||||
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, 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;
|
||||
if (last_matching_slash < 0)
|
||||
return 0;
|
||||
prefix = last_matching_slash + 1;
|
||||
first = *pathspec;
|
||||
while ((n = *pathspec++)) {
|
||||
size_t i, len = 0;
|
||||
for (i = 0; first == n || i < max; i++) {
|
||||
char c = n[i];
|
||||
if (!c || c != first[i] || is_glob_special(c))
|
||||
break;
|
||||
if (c == '/')
|
||||
len = i + 1;
|
||||
}
|
||||
if (first == n || len < max) {
|
||||
max = len;
|
||||
if (!max)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return prefix;
|
||||
return max;
|
||||
}
|
||||
|
||||
int fill_directory(struct dir_struct *dir, const char **pathspec)
|
||||
{
|
||||
const char *path;
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
/*
|
||||
* Calculate common prefix for the pathspec, and
|
||||
* use that to optimize the directory walk
|
||||
*/
|
||||
len = common_prefix(pathspec);
|
||||
len = common_prefix_len(pathspec);
|
||||
path = "";
|
||||
|
||||
if (len)
|
||||
@ -84,6 +78,8 @@ int fill_directory(struct dir_struct *dir, const char **pathspec)
|
||||
|
||||
/* Read the directory and prune it */
|
||||
read_directory(dir, path, len, pathspec);
|
||||
if (*path)
|
||||
free((char *)path);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
1
dir.h
1
dir.h
@ -64,6 +64,7 @@ struct dir_struct {
|
||||
#define MATCHED_RECURSIVELY 1
|
||||
#define MATCHED_FNMATCH 2
|
||||
#define MATCHED_EXACTLY 3
|
||||
extern size_t common_prefix_len(const char **pathspec);
|
||||
extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
|
||||
extern int match_pathspec_depth(const struct pathspec *pathspec,
|
||||
const char *name, int namelen,
|
||||
|
29
setup.c
29
setup.c
@ -266,34 +266,9 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
|
||||
|
||||
char *pathspec_prefix(const char **pathspec)
|
||||
{
|
||||
const char **p, *n, *prev;
|
||||
unsigned long max;
|
||||
size_t len = common_prefix_len(pathspec);
|
||||
|
||||
if (!pathspec)
|
||||
return NULL;
|
||||
|
||||
prev = NULL;
|
||||
max = PATH_MAX;
|
||||
for (p = pathspec; (n = *p) != NULL; p++) {
|
||||
int i, len = 0;
|
||||
for (i = 0; i < max; i++) {
|
||||
char c = n[i];
|
||||
if (prev && prev[i] != c)
|
||||
break;
|
||||
if (!c || c == '*' || c == '?')
|
||||
break;
|
||||
if (c == '/')
|
||||
len = i+1;
|
||||
}
|
||||
prev = n;
|
||||
if (len < max) {
|
||||
max = len;
|
||||
if (!max)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return max ? xmemdupz(prev, max) : NULL;
|
||||
return len ? xmemdupz(*pathspec, len) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user