Skip to content

Commit c4dc9d4

Browse files
pcloudsgitster
authored andcommitted
tree_entry_interesting(): support depth limit
This is needed to replace pathspec_matches() in builtin/grep.c. max_depth == -1 means infinite depth. Depth limit is only effective when pathspec.recursive == 1. When pathspec.recursive == 0, the behavior depends on match functions: non-recursive for tree_entry_interesting() and recursive for match_pathspec{,_depth} Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 1ebdd91 commit c4dc9d4

File tree

5 files changed

+38
-3
lines changed

5 files changed

+38
-3
lines changed

cache.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,8 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct
496496
struct pathspec {
497497
const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
498498
int nr;
499+
int recursive:1;
500+
int max_depth;
499501
struct pathspec_item {
500502
const char *match;
501503
int len;

dir.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,21 @@ int fill_directory(struct dir_struct *dir, const char **pathspec)
7171
return len;
7272
}
7373

74+
int within_depth(const char *name, int namelen,
75+
int depth, int max_depth)
76+
{
77+
const char *cp = name, *cpe = name + namelen;
78+
79+
while (cp < cpe) {
80+
if (*cp++ != '/')
81+
continue;
82+
depth++;
83+
if (depth > max_depth)
84+
return 0;
85+
}
86+
return 1;
87+
}
88+
7489
/*
7590
* Does 'match' match the given name?
7691
* A match is found if

dir.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct dir_struct {
6565
#define MATCHED_FNMATCH 2
6666
#define MATCHED_EXACTLY 3
6767
extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
68+
extern int within_depth(const char *name, int namelen, int depth, int max_depth);
6869

6970
extern int fill_directory(struct dir_struct *dir, const char **pathspec);
7071
extern int read_directory(struct dir_struct *, const char *path, int len, const char **pathspec);

tree-diff.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
152152
struct strbuf base;
153153
int baselen = strlen(base_str);
154154

155+
/* Enable recursion indefinitely */
156+
opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
157+
opt->pathspec.max_depth = -1;
158+
155159
strbuf_init(&base, PATH_MAX);
156160
strbuf_add(&base, base_str, baselen);
157161

tree-walk.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "cache.h"
22
#include "tree-walk.h"
33
#include "unpack-trees.h"
4+
#include "dir.h"
45
#include "tree.h"
56

67
static const char *get_mode(const char *str, unsigned int *modep)
@@ -557,8 +558,13 @@ int tree_entry_interesting(const struct name_entry *entry,
557558
int pathlen, baselen = base->len;
558559
int never_interesting = -1;
559560

560-
if (!ps || !ps->nr)
561-
return 1;
561+
if (!ps->nr) {
562+
if (!ps->recursive || ps->max_depth == -1)
563+
return 1;
564+
return !!within_depth(base->buf, baselen,
565+
!!S_ISDIR(entry->mode),
566+
ps->max_depth);
567+
}
562568

563569
pathlen = tree_entry_len(entry->path, entry->sha1);
564570

@@ -571,7 +577,14 @@ int tree_entry_interesting(const struct name_entry *entry,
571577
/* If it doesn't match, move along... */
572578
if (!match_dir_prefix(base->buf, baselen, match, matchlen))
573579
continue;
574-
return 2;
580+
581+
if (!ps->recursive || ps->max_depth == -1)
582+
return 2;
583+
584+
return !!within_depth(base->buf + matchlen + 1,
585+
baselen - matchlen - 1,
586+
!!S_ISDIR(entry->mode),
587+
ps->max_depth);
575588
}
576589

577590
/* Does the base match? */

0 commit comments

Comments
 (0)