From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Jonathan Nieder" <jrnieder@gmail.com>,
"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH WIP 2/3] tree-diff: teach it to understand exclude patterns
Date: Wed, 5 Oct 2011 18:18:07 +1100 [thread overview]
Message-ID: <1317799088-26626-3-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1317799088-26626-1-git-send-email-pclouds@gmail.com>
We introduce a new set of API, diff_tree_*_with_exclude, that also
exclude entries based on .gitignore patterns.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
diff.h | 11 +++++++++++
tree-diff.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/diff.h b/diff.h
index 8c66b59..51c8a5f 100644
--- a/diff.h
+++ b/diff.h
@@ -12,6 +12,7 @@ struct diff_queue_struct;
struct strbuf;
struct diff_filespec;
struct userdiff_driver;
+struct exclude_list;
typedef void (*change_fn_t)(struct diff_options *options,
unsigned old_mode, unsigned new_mode,
@@ -170,8 +171,18 @@ extern void diff_tree_setup_paths(const char **paths, struct diff_options *);
extern void diff_tree_release_paths(struct diff_options *);
extern int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
const char *base, struct diff_options *opt);
+extern int diff_tree_with_exclude(struct tree_desc *t1, struct tree_desc *t2,
+ const char *base, struct diff_options *opt,
+ struct exclude_list *el,
+ int def_excl1, int def_excl2);
extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new,
const char *base, struct diff_options *opt);
+extern int diff_tree_sha1_with_exclude(const unsigned char *old,
+ const unsigned char *new,
+ const char *base,
+ struct diff_options *opt,
+ struct exclude_list *el,
+ int def_excl1, int def_excl2);
extern int diff_root_tree_sha1(const unsigned char *new, const char *base,
struct diff_options *opt);
diff --git a/tree-diff.c b/tree-diff.c
index b3cc2e4..9938ccf 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -5,12 +5,14 @@
#include "diff.h"
#include "diffcore.h"
#include "tree.h"
+#include "dir.h"
static void show_entry(struct diff_options *opt, const char *prefix,
struct tree_desc *desc, struct strbuf *base);
static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2,
- struct strbuf *base, struct diff_options *opt)
+ struct strbuf *base, struct diff_options *opt,
+ struct exclude_list *el, int def_excl1, int def_excl2)
{
unsigned mode1, mode2;
const char *path1, *path2;
@@ -52,7 +54,8 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2,
sha1, sha2, base->buf, 0, 0);
}
strbuf_addch(base, '/');
- diff_tree_sha1(sha1, sha2, base->buf, opt);
+ diff_tree_sha1_with_exclude(sha1, sha2, base->buf, opt,
+ el, def_excl1, def_excl2);
} else {
opt->change(opt, mode1, mode2, sha1, sha2, base->buf, 0, 0);
}
@@ -113,6 +116,31 @@ static void show_entry(struct diff_options *opt, const char *prefix,
strbuf_setlen(base, old_baselen);
}
+static int skip_excludes(struct tree_desc *t, struct strbuf *base,
+ struct exclude_list *el, int defval)
+{
+ for (; t->size; update_tree_entry(t)) {
+ /*
+ * excluded_from_list only cares whether dtype is
+ * DT_DIR or something else (except DT_UNKNOWN). Any
+ * other value would do
+ */
+ int dtype = S_ISDIR(t->entry.mode) ? DT_DIR : DT_REG;
+ int ret = excluded_from_list(base->buf, base->len, t->entry.path,
+ &dtype, el);
+
+ /* If undecided, use matching result of parent dir in defval */
+ if (ret < 0)
+ ret = defval;
+
+ if (ret == 1 && dtype == DT_REG)
+ ;
+ else
+ return ret;
+ }
+ return defval;
+}
+
static void skip_uninteresting(struct tree_desc *t, struct strbuf *base,
struct diff_options *opt, int *match)
{
@@ -130,9 +158,17 @@ static void skip_uninteresting(struct tree_desc *t, struct strbuf *base,
int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
const char *base_str, struct diff_options *opt)
{
+ return diff_tree_with_exclude(t1, t2, base_str, opt, NULL, 0, 0);
+}
+
+int diff_tree_with_exclude(struct tree_desc *t1, struct tree_desc *t2,
+ const char *base_str, struct diff_options *opt,
+ struct exclude_list *el, int def_excl1, int def_excl2)
+{
struct strbuf base;
int baselen = strlen(base_str);
int t1_match = 0, t2_match = 0;
+ int excl1 = 0, excl2 = 0;
/* Enable recursion indefinitely */
opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
@@ -148,6 +184,10 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
skip_uninteresting(t1, &base, opt, &t1_match);
skip_uninteresting(t2, &base, opt, &t2_match);
}
+ if (el && el->nr) {
+ excl1 = skip_excludes(t1, &base, el, def_excl1);
+ excl2 = skip_excludes(t2, &base, el, def_excl2);
+ }
if (!t1->size) {
if (!t2->size)
break;
@@ -160,7 +200,7 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
update_tree_entry(t1);
continue;
}
- switch (compare_tree_entry(t1, t2, &base, opt)) {
+ switch (compare_tree_entry(t1, t2, &base, opt, el, excl1, excl2)) {
case -1:
update_tree_entry(t1);
continue;
@@ -267,6 +307,16 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co
int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base, struct diff_options *opt)
{
+ return diff_tree_sha1_with_exclude(old, new, base, opt, NULL, 0, 0);
+}
+
+int diff_tree_sha1_with_exclude(const unsigned char *old,
+ const unsigned char *new,
+ const char *base,
+ struct diff_options *opt,
+ struct exclude_list *el,
+ int def_excl1, int def_excl2)
+{
void *tree1, *tree2;
struct tree_desc t1, t2;
unsigned long size1, size2;
@@ -280,7 +330,7 @@ int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const cha
die("unable to read destination tree (%s)", sha1_to_hex(new));
init_tree_desc(&t1, tree1, size1);
init_tree_desc(&t2, tree2, size2);
- retval = diff_tree(&t1, &t2, base, opt);
+ retval = diff_tree_with_exclude(&t1, &t2, base, opt, el, def_excl1, def_excl2);
if (!*base && DIFF_OPT_TST(opt, FOLLOW_RENAMES) && diff_might_be_rename()) {
init_tree_desc(&t1, tree1, size1);
init_tree_desc(&t2, tree2, size2);
--
1.7.3.1.256.g2539c.dirty
next prev parent reply other threads:[~2011-10-05 7:18 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-10-05 7:18 [PATCH WIP 0/3] git log --exclude Nguyễn Thái Ngọc Duy
2011-10-05 7:18 ` [PATCH WIP 1/3] diff-no-index: rename read_directory to avoid conflict from dir.h Nguyễn Thái Ngọc Duy
2011-10-05 7:18 ` Nguyễn Thái Ngọc Duy [this message]
2011-10-05 7:18 ` [PATCH WIP 3/3] log: add --exclude option Nguyễn Thái Ngọc Duy
2011-10-05 8:08 ` [PATCH WIP 0/3] git log --exclude Matthieu Moy
2011-10-05 8:28 ` Nguyen Thai Ngoc Duy
2011-10-05 17:20 ` Junio C Hamano
2011-10-06 14:34 ` Jeff King
2011-10-06 17:22 ` Junio C Hamano
2011-10-06 21:47 ` Nguyen Thai Ngoc Duy
2011-10-07 7:16 ` Nguyen Thai Ngoc Duy
2011-10-07 17:57 ` Junio C Hamano
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=1317799088-26626-3-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
--cc=jrnieder@gmail.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.