Turn the flags in struct dir_struct into a single variable
[gitweb.git] / builtin-ls-files.c
index 21b0bf75f764f6fd1fe7d195ae543baffa5f4b48..d36f80b3de96c43cfc131f336850486c04444080 100644 (file)
@@ -36,42 +36,6 @@ static const char *tag_other = "";
 static const char *tag_killed = "";
 static const char *tag_modified = "";
 
-
-/*
- * Match a pathspec against a filename. The first "skiplen" characters
- * are the common prefix
- */
-int pathspec_match(const char **spec, char *ps_matched,
-                  const char *filename, int skiplen)
-{
-       const char *m;
-
-       while ((m = *spec++) != NULL) {
-               int matchlen = strlen(m + skiplen);
-
-               if (!matchlen)
-                       goto matched;
-               if (!strncmp(m + skiplen, filename + skiplen, matchlen)) {
-                       if (m[skiplen + matchlen - 1] == '/')
-                               goto matched;
-                       switch (filename[skiplen + matchlen]) {
-                       case '/': case '\0':
-                               goto matched;
-                       }
-               }
-               if (!fnmatch(m + skiplen, filename + skiplen, 0))
-                       goto matched;
-               if (ps_matched)
-                       ps_matched++;
-               continue;
-       matched:
-               if (ps_matched)
-                       *ps_matched = 1;
-               return 1;
-       }
-       return 0;
-}
-
 static void show_dir_entry(const char *tag, struct dir_entry *ent)
 {
        int len = prefix_len;
@@ -80,7 +44,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
        if (len >= ent->len)
                die("git ls-files: internal error - directory entry not superset of prefix");
 
-       if (pathspec && !pathspec_match(pathspec, ps_matched, ent->name, len))
+       if (!match_pathspec(pathspec, ent->name, ent->len, len, ps_matched))
                return;
 
        fputs(tag, stdout);
@@ -156,7 +120,7 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
        if (len >= ce_namelen(ce))
                die("git ls-files: internal error - cache entry not superset of prefix");
 
-       if (pathspec && !pathspec_match(pathspec, ps_matched, ce->name, len))
+       if (!match_pathspec(pathspec, ce->name, ce_namelen(ce), len, ps_matched))
                return;
 
        if (tag && *tag && show_valid_bit &&
@@ -210,7 +174,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
                for (i = 0; i < active_nr; i++) {
                        struct cache_entry *ce = active_cache[i];
                        int dtype = ce_to_dtype(ce);
-                       if (excluded(dir, ce->name, &dtype) != dir->show_ignored)
+                       if (excluded(dir, ce->name, &dtype) !=
+                                       !!(dir->flags & DIR_SHOW_IGNORED))
                                continue;
                        if (show_unmerged && !ce_stage(ce))
                                continue;
@@ -225,7 +190,10 @@ static void show_files(struct dir_struct *dir, const char *prefix)
                        struct stat st;
                        int err;
                        int dtype = ce_to_dtype(ce);
-                       if (excluded(dir, ce->name, &dtype) != dir->show_ignored)
+                       if (excluded(dir, ce->name, &dtype) !=
+                                       !!(dir->flags & DIR_SHOW_IGNORED))
+                               continue;
+                       if (ce->ce_flags & CE_UPDATE)
                                continue;
                        err = lstat(ce->name, &st);
                        if (show_deleted && err)
@@ -296,6 +264,21 @@ static const char *verify_pathspec(const char *prefix)
        return max ? xmemdupz(prev, max) : NULL;
 }
 
+static void strip_trailing_slash_from_submodules(void)
+{
+       const char **p;
+
+       for (p = pathspec; *p != NULL; p++) {
+               int len = strlen(*p), pos;
+
+               if (len < 1 || (*p)[len - 1] != '/')
+                       continue;
+               pos = cache_name_pos(*p, len - 1);
+               if (pos >= 0 && S_ISGITLINK(active_cache[pos]->ce_mode))
+                       *p = xstrndup(*p, len - 1);
+       }
+}
+
 /*
  * Read the tree specified with --with-tree option
  * (typically, HEAD) into stage #1 and then
@@ -451,7 +434,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
                        continue;
                }
                if (!strcmp(arg, "-i") || !strcmp(arg, "--ignored")) {
-                       dir.show_ignored = 1;
+                       dir.flags |= DIR_SHOW_IGNORED;
                        require_work_tree = 1;
                        continue;
                }
@@ -465,11 +448,11 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
                        continue;
                }
                if (!strcmp(arg, "--directory")) {
-                       dir.show_other_directories = 1;
+                       dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
                        continue;
                }
                if (!strcmp(arg, "--no-empty-directory")) {
-                       dir.hide_empty_directories = 1;
+                       dir.flags |= DIR_HIDE_EMPTY_DIRECTORIES;
                        continue;
                }
                if (!strcmp(arg, "-u") || !strcmp(arg, "--unmerged")) {
@@ -544,6 +527,11 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
 
        pathspec = get_pathspec(prefix, argv + i);
 
+       /* be nice with submodule patsh ending in a slash */
+       read_cache();
+       if (pathspec)
+               strip_trailing_slash_from_submodules();
+
        /* Verify that the pathspec matches the prefix */
        if (pathspec)
                prefix = verify_pathspec(prefix);
@@ -556,7 +544,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
                ps_matched = xcalloc(1, num);
        }
 
-       if (dir.show_ignored && !exc_given) {
+       if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given) {
                fprintf(stderr, "%s: --ignored needs some exclude pattern\n",
                        argv[0]);
                exit(1);
@@ -567,7 +555,6 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
              show_killed | show_modified))
                show_cached = 1;
 
-       read_cache();
        if (prefix)
                prune_cache(prefix);
        if (with_tree) {