All of lore.kernel.org
 help / color / mirror / Atom feed
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/2] Reimplement read_tree_recursive() using tree_entry_interesting()
Date: Thu, 24 Mar 2011 21:41:14 +0700	[thread overview]
Message-ID: <1300977675-6243-1-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <AANLkTinYB=ZUTe29Y9ibLVL5z3KhiYmnCpCGcHx=18RJ@mail.gmail.com>

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>
---
 tree.c |  156 +++++++++++++++++++++++++--------------------------------------
 1 files changed, 62 insertions(+), 94 deletions(-)

diff --git a/tree.c b/tree.c
index 5ab90af..2b23381 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 *pathspecs,
+		       read_tree_fn_t fn, void *context)
 {
 	struct tree_desc desc;
 	struct name_entry entry;
+	unsigned char sha1[20];
+	int len, retval, all_interesting = 0, oldlen = base->len;
 
 	if (parse_tree(tree))
 		return -1;
@@ -108,10 +60,22 @@ 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))
+		if (all_interesting)
+			retval = all_interesting > 0;
+		else {
+			retval = tree_entry_interesting(&entry, base, 0, pathspecs);
+			if (retval == 2)
+				all_interesting = 1;
+			else if (retval == -1) {
+				all_interesting = -1;
+				retval = 0;
+			}
+		}
+		if (!retval)
 			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 +83,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, pathspecs,
+				     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 pathspecs;
+	int i, ret;
+
+	init_pathspec(&pathspecs, match);
+	for (i = 0; i < pathspecs.nr; i++)
+		pathspecs.items[i].has_wildcard = 0;
+	strbuf_add(&sb, base, baselen);
+	ret = read_tree_1(tree, &sb, stage, &pathspecs, fn, context);
+	strbuf_release(&sb);
+	free_pathspec(&pathspecs);
+	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

  reply	other threads:[~2011-03-24 14:41 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                       ` Nguyễn Thái Ngọc Duy [this message]
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                           ` [PATCH 1/3] " Nguyễn Thái Ngọc Duy
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=1300977675-6243-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.