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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).