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));
|
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;
|
const char *n, *first;
|
||||||
int prefix;
|
size_t max = 0;
|
||||||
|
|
||||||
if (!pathspec)
|
if (!pathspec)
|
||||||
return 0;
|
return max;
|
||||||
|
|
||||||
path = *pathspec;
|
first = *pathspec;
|
||||||
slash = strrchr(path, '/');
|
while ((n = *pathspec++)) {
|
||||||
if (!slash)
|
size_t i, len = 0;
|
||||||
return 0;
|
for (i = 0; first == n || i < max; i++) {
|
||||||
|
char c = n[i];
|
||||||
/*
|
if (!c || c != first[i] || is_glob_special(c))
|
||||||
* The first 'prefix' characters of 'path' are common leading
|
break;
|
||||||
* path components among the pathspecs we have seen so far,
|
if (c == '/')
|
||||||
* including the trailing slash.
|
len = i + 1;
|
||||||
*/
|
}
|
||||||
prefix = slash - path + 1;
|
if (first == n || len < max) {
|
||||||
while ((next = *++pathspec) != NULL) {
|
max = len;
|
||||||
int len, last_matching_slash = -1;
|
if (!max)
|
||||||
for (len = 0; len < prefix && next[len] == path[len]; len++)
|
break;
|
||||||
if (next[len] == '/')
|
}
|
||||||
last_matching_slash = len;
|
|
||||||
if (len == prefix)
|
|
||||||
continue;
|
|
||||||
if (last_matching_slash < 0)
|
|
||||||
return 0;
|
|
||||||
prefix = last_matching_slash + 1;
|
|
||||||
}
|
}
|
||||||
return prefix;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fill_directory(struct dir_struct *dir, const char **pathspec)
|
int fill_directory(struct dir_struct *dir, const char **pathspec)
|
||||||
{
|
{
|
||||||
const char *path;
|
const char *path;
|
||||||
int len;
|
size_t len;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate common prefix for the pathspec, and
|
* Calculate common prefix for the pathspec, and
|
||||||
* use that to optimize the directory walk
|
* use that to optimize the directory walk
|
||||||
*/
|
*/
|
||||||
len = common_prefix(pathspec);
|
len = common_prefix_len(pathspec);
|
||||||
path = "";
|
path = "";
|
||||||
|
|
||||||
if (len)
|
if (len)
|
||||||
@ -84,6 +78,8 @@ int fill_directory(struct dir_struct *dir, const char **pathspec)
|
|||||||
|
|
||||||
/* Read the directory and prune it */
|
/* Read the directory and prune it */
|
||||||
read_directory(dir, path, len, pathspec);
|
read_directory(dir, path, len, pathspec);
|
||||||
|
if (*path)
|
||||||
|
free((char *)path);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
dir.h
1
dir.h
@ -64,6 +64,7 @@ struct dir_struct {
|
|||||||
#define MATCHED_RECURSIVELY 1
|
#define MATCHED_RECURSIVELY 1
|
||||||
#define MATCHED_FNMATCH 2
|
#define MATCHED_FNMATCH 2
|
||||||
#define MATCHED_EXACTLY 3
|
#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(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
|
||||||
extern int match_pathspec_depth(const struct pathspec *pathspec,
|
extern int match_pathspec_depth(const struct pathspec *pathspec,
|
||||||
const char *name, int namelen,
|
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)
|
char *pathspec_prefix(const char **pathspec)
|
||||||
{
|
{
|
||||||
const char **p, *n, *prev;
|
size_t len = common_prefix_len(pathspec);
|
||||||
unsigned long max;
|
|
||||||
|
|
||||||
if (!pathspec)
|
return len ? xmemdupz(*pathspec, len) : NULL;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user