Merge branch 'cb/common-prefix-unification' into next

* cb/common-prefix-unification:
  rename pathspec_prefix() to common_prefix() and move to dir.[ch]
  consolidate pathspec_prefix and common_prefix
  remove prefix argument from pathspec_prefix
This commit is contained in:
Junio C Hamano 2011-10-06 15:41:51 -07:00
commit 8349bca15d
6 changed files with 40 additions and 64 deletions

View file

@ -255,8 +255,9 @@ static int list_paths(struct string_list *list, const char *with_tree,
m = xcalloc(1, i); m = xcalloc(1, i);
if (with_tree) { if (with_tree) {
const char *max_prefix = pathspec_prefix(prefix, pattern); char *max_prefix = common_prefix(pattern);
overlay_tree_on_cache(with_tree, max_prefix); overlay_tree_on_cache(with_tree, max_prefix ? max_prefix : prefix);
free(max_prefix);
} }
for (i = 0; i < active_nr; i++) { for (i = 0; i < active_nr; i++) {

View file

@ -545,7 +545,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
strip_trailing_slash_from_submodules(); strip_trailing_slash_from_submodules();
/* Find common prefix for all pathspec's */ /* Find common prefix for all pathspec's */
max_prefix = pathspec_prefix(prefix, pathspec); max_prefix = common_prefix(pathspec);
max_prefix_len = max_prefix ? strlen(max_prefix) : 0; max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
/* Treat unmatching pathspec elements as errors */ /* Treat unmatching pathspec elements as errors */

View file

@ -445,7 +445,6 @@ extern void set_git_work_tree(const char *tree);
#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES" #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
extern const char **get_pathspec(const char *prefix, const char **pathspec); extern const char **get_pathspec(const char *prefix, const char **pathspec);
extern const char *pathspec_prefix(const char *prefix, const char **pathspec);
extern void setup_work_tree(void); extern void setup_work_tree(void);
extern const char *setup_git_directory_gently(int *); extern const char *setup_git_directory_gently(int *);
extern const char *setup_git_directory(void); extern const char *setup_git_directory(void);

63
dir.c
View file

@ -34,49 +34,54 @@ 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) static 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;
}
/*
* Returns a copy of the longest leading path common among all
* pathspecs.
*/
char *common_prefix(const char **pathspec)
{
unsigned long len = common_prefix_len(pathspec);
return len ? xmemdupz(*pathspec, len) : NULL;
} }
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 +89,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
View file

@ -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 char *common_prefix(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,

32
setup.c
View file

@ -236,38 +236,6 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
return pathspec; return pathspec;
} }
const char *pathspec_prefix(const char *prefix, const char **pathspec)
{
const char **p, *n, *prev;
unsigned long max;
if (!pathspec)
return prefix ? xmemdupz(prefix, strlen(prefix)) : 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;
}
/* /*
* Test if it looks like we're at a git directory. * Test if it looks like we're at a git directory.
* We want to see: * We want to see: