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 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).