shell: do not play duplicated definition games to shrink the executable
[gitweb.git] / dir.c
diff --git a/dir.c b/dir.c
index a4f8c258cc49b558ce26cf35a065849fc73be1ff..109e05b01346ac13296dfbcfa2355a43d97731cd 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -17,6 +17,7 @@ struct path_simplify {
 static int read_directory_recursive(struct dir_struct *dir,
        const char *path, const char *base, int baselen,
        int check_only, const struct path_simplify *simplify);
+static int get_dtype(struct dirent *de, const char *path);
 
 int common_prefix(const char **pathspec)
 {
@@ -51,6 +52,11 @@ int common_prefix(const char **pathspec)
        return prefix;
 }
 
+static inline int special_char(unsigned char c1)
+{
+       return !c1 || c1 == '*' || c1 == '[' || c1 == '?' || c1 == '\\';
+}
+
 /*
  * Does 'match' matches the given name?
  * A match is found if
@@ -68,18 +74,31 @@ static int match_one(const char *match, const char *name, int namelen)
        int matchlen;
 
        /* If the match was just the prefix, we matched */
-       matchlen = strlen(match);
-       if (!matchlen)
+       if (!*match)
                return MATCHED_RECURSIVELY;
 
+       for (;;) {
+               unsigned char c1 = *match;
+               unsigned char c2 = *name;
+               if (special_char(c1))
+                       break;
+               if (c1 != c2)
+                       return 0;
+               match++;
+               name++;
+               namelen--;
+       }
+
+
        /*
         * If we don't match the matchstring exactly,
         * we need to match by fnmatch
         */
+       matchlen = strlen(match);
        if (strncmp(match, name, matchlen))
                return !fnmatch(match, name, 0) ? MATCHED_FNMATCH : 0;
 
-       if (!name[matchlen])
+       if (namelen == matchlen)
                return MATCHED_EXACTLY;
        if (match[matchlen-1] == '/' || name[matchlen] == '/')
                return MATCHED_RECURSIVELY;
@@ -277,7 +296,7 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
  * Return 1 for exclude, 0 for include and -1 for undecided.
  */
 static int excluded_1(const char *pathname,
-                     int pathlen, const char *basename, int dtype,
+                     int pathlen, const char *basename, int *dtype,
                      struct exclude_list *el)
 {
        int i;
@@ -288,9 +307,12 @@ static int excluded_1(const char *pathname,
                        const char *exclude = x->pattern;
                        int to_exclude = x->to_exclude;
 
-                       if ((x->flags & EXC_FLAG_MUSTBEDIR) &&
-                           (dtype != DT_DIR))
-                               continue;
+                       if (x->flags & EXC_FLAG_MUSTBEDIR) {
+                               if (*dtype == DT_UNKNOWN)
+                                       *dtype = get_dtype(NULL, pathname);
+                               if (*dtype != DT_DIR)
+                                       continue;
+                       }
 
                        if (x->flags & EXC_FLAG_NODIR) {
                                /* match basename */
@@ -334,7 +356,7 @@ static int excluded_1(const char *pathname,
        return -1; /* undecided */
 }
 
-int excluded(struct dir_struct *dir, const char *pathname, int dtype)
+int excluded(struct dir_struct *dir, const char *pathname, int *dtype_p)
 {
        int pathlen = strlen(pathname);
        int st;
@@ -344,7 +366,7 @@ int excluded(struct dir_struct *dir, const char *pathname, int dtype)
        prep_exclude(dir, pathname, basename-pathname);
        for (st = EXC_CMDL; st <= EXC_FILE; st++) {
                switch (excluded_1(pathname, pathlen, basename,
-                                  dtype, &dir->exclude_list[st])) {
+                                  dtype_p, &dir->exclude_list[st])) {
                case 0:
                        return 0;
                case 1:
@@ -367,7 +389,7 @@ static struct dir_entry *dir_entry_new(const char *pathname, int len)
 
 struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len)
 {
-       if (cache_name_pos(pathname, len) >= 0)
+       if (cache_name_exists(pathname, len, ignore_case))
                return NULL;
 
        ALLOC_GROW(dir->entries, dir->nr+1, dir->alloc);
@@ -412,7 +434,7 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
                        break;
                if (endchar == '/')
                        return index_directory;
-               if (!endchar && S_ISGITLINK(ntohl(ce->ce_mode)))
+               if (!endchar && S_ISGITLINK(ce->ce_mode))
                        return index_gitdir;
        }
        return index_nonexistent;
@@ -529,7 +551,7 @@ static int in_pathspec(const char *path, int len, const struct path_simplify *si
 
 static int get_dtype(struct dirent *de, const char *path)
 {
-       int dtype = DTYPE(de);
+       int dtype = de ? DTYPE(de) : DT_UNKNOWN;
        struct stat st;
 
        if (dtype != DT_UNKNOWN)
@@ -581,8 +603,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
                        if (simplify_away(fullname, baselen + len, simplify))
                                continue;
 
-                       dtype = get_dtype(de, fullname);
-                       exclude = excluded(dir, fullname, dtype);
+                       dtype = DTYPE(de);
+                       exclude = excluded(dir, fullname, &dtype);
                        if (exclude && dir->collect_ignored
                            && in_pathspec(fullname, baselen + len, simplify))
                                dir_add_ignored(dir, fullname, baselen + len);
@@ -594,6 +616,9 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
                        if (exclude && !dir->show_ignored)
                                continue;
 
+                       if (dtype == DT_UNKNOWN)
+                               dtype = get_dtype(de, fullname);
+
                        /*
                         * Do we want to see just the ignored files?
                         * We still need to recurse into directories,
@@ -697,8 +722,7 @@ static struct path_simplify *create_simplify(const char **pathspec)
 
 static void free_simplify(struct path_simplify *simplify)
 {
-       if (simplify)
-               free(simplify);
+       free(simplify);
 }
 
 int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen, const char **pathspec)