match-trees: drop unused path parameter from score functions
[gitweb.git] / tree-walk.c
index 8f5090862b5193db135f18854974b21e75eb8ae4..08210a4109c70364e630290a24478333aeee449a 100644 (file)
@@ -2,6 +2,7 @@
 #include "tree-walk.h"
 #include "unpack-trees.h"
 #include "dir.h"
+#include "object-store.h"
 #include "tree.h"
 #include "pathspec.h"
 
@@ -26,8 +27,9 @@ static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned l
 {
        const char *path;
        unsigned int mode, len;
+       const unsigned hashsz = the_hash_algo->rawsz;
 
-       if (size < 23 || buf[size - 21]) {
+       if (size < hashsz + 3 || buf[size - (hashsz + 1)]) {
                strbuf_addstr(err, _("too-short tree object"));
                return -1;
        }
@@ -363,7 +365,8 @@ static void free_extended_entry(struct tree_desc_x *t)
        }
 }
 
-static inline int prune_traversal(struct name_entry *e,
+static inline int prune_traversal(struct index_state *istate,
+                                 struct name_entry *e,
                                  struct traverse_info *info,
                                  struct strbuf *base,
                                  int still_interesting)
@@ -372,10 +375,13 @@ static inline int prune_traversal(struct name_entry *e,
                return 2;
        if (still_interesting < 0)
                return still_interesting;
-       return tree_entry_interesting(e, base, 0, info->pathspec);
+       return tree_entry_interesting(istate, e, base,
+                                     0, info->pathspec);
 }
 
-int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
+int traverse_trees(struct index_state *istate,
+                  int n, struct tree_desc *t,
+                  struct traverse_info *info)
 {
        int error = 0;
        struct name_entry *entry = xmalloc(n*sizeof(*entry));
@@ -459,7 +465,7 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
                }
                if (!mask)
                        break;
-               interesting = prune_traversal(e, info, &base, interesting);
+               interesting = prune_traversal(istate, e, info, &base, interesting);
                if (interesting < 0)
                        break;
                if (interesting) {
@@ -926,7 +932,8 @@ static int match_wildcard_base(const struct pathspec_item *item,
  * Pre-condition: either baselen == base_offset (i.e. empty path)
  * or base[baselen-1] == '/' (i.e. with trailing slash).
  */
-static enum interesting do_match(const struct name_entry *entry,
+static enum interesting do_match(struct index_state *istate,
+                                const struct name_entry *entry,
                                 struct strbuf *base, int base_offset,
                                 const struct pathspec *ps,
                                 int exclude)
@@ -942,7 +949,8 @@ static enum interesting do_match(const struct name_entry *entry,
                       PATHSPEC_LITERAL |
                       PATHSPEC_GLOB |
                       PATHSPEC_ICASE |
-                      PATHSPEC_EXCLUDE);
+                      PATHSPEC_EXCLUDE |
+                      PATHSPEC_ATTR);
 
        if (!ps->nr) {
                if (!ps->recursive ||
@@ -974,14 +982,20 @@ static enum interesting do_match(const struct name_entry *entry,
 
                        if (!ps->recursive ||
                            !(ps->magic & PATHSPEC_MAXDEPTH) ||
-                           ps->max_depth == -1)
-                               return all_entries_interesting;
-
-                       return within_depth(base_str + matchlen + 1,
-                                           baselen - matchlen - 1,
-                                           !!S_ISDIR(entry->mode),
-                                           ps->max_depth) ?
-                               entry_interesting : entry_not_interesting;
+                           ps->max_depth == -1) {
+                               if (!item->attr_match_nr)
+                                       return all_entries_interesting;
+                               else
+                                       goto interesting;
+                       }
+
+                       if (within_depth(base_str + matchlen + 1,
+                                        baselen - matchlen - 1,
+                                        !!S_ISDIR(entry->mode),
+                                        ps->max_depth))
+                               goto interesting;
+                       else
+                               return entry_not_interesting;
                }
 
                /* Either there must be no base, or the base must match. */
@@ -989,12 +1003,12 @@ static enum interesting do_match(const struct name_entry *entry,
                        if (match_entry(item, entry, pathlen,
                                        match + baselen, matchlen - baselen,
                                        &never_interesting))
-                               return entry_interesting;
+                               goto interesting;
 
                        if (item->nowildcard_len < item->len) {
                                if (!git_fnmatch(item, match + baselen, entry->path,
                                                 item->nowildcard_len - baselen))
-                                       return entry_interesting;
+                                       goto interesting;
 
                                /*
                                 * Match all directories. We'll try to
@@ -1015,7 +1029,7 @@ static enum interesting do_match(const struct name_entry *entry,
                                    !ps_strncmp(item, match + baselen,
                                                entry->path,
                                                item->nowildcard_len - baselen))
-                                       return entry_interesting;
+                                       goto interesting;
                        }
 
                        continue;
@@ -1050,7 +1064,7 @@ static enum interesting do_match(const struct name_entry *entry,
                if (!git_fnmatch(item, match, base->buf + base_offset,
                                 item->nowildcard_len)) {
                        strbuf_setlen(base, base_offset + baselen);
-                       return entry_interesting;
+                       goto interesting;
                }
 
                /*
@@ -1064,7 +1078,7 @@ static enum interesting do_match(const struct name_entry *entry,
                    !ps_strncmp(item, match, base->buf + base_offset,
                                item->nowildcard_len)) {
                        strbuf_setlen(base, base_offset + baselen);
-                       return entry_interesting;
+                       goto interesting;
                }
 
                strbuf_setlen(base, base_offset + baselen);
@@ -1078,6 +1092,38 @@ static enum interesting do_match(const struct name_entry *entry,
                 */
                if (ps->recursive && S_ISDIR(entry->mode))
                        return entry_interesting;
+               continue;
+interesting:
+               if (item->attr_match_nr) {
+                       int ret;
+
+                       /*
+                        * Must not return all_entries_not_interesting
+                        * prematurely. We do not know if all entries do not
+                        * match some attributes with current attr API.
+                        */
+                       never_interesting = entry_not_interesting;
+
+                       /*
+                        * Consider all directories interesting (because some
+                        * of those files inside may match some attributes
+                        * even though the parent dir does not)
+                        *
+                        * FIXME: attributes _can_ match directories and we
+                        * can probably return all_entries_interesting or
+                        * all_entries_not_interesting here if matched.
+                        */
+                       if (S_ISDIR(entry->mode))
+                               return entry_interesting;
+
+                       strbuf_add(base, entry->path, pathlen);
+                       ret = match_pathspec_attrs(istate, base->buf + base_offset,
+                                                  base->len - base_offset, item);
+                       strbuf_setlen(base, base_offset + baselen);
+                       if (!ret)
+                               continue;
+               }
+               return entry_interesting;
        }
        return never_interesting; /* No matches */
 }
@@ -1088,12 +1134,13 @@ static enum interesting do_match(const struct name_entry *entry,
  * Pre-condition: either baselen == base_offset (i.e. empty path)
  * or base[baselen-1] == '/' (i.e. with trailing slash).
  */
-enum interesting tree_entry_interesting(const struct name_entry *entry,
+enum interesting tree_entry_interesting(struct index_state *istate,
+                                       const struct name_entry *entry,
                                        struct strbuf *base, int base_offset,
                                        const struct pathspec *ps)
 {
        enum interesting positive, negative;
-       positive = do_match(entry, base, base_offset, ps, 0);
+       positive = do_match(istate, entry, base, base_offset, ps, 0);
 
        /*
         * case | entry | positive | negative | result
@@ -1105,7 +1152,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
         *   5  |  file |    1     |    1     |   0
         *   6  |  file |    1     |    2     |   0
         *   7  |  file |    2     |   -1     |   2
-        *   8  |  file |    2     |    0     |   2
+        *   8  |  file |    2     |    0     |   1
         *   9  |  file |    2     |    1     |   0
         *  10  |  file |    2     |    2     |  -1
         * -----+-------+----------+----------+-------
@@ -1116,7 +1163,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
         *  15  |  dir  |    1     |    1     |   1 (*)
         *  16  |  dir  |    1     |    2     |   0
         *  17  |  dir  |    2     |   -1     |   2
-        *  18  |  dir  |    2     |    0     |   2
+        *  18  |  dir  |    2     |    0     |   1
         *  19  |  dir  |    2     |    1     |   1 (*)
         *  20  |  dir  |    2     |    2     |  -1
         *
@@ -1130,9 +1177,14 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
            positive <= entry_not_interesting) /* #1, #2, #11, #12 */
                return positive;
 
-       negative = do_match(entry, base, base_offset, ps, 1);
+       negative = do_match(istate, entry, base, base_offset, ps, 1);
+
+       /* #8, #18 */
+       if (positive == all_entries_interesting &&
+           negative == entry_not_interesting)
+               return entry_interesting;
 
-       /* #3, #4, #7, #8, #13, #14, #17, #18 */
+       /* #3, #4, #7, #13, #14, #17 */
        if (negative <= entry_not_interesting)
                return positive;