Skip to content

Commit

Permalink
consolidate pathspec_prefix and common_prefix
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
gitster committed Sep 6, 2011
1 parent 5879f56 commit 4a085b1
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 56 deletions.
54 changes: 25 additions & 29 deletions dir.c
Expand Up @@ -34,56 +34,52 @@ 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;

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;
return max;

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)
path = xmemdupz(*pathspec, len);

/* Read the directory and prune it */
read_directory(dir, path, len, pathspec);
if (*path)
free((char *)path);
return len;
}

Expand Down
1 change: 1 addition & 0 deletions dir.h
Expand Up @@ -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,
Expand Down
29 changes: 2 additions & 27 deletions setup.c
Expand Up @@ -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;
}

/*
Expand Down

0 comments on commit 4a085b1

Please sign in to comment.