From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org, Junio C Hamano <gitster@pobox.com>,
Michael J Gruber <git@drmicha.warpmail.net>
Cc: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH 1/3] Reimplement read_tree_recursive() using tree_entry_interesting()
Date: Fri, 25 Mar 2011 16:34:18 +0700 [thread overview]
Message-ID: <1301045660-25053-1-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <7vlj048f97.fsf@alter.siamese.dyndns.org>
read_tree_recursive() uses a very similar function, match_tree_entry, to
tree_entry_interesting() to do its path matching. This patch kills
match_tree_entry() in favor of tree_entry_interesting().
match_tree_entry(), like older version of tree_entry_interesting(), does
not support wildcard matching. New read_tree_recursive() retains this
behavior by forcing all pathspecs literal.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
2011/3/25 Junio C Hamano <gitster@pobox.com>:
> Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:
>
>> +static int read_tree_1(struct tree *tree, struct strbuf *base,
>> + int stage, struct pathspec *pathspecs,
>> + read_tree_fn_t fn, void *context)
>
> Micronit: call the variable pathspec, not pathspecs.
Fixed (also in the second patch)
> This "if all-interesting then avoid calling into an expensive matcher"
> logic looks familiar but is not something that came from the parts deleted
> by this patch. Where did I see it? Is that something we can share in a
> common helper function? Is such a sharing worth pursuing, considering that
> the above is a reasonably trivial logic in a tight loop?
>
> "That's how the return value of tree-entry-interesting is designed to be
> used, and it is unsurprising that all the callers will fall into that
> pattern" is a perfectly acceptable answer, I guess.
Actually the surrounding code could be improved so that helper function
is not needed. I also update other t_e_i() callsites in the third patch.
tree.c | 152 ++++++++++++++++++++++++----------------------------------------
1 files changed, 57 insertions(+), 95 deletions(-)
diff --git a/tree.c b/tree.c
index 5ab90af..db3a5c3 100644
--- a/tree.c
+++ b/tree.c
@@ -45,62 +45,14 @@ static int read_one_entry_quick(const unsigned char *sha1, const char *base, int
ADD_CACHE_JUST_APPEND);
}
-static int match_tree_entry(const char *base, int baselen, const char *path, unsigned int mode, const char **paths)
-{
- const char *match;
- int pathlen;
-
- if (!paths)
- return 1;
- pathlen = strlen(path);
- while ((match = *paths++) != NULL) {
- int matchlen = strlen(match);
-
- if (baselen >= matchlen) {
- /* If it doesn't match, move along... */
- if (strncmp(base, match, matchlen))
- continue;
- /* pathspecs match only at the directory boundaries */
- if (!matchlen ||
- baselen == matchlen ||
- base[matchlen] == '/' ||
- match[matchlen - 1] == '/')
- return 1;
- continue;
- }
-
- /* Does the base match? */
- if (strncmp(base, match, baselen))
- continue;
-
- match += baselen;
- matchlen -= baselen;
-
- if (pathlen > matchlen)
- continue;
-
- if (matchlen > pathlen) {
- if (match[pathlen] != '/')
- continue;
- if (!S_ISDIR(mode))
- continue;
- }
-
- if (strncmp(path, match, pathlen))
- continue;
-
- return 1;
- }
- return 0;
-}
-
-int read_tree_recursive(struct tree *tree,
- const char *base, int baselen,
- int stage, const char **match,
- read_tree_fn_t fn, void *context)
+static int read_tree_1(struct tree *tree, struct strbuf *base,
+ int stage, struct pathspec *pathspec,
+ read_tree_fn_t fn, void *context)
{
struct tree_desc desc;
struct name_entry entry;
+ unsigned char sha1[20];
+ int len, retval = 0, oldlen = base->len;
if (parse_tree(tree))
return -1;
@@ -108,10 +60,16 @@ int read_tree_recursive(struct tree *tree,
init_tree_desc(&desc, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) {
- if (!match_tree_entry(base, baselen, entry.path, entry.mode, match))
- continue;
+ if (retval != 2) {
+ retval = tree_entry_interesting(&entry, base, 0, pathspec);
+ if (retval < 0)
+ break;
+ if (retval == 0)
+ continue;
+ }
- switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage, context)) {
+ switch (fn(entry.sha1, base->buf, base->len,
+ entry.path, entry.mode, stage, context)) {
case 0:
continue;
case READ_TREE_RECURSIVE:
@@ -119,56 +77,60 @@ int read_tree_recursive(struct tree *tree,
default:
return -1;
}
- if (S_ISDIR(entry.mode)) {
- int retval;
- char *newbase;
- unsigned int pathlen = tree_entry_len(entry.path, entry.sha1);
-
- newbase = xmalloc(baselen + 1 + pathlen);
- memcpy(newbase, base, baselen);
- memcpy(newbase + baselen, entry.path, pathlen);
- newbase[baselen + pathlen] = '/';
- retval = read_tree_recursive(lookup_tree(entry.sha1),
- newbase,
- baselen + pathlen + 1,
- stage, match, fn, context);
- free(newbase);
- if (retval)
- return -1;
- continue;
- } else if (S_ISGITLINK(entry.mode)) {
- int retval;
- struct strbuf path;
- unsigned int entrylen;
- struct commit *commit;
- entrylen = tree_entry_len(entry.path, entry.sha1);
- strbuf_init(&path, baselen + entrylen + 1);
- strbuf_add(&path, base, baselen);
- strbuf_add(&path, entry.path, entrylen);
- strbuf_addch(&path, '/');
+ if (S_ISDIR(entry.mode))
+ hashcpy(sha1, entry.sha1);
+ else if (S_ISGITLINK(entry.mode)) {
+ struct commit *commit;
commit = lookup_commit(entry.sha1);
if (!commit)
- die("Commit %s in submodule path %s not found",
- sha1_to_hex(entry.sha1), path.buf);
+ die("Commit %s in submodule path %s%s not found",
+ sha1_to_hex(entry.sha1),
+ base->buf, entry.path);
if (parse_commit(commit))
- die("Invalid commit %s in submodule path %s",
- sha1_to_hex(entry.sha1), path.buf);
-
- retval = read_tree_recursive(commit->tree,
- path.buf, path.len,
- stage, match, fn, context);
- strbuf_release(&path);
- if (retval)
- return -1;
- continue;
+ die("Invalid commit %s in submodule path %s%s",
+ sha1_to_hex(entry.sha1),
+ base->buf, entry.path);
+
+ hashcpy(sha1, commit->tree->object.sha1);
}
+ else
+ continue;
+
+ len = tree_entry_len(entry.path, entry.sha1);
+ strbuf_add(base, entry.path, len);
+ strbuf_addch(base, '/');
+ retval = read_tree_1(lookup_tree(sha1),
+ base, stage, pathspec,
+ fn, context);
+ strbuf_setlen(base, oldlen);
+ if (retval)
+ return -1;
}
return 0;
}
+int read_tree_recursive(struct tree *tree,
+ const char *base, int baselen,
+ int stage, const char **match,
+ read_tree_fn_t fn, void *context)
+{
+ struct strbuf sb = STRBUF_INIT;
+ struct pathspec pathspec;
+ int i, ret;
+
+ init_pathspec(&pathspec, match);
+ for (i = 0; i < pathspec.nr; i++)
+ pathspec.items[i].has_wildcard = 0;
+ strbuf_add(&sb, base, baselen);
+ ret = read_tree_1(tree, &sb, stage, &pathspec, fn, context);
+ strbuf_release(&sb);
+ free_pathspec(&pathspec);
+ return ret;
+}
+
static int cmp_cache_name_compare(const void *a_, const void *b_)
{
const struct cache_entry *ce1, *ce2;
--
1.7.4.74.g639db
next prev parent reply other threads:[~2011-03-25 9:34 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-23 10:33 Relative ls-files John Tapsell
2011-03-23 10:49 ` Michael J Gruber
2011-03-23 11:27 ` John Tapsell
2011-03-23 11:28 ` demerphq
2011-03-23 11:42 ` Michael J Gruber
2011-03-23 13:54 ` Martin Langhoff
2011-03-23 14:09 ` Junio C Hamano
2011-03-23 14:14 ` Nguyen Thai Ngoc Duy
2011-03-23 15:20 ` Junio C Hamano
2011-03-23 15:41 ` Nguyen Thai Ngoc Duy
2011-03-23 22:44 ` Junio C Hamano
2011-03-24 13:26 ` Nguyen Thai Ngoc Duy
2011-03-24 14:41 ` [PATCH 1/2] Reimplement read_tree_recursive() using tree_entry_interesting() Nguyễn Thái Ngọc Duy
2011-03-24 14:41 ` [PATCH 2/2] Convert read_tree{,_recursive} to support struct pathspec Nguyễn Thái Ngọc Duy
2011-03-24 14:49 ` Nguyen Thai Ngoc Duy
2011-03-24 19:58 ` Junio C Hamano
2011-03-24 19:07 ` [PATCH 1/2] Reimplement read_tree_recursive() using tree_entry_interesting() Junio C Hamano
2011-03-24 19:55 ` Junio C Hamano
2011-03-25 9:34 ` Nguyễn Thái Ngọc Duy [this message]
2011-03-25 9:34 ` [PATCH 2/3] Convert read_tree{,_recursive} to support struct pathspec Nguyễn Thái Ngọc Duy
2011-03-25 9:34 ` [PATCH 3/3] Improve tree_entry_interesting() handling code Nguyễn Thái Ngọc Duy
2011-03-24 14:47 ` Relative ls-files Junio C Hamano
2011-03-23 14:46 ` Martin Langhoff
2011-03-23 15:24 ` Junio C Hamano
2011-03-23 17:35 ` Junio C Hamano
2011-03-23 15:42 ` Junio C Hamano
2011-03-23 15:57 ` Michael J Gruber
2011-03-23 16:10 ` Nguyen Thai Ngoc Duy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1301045660-25053-1-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@drmicha.warpmail.net \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.