Merge branch 'cb/common-prefix-unification'
authorJunio C Hamano <gitster@pobox.com>
Mon, 10 Oct 2011 22:56:17 +0000 (15:56 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 10 Oct 2011 22:56:17 +0000 (15:56 -0700)
* 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

builtin/commit.c
builtin/ls-files.c
cache.h
dir.c
dir.h
setup.c
index cbc9613ec661bc2cef8274cd66efb06b9cab55b6..b9ab5ef3146ff0536cb79dabf8c77605e4974c31 100644 (file)
@@ -255,8 +255,9 @@ static int list_paths(struct string_list *list, const char *with_tree,
        m = xcalloc(1, i);
 
        if (with_tree) {
-               const char *max_prefix = pathspec_prefix(prefix, pattern);
-               overlay_tree_on_cache(with_tree, max_prefix);
+               char *max_prefix = common_prefix(pattern);
+               overlay_tree_on_cache(with_tree, max_prefix ? max_prefix : prefix);
+               free(max_prefix);
        }
 
        for (i = 0; i < active_nr; i++) {
index e8a800d3ac42bfce328bea786d8e1efa4ff695c7..7cff175745d680d9cde24280e569b4f513d28673 100644 (file)
@@ -545,7 +545,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
                strip_trailing_slash_from_submodules();
 
        /* 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;
 
        /* Treat unmatching pathspec elements as errors */
diff --git a/cache.h b/cache.h
index c989f79835a332d879333ee8b927ede150784e54..1aa682d83dfb678f43930a4fa7d816c516d8ee1d 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -445,7 +445,6 @@ extern void set_git_work_tree(const char *tree);
 #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 
 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 const char *setup_git_directory_gently(int *);
 extern const char *setup_git_directory(void);
diff --git a/dir.c b/dir.c
index 08281d2ef74ea7790913e71f08d00299a1825765..6c0d7825799f6c35a2c1f1830767ab6203e2da92 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -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));
 }
 
-static int common_prefix(const char **pathspec)
+static 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;
+
+       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 max;
+}
 
-       path = *pathspec;
-       slash = strrchr(path, '/');
-       if (!slash)
-               return 0;
+/*
+ * 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);
 
-       /*
-        * 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 prefix;
+       return len ? xmemdupz(*pathspec, len) : NULL;
 }
 
 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 +89,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;
 }
 
diff --git a/dir.h b/dir.h
index 433b5b4cd4c51e9b7557d3056570ed46b7ceba92..dd6947e1d46098732ff1d8c3f23087c1e7163fe9 100644 (file)
--- a/dir.h
+++ b/dir.h
@@ -64,6 +64,7 @@ struct dir_struct {
 #define MATCHED_RECURSIVELY 1
 #define MATCHED_FNMATCH 2
 #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_depth(const struct pathspec *pathspec,
                                const char *name, int namelen,
diff --git a/setup.c b/setup.c
index b2b4872b700ab9776144f145dfb27d5d16dfc945..61c22e6becc1e49f1e92c916a4b8badd30a9cb2f 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -236,38 +236,6 @@ const char **get_pathspec(const char *prefix, const char **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.
  * We want to see: