* [PATCH 0/5] en/object-list-with-pathspec (v3?)
@ 2010-09-07 15:47 Nguyễn Thái Ngọc Duy
2010-09-07 15:47 ` [PATCH 1/5] diff-no-index.c: rename read_directory() to read_dir() Nguyễn Thái Ngọc Duy
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2010-09-07 15:47 UTC (permalink / raw)
To: git, Elijah Newren, Junio C Hamano; +Cc: Nguyễn Thái Ngọc Duy
Changes from last time is tree_entry_interesting() now takes
struct exclude * as the pathspecs.
I think there'll be a bit of performance loss because diff_options.el
is not initialized from the beginning. But that requires more changes
outside tree-diff.c (makes sure that diff_options.el is copied properly,
makes sure that diff_tree_setup_* is called ...) So one step at a time.
I'm working on it.
Elijah Newren (2):
Add testcases showing how pathspecs are ignored with rev-list
--objects
Make rev-list --objects work together with pathspecs
Nguyễn Thái Ngọc Duy (3):
diff-no-index.c: rename read_directory() to read_dir()
tree-walk: move tree_entry_interesting() from tree-diff.c
tree_entry_interesting(): remove dependency on struct diff_options
diff-no-index.c | 6 +-
diff.h | 3 +
list-objects.c | 25 ++++++++
revision.c | 8 ++-
revision.h | 3 +-
t/t6000-rev-list-misc.sh | 51 ++++++++++++++++
tree-diff.c | 145 +++++++++-------------------------------------
tree-walk.c | 111 +++++++++++++++++++++++++++++++++++
tree-walk.h | 4 +
9 files changed, 233 insertions(+), 123 deletions(-)
create mode 100755 t/t6000-rev-list-misc.sh
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/5] diff-no-index.c: rename read_directory() to read_dir()
2010-09-07 15:47 [PATCH 0/5] en/object-list-with-pathspec (v3?) Nguyễn Thái Ngọc Duy
@ 2010-09-07 15:47 ` Nguyễn Thái Ngọc Duy
2010-09-07 15:48 ` [PATCH 2/5] Add testcases showing how pathspecs are ignored with rev-list --objects Nguyễn Thái Ngọc Duy
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2010-09-07 15:47 UTC (permalink / raw)
To: git, Elijah Newren, Junio C Hamano; +Cc: Nguyễn Thái Ngọc Duy
This name clashes with one in dir.h, to be included later on.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
diff-no-index.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/diff-no-index.c b/diff-no-index.c
index ce9e783..859a8ba 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -16,7 +16,7 @@
#include "builtin.h"
#include "string-list.h"
-static int read_directory(const char *path, struct string_list *list)
+static int read_dir(const char *path, struct string_list *list)
{
DIR *dir;
struct dirent *e;
@@ -68,9 +68,9 @@ static int queue_diff(struct diff_options *o,
struct string_list p2 = STRING_LIST_INIT_DUP;
int len1 = 0, len2 = 0, i1, i2, ret = 0;
- if (name1 && read_directory(name1, &p1))
+ if (name1 && read_dir(name1, &p1))
return -1;
- if (name2 && read_directory(name2, &p2)) {
+ if (name2 && read_dir(name2, &p2)) {
string_list_clear(&p1, 0);
return -1;
}
--
1.7.1.rc1.69.g24c2f7
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/5] Add testcases showing how pathspecs are ignored with rev-list --objects
2010-09-07 15:47 [PATCH 0/5] en/object-list-with-pathspec (v3?) Nguyễn Thái Ngọc Duy
2010-09-07 15:47 ` [PATCH 1/5] diff-no-index.c: rename read_directory() to read_dir() Nguyễn Thái Ngọc Duy
@ 2010-09-07 15:48 ` Nguyễn Thái Ngọc Duy
2010-09-07 15:48 ` [PATCH 3/5] tree-walk: move tree_entry_interesting() from tree-diff.c Nguyễn Thái Ngọc Duy
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2010-09-07 15:48 UTC (permalink / raw)
To: git, Elijah Newren, Junio C Hamano
Cc: Elijah Newren, Junio C Hamano,
Nguyễn Thái Ngọc Duy
From: Elijah Newren <newren@gmail.com>
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
t/t6000-rev-list-misc.sh | 51 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 51 insertions(+), 0 deletions(-)
create mode 100755 t/t6000-rev-list-misc.sh
diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh
new file mode 100755
index 0000000..b3c1dd8
--- /dev/null
+++ b/t/t6000-rev-list-misc.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+test_description='miscellaneous rev-list tests'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo content1 >wanted_file &&
+ echo content2 >unwanted_file &&
+ git add wanted_file unwanted_file &&
+ git commit -m one
+'
+
+test_expect_failure 'rev-list --objects heeds pathspecs' '
+ git rev-list --objects HEAD -- wanted_file >output &&
+ grep wanted_file output &&
+ ! grep unwanted_file output
+'
+
+test_expect_failure 'rev-list --objects with pathspecs and deeper paths' '
+ mkdir foo &&
+ >foo/file &&
+ git add foo/file &&
+ git commit -m two &&
+
+ git rev-list --objects HEAD -- foo >output &&
+ grep foo/file output &&
+
+ git rev-list --objects HEAD -- foo/file >output &&
+ grep foo/file output &&
+ ! grep unwanted_file output
+'
+
+test_expect_failure 'rev-list --objects with pathspecs and copied files' '
+ git checkout --orphan junio-testcase &&
+ git rm -rf . &&
+
+ mkdir two &&
+ echo frotz >one &&
+ cp one two/three &&
+ git add one two/three &&
+ test_tick &&
+ git commit -m that &&
+
+ ONE=$(git rev-parse HEAD:one)
+ git rev-list --objects HEAD two >output &&
+ grep "$ONE two/three" output &&
+ ! grep one output
+'
+
+test_done
--
1.7.1.rc1.69.g24c2f7
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/5] tree-walk: move tree_entry_interesting() from tree-diff.c
2010-09-07 15:47 [PATCH 0/5] en/object-list-with-pathspec (v3?) Nguyễn Thái Ngọc Duy
2010-09-07 15:47 ` [PATCH 1/5] diff-no-index.c: rename read_directory() to read_dir() Nguyễn Thái Ngọc Duy
2010-09-07 15:48 ` [PATCH 2/5] Add testcases showing how pathspecs are ignored with rev-list --objects Nguyễn Thái Ngọc Duy
@ 2010-09-07 15:48 ` Nguyễn Thái Ngọc Duy
2010-09-07 15:48 ` [PATCH 4/5] tree_entry_interesting(): remove dependency on struct diff_options Nguyễn Thái Ngọc Duy
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2010-09-07 15:48 UTC (permalink / raw)
To: git, Elijah Newren, Junio C Hamano; +Cc: Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
tree-diff.c | 114 ----------------------------------------------------------
tree-walk.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tree-walk.h | 3 ++
3 files changed, 118 insertions(+), 114 deletions(-)
diff --git a/tree-diff.c b/tree-diff.c
index cd659c6..c74d0b5 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -82,120 +82,6 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
return 0;
}
-/*
- * Is a tree entry interesting given the pathspec we have?
- *
- * Return:
- * - 2 for "yes, and all subsequent entries will be"
- * - 1 for yes
- * - zero for no
- * - negative for "no, and no subsequent entries will be either"
- */
-static int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt)
-{
- const char *path;
- const unsigned char *sha1;
- unsigned mode;
- int i;
- int pathlen;
- int never_interesting = -1;
-
- if (!opt->nr_paths)
- return 1;
-
- sha1 = tree_entry_extract(desc, &path, &mode);
-
- pathlen = tree_entry_len(path, sha1);
-
- for (i = 0; i < opt->nr_paths; i++) {
- const char *match = opt->paths[i];
- int matchlen = opt->pathlens[i];
- int m = -1; /* signals that we haven't called strncmp() */
-
- if (baselen >= matchlen) {
- /* If it doesn't match, move along... */
- if (strncmp(base, match, matchlen))
- continue;
-
- /*
- * If the base is a subdirectory of a path which
- * was specified, all of them are interesting.
- */
- if (!matchlen ||
- base[matchlen] == '/' ||
- match[matchlen - 1] == '/')
- return 2;
-
- /* Just a random prefix match */
- continue;
- }
-
- /* Does the base match? */
- if (strncmp(base, match, baselen))
- continue;
-
- match += baselen;
- matchlen -= baselen;
-
- if (never_interesting) {
- /*
- * We have not seen any match that sorts later
- * than the current path.
- */
-
- /*
- * Does match sort strictly earlier than path
- * with their common parts?
- */
- m = strncmp(match, path,
- (matchlen < pathlen) ? matchlen : pathlen);
- if (m < 0)
- continue;
-
- /*
- * If we come here even once, that means there is at
- * least one pathspec that would sort equal to or
- * later than the path we are currently looking at.
- * In other words, if we have never reached this point
- * after iterating all pathspecs, it means all
- * pathspecs are either outside of base, or inside the
- * base but sorts strictly earlier than the current
- * one. In either case, they will never match the
- * subsequent entries. In such a case, we initialized
- * the variable to -1 and that is what will be
- * returned, allowing the caller to terminate early.
- */
- never_interesting = 0;
- }
-
- if (pathlen > matchlen)
- continue;
-
- if (matchlen > pathlen) {
- if (match[pathlen] != '/')
- continue;
- if (!S_ISDIR(mode))
- continue;
- }
-
- if (m == -1)
- /*
- * we cheated and did not do strncmp(), so we do
- * that here.
- */
- m = strncmp(match, path, pathlen);
-
- /*
- * If common part matched earlier then it is a hit,
- * because we rejected the case where path is not a
- * leading directory and is shorter than match.
- */
- if (!m)
- return 1;
- }
- return never_interesting; /* No matches */
-}
-
/* A whole sub-tree went away or appeared */
static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base, int baselen)
{
diff --git a/tree-walk.c b/tree-walk.c
index a9bbf4e..bc83fa3 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -2,6 +2,7 @@
#include "tree-walk.h"
#include "unpack-trees.h"
#include "tree.h"
+#include "diff.h"
static const char *get_mode(const char *str, unsigned int *modep)
{
@@ -455,3 +456,117 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch
free(tree);
return retval;
}
+
+/*
+ * Is a tree entry interesting given the pathspec we have?
+ *
+ * Return:
+ * - 2 for "yes, and all subsequent entries will be"
+ * - 1 for yes
+ * - zero for no
+ * - negative for "no, and no subsequent entries will be either"
+ */
+static int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt)
+{
+ const char *path;
+ const unsigned char *sha1;
+ unsigned mode;
+ int i;
+ int pathlen;
+ int never_interesting = -1;
+
+ if (!opt->nr_paths)
+ return 1;
+
+ sha1 = tree_entry_extract(desc, &path, &mode);
+
+ pathlen = tree_entry_len(path, sha1);
+
+ for (i = 0; i < opt->nr_paths; i++) {
+ const char *match = opt->paths[i];
+ int matchlen = opt->pathlens[i];
+ int m = -1; /* signals that we haven't called strncmp() */
+
+ if (baselen >= matchlen) {
+ /* If it doesn't match, move along... */
+ if (strncmp(base, match, matchlen))
+ continue;
+
+ /*
+ * If the base is a subdirectory of a path which
+ * was specified, all of them are interesting.
+ */
+ if (!matchlen ||
+ base[matchlen] == '/' ||
+ match[matchlen - 1] == '/')
+ return 2;
+
+ /* Just a random prefix match */
+ continue;
+ }
+
+ /* Does the base match? */
+ if (strncmp(base, match, baselen))
+ continue;
+
+ match += baselen;
+ matchlen -= baselen;
+
+ if (never_interesting) {
+ /*
+ * We have not seen any match that sorts later
+ * than the current path.
+ */
+
+ /*
+ * Does match sort strictly earlier than path
+ * with their common parts?
+ */
+ m = strncmp(match, path,
+ (matchlen < pathlen) ? matchlen : pathlen);
+ if (m < 0)
+ continue;
+
+ /*
+ * If we come here even once, that means there is at
+ * least one pathspec that would sort equal to or
+ * later than the path we are currently looking at.
+ * In other words, if we have never reached this point
+ * after iterating all pathspecs, it means all
+ * pathspecs are either outside of base, or inside the
+ * base but sorts strictly earlier than the current
+ * one. In either case, they will never match the
+ * subsequent entries. In such a case, we initialized
+ * the variable to -1 and that is what will be
+ * returned, allowing the caller to terminate early.
+ */
+ never_interesting = 0;
+ }
+
+ if (pathlen > matchlen)
+ continue;
+
+ if (matchlen > pathlen) {
+ if (match[pathlen] != '/')
+ continue;
+ if (!S_ISDIR(mode))
+ continue;
+ }
+
+ if (m == -1)
+ /*
+ * we cheated and did not do strncmp(), so we do
+ * that here.
+ */
+ m = strncmp(match, path, pathlen);
+
+ /*
+ * If common part matched earlier then it is a hit,
+ * because we rejected the case where path is not a
+ * leading directory and is shorter than match.
+ */
+ if (!m)
+ return 1;
+ }
+ return never_interesting; /* No matches */
+}
diff --git a/tree-walk.h b/tree-walk.h
index 88ea7e9..0572721 100644
--- a/tree-walk.h
+++ b/tree-walk.h
@@ -57,4 +57,7 @@ static inline int traverse_path_len(const struct traverse_info *info, const stru
return info->pathlen + tree_entry_len(n->path, n->sha1);
}
+struct diff_options;
+extern int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt);
+
#endif
--
1.7.1.rc1.69.g24c2f7
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/5] tree_entry_interesting(): remove dependency on struct diff_options
2010-09-07 15:47 [PATCH 0/5] en/object-list-with-pathspec (v3?) Nguyễn Thái Ngọc Duy
` (2 preceding siblings ...)
2010-09-07 15:48 ` [PATCH 3/5] tree-walk: move tree_entry_interesting() from tree-diff.c Nguyễn Thái Ngọc Duy
@ 2010-09-07 15:48 ` Nguyễn Thái Ngọc Duy
2010-09-07 15:48 ` [PATCH 5/5] Make rev-list --objects work together with pathspecs Nguyễn Thái Ngọc Duy
2010-09-08 7:47 ` [PATCH 0/5] en/object-list-with-pathspec (v3?) Elijah Newren
5 siblings, 0 replies; 8+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2010-09-07 15:48 UTC (permalink / raw)
To: git, Elijah Newren, Junio C Hamano; +Cc: Nguyễn Thái Ngọc Duy
This function can be potentially used in more places than just
tree-diff.c. "struct diff_options" does not make much sense outside
diff_tree_sha1().
Moreover people seem to be agree that diff machinery should learn
proper pathspecs too (i.e. glob support [1] and stuff), not just
treating pathspecs as tree prefix.
So instead of using pathspecs in
diff_options.{nr_paths,paths,pathlens}, tree_entry_interesting() now
uses struct exclude_list.
Struct exclude_list is also added to diff_options with the intention
to replace {nr_paths,paths,pathlens} later on. But for now, it's just
a temporary field.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
diff.h | 3 +++
tree-diff.c | 31 ++++++++++++++++++++++++++++---
tree-walk.c | 26 +++++++++++---------------
tree-walk.h | 5 +++--
4 files changed, 45 insertions(+), 20 deletions(-)
diff --git a/diff.h b/diff.h
index bf2f44d..bd8fe9e 100644
--- a/diff.h
+++ b/diff.h
@@ -5,6 +5,7 @@
#define DIFF_H
#include "tree-walk.h"
+#include "dir.h"
struct rev_info;
struct diff_options;
@@ -136,6 +137,7 @@ struct diff_options {
int nr_paths;
const char **paths;
int *pathlens;
+ struct exclude_list el;
change_fn_t change;
add_remove_fn_t add_remove;
diff_format_fn_t format_callback;
@@ -163,6 +165,7 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix);
extern const char mime_boundary_leader[];
extern void diff_tree_setup_paths(const char **paths, struct diff_options *);
+extern void diff_tree_setup_exclude_list(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);
diff --git a/tree-diff.c b/tree-diff.c
index c74d0b5..c2951af 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -92,8 +92,7 @@ static void show_tree(struct diff_options *opt, const char *prefix, struct tree_
if (all_interesting)
show = 1;
else {
- show = tree_entry_interesting(desc, base, baselen,
- opt);
+ show = tree_entry_interesting(&desc->entry, base, baselen, &opt->el);
if (show == 2)
all_interesting = 1;
}
@@ -152,7 +151,7 @@ static void skip_uninteresting(struct tree_desc *t, const char *base, int basele
if (all_interesting)
show = 1;
else {
- show = tree_entry_interesting(t, base, baselen, opt);
+ show = tree_entry_interesting(&t->entry, base, baselen, &opt->el);
if (show == 2)
all_interesting = 1;
}
@@ -167,10 +166,34 @@ static void skip_uninteresting(struct tree_desc *t, const char *base, int basele
}
}
+void diff_tree_setup_exclude_list(struct diff_options *opt)
+{
+ int i, size1, size2;
+
+ memset(&opt->el, 0, sizeof(opt->el));
+ opt->el.nr = opt->nr_paths;
+ if (!opt->el.nr)
+ return;
+
+ size1 = opt->el.nr * sizeof(struct exclude *);
+ size2 = opt->el.nr * sizeof(struct exclude);
+ opt->el.excludes = xmalloc(size1+size2);
+ memset(opt->el.excludes, 0, size1+size2);
+ for (i=0; i < opt->el.nr; i++) {
+ struct exclude *exc = ((struct exclude *)((char*)opt->el.excludes+size1))+i;
+ exc->base = opt->paths[i];
+ exc->baselen = opt->pathlens[i];
+ opt->el.excludes[i] = exc;
+ }
+}
+
int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)
{
int baselen = strlen(base);
+ struct exclude_list el;
+ el = opt->el; /* diff_tree() can be nested, save and restore opt->el later */
+ diff_tree_setup_exclude_list(opt);
for (;;) {
if (DIFF_OPT_TST(opt, QUICK) &&
DIFF_OPT_TST(opt, HAS_CHANGES))
@@ -204,6 +227,8 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, stru
}
die("git diff-tree: internal error");
}
+ free(opt->el.excludes);
+ opt->el = el;
return 0;
}
diff --git a/tree-walk.c b/tree-walk.c
index bc83fa3..c915218 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -2,7 +2,7 @@
#include "tree-walk.h"
#include "unpack-trees.h"
#include "tree.h"
-#include "diff.h"
+#include "dir.h"
static const char *get_mode(const char *str, unsigned int *modep)
{
@@ -466,25 +466,21 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch
* - zero for no
* - negative for "no, and no subsequent entries will be either"
*/
-static int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt)
+int tree_entry_interesting(const struct name_entry *entry, const char *base, int baselen,
+ const struct exclude_list *el)
{
- const char *path;
- const unsigned char *sha1;
- unsigned mode;
int i;
int pathlen;
int never_interesting = -1;
- if (!opt->nr_paths)
+ if (!el->nr)
return 1;
- sha1 = tree_entry_extract(desc, &path, &mode);
-
- pathlen = tree_entry_len(path, sha1);
+ pathlen = tree_entry_len(entry->path, entry->sha1);
- for (i = 0; i < opt->nr_paths; i++) {
- const char *match = opt->paths[i];
- int matchlen = opt->pathlens[i];
+ for (i = 0; i < el->nr; i++) {
+ const char *match = el->excludes[i]->base;
+ int matchlen = el->excludes[i]->baselen;
int m = -1; /* signals that we haven't called strncmp() */
if (baselen >= matchlen) {
@@ -522,7 +518,7 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int
* Does match sort strictly earlier than path
* with their common parts?
*/
- m = strncmp(match, path,
+ m = strncmp(match, entry->path,
(matchlen < pathlen) ? matchlen : pathlen);
if (m < 0)
continue;
@@ -549,7 +545,7 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int
if (matchlen > pathlen) {
if (match[pathlen] != '/')
continue;
- if (!S_ISDIR(mode))
+ if (!S_ISDIR(entry->mode))
continue;
}
@@ -558,7 +554,7 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int
* we cheated and did not do strncmp(), so we do
* that here.
*/
- m = strncmp(match, path, pathlen);
+ m = strncmp(match, entry->path, pathlen);
/*
* If common part matched earlier then it is a hit,
diff --git a/tree-walk.h b/tree-walk.h
index 0572721..4b37671 100644
--- a/tree-walk.h
+++ b/tree-walk.h
@@ -57,7 +57,8 @@ static inline int traverse_path_len(const struct traverse_info *info, const stru
return info->pathlen + tree_entry_len(n->path, n->sha1);
}
-struct diff_options;
-extern int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt);
+struct exclude_list;
+extern int tree_entry_interesting(const struct name_entry *entry, const char *base, int baselen,
+ const struct exclude_list *el);
#endif
--
1.7.1.rc1.69.g24c2f7
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/5] Make rev-list --objects work together with pathspecs
2010-09-07 15:47 [PATCH 0/5] en/object-list-with-pathspec (v3?) Nguyễn Thái Ngọc Duy
` (3 preceding siblings ...)
2010-09-07 15:48 ` [PATCH 4/5] tree_entry_interesting(): remove dependency on struct diff_options Nguyễn Thái Ngọc Duy
@ 2010-09-07 15:48 ` Nguyễn Thái Ngọc Duy
2010-09-08 7:47 ` [PATCH 0/5] en/object-list-with-pathspec (v3?) Elijah Newren
5 siblings, 0 replies; 8+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2010-09-07 15:48 UTC (permalink / raw)
To: git, Elijah Newren, Junio C Hamano
Cc: Elijah Newren, Junio C Hamano,
Nguyễn Thái Ngọc Duy
From: Elijah Newren <newren@gmail.com>
When traversing commits, the selection of commits would heed the list of
pathspecs passed, but subsequent walking of the trees of those commits
would not. This resulted in 'rev-list --objects HEAD -- <paths>'
displaying objects at unwanted paths.
Have process_tree() call tree_entry_interesting() to determine which paths
are interesting and should be walked.
Naturally, this change can provide a large speedup when paths are specified
together with --objects, since many tree entries are now correctly ignored.
Interestingly, though, this change also gives me a small (~1%) but
repeatable speedup even when no paths are specified with --objects.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
list-objects.c | 25 +++++++++++++++++++++++++
revision.c | 8 ++++++--
revision.h | 3 ++-
t/t6000-rev-list-misc.sh | 6 +++---
4 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/list-objects.c b/list-objects.c
index 8953548..44efca3 100644
--- a/list-objects.c
+++ b/list-objects.c
@@ -67,6 +67,9 @@ static void process_tree(struct rev_info *revs,
struct tree_desc desc;
struct name_entry entry;
struct name_path me;
+ int all_interesting = (revs->diffopt.nr_paths == 0);
+ char *full_prefix = NULL;
+ int full_prefix_len = 0;
if (!revs->tree_objects)
return;
@@ -82,9 +85,28 @@ static void process_tree(struct rev_info *revs,
me.elem = name;
me.elem_len = strlen(name);
+ if (!all_interesting) {
+ full_prefix = path_name_impl(path, name, 1);
+ full_prefix_len = strlen(full_prefix);
+ }
+
init_tree_desc(&desc, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) {
+ if (!all_interesting) {
+ int showit = tree_entry_interesting(&entry,
+ full_prefix,
+ full_prefix_len,
+ &revs->diffopt.el);
+
+ if (showit < 0)
+ break;
+ else if (!showit)
+ continue;
+ else if (showit == 2)
+ all_interesting = 1;
+ }
+
if (S_ISDIR(entry.mode))
process_tree(revs,
lookup_tree(entry.sha1),
@@ -97,6 +119,7 @@ static void process_tree(struct rev_info *revs,
lookup_blob(entry.sha1),
show, &me, entry.path);
}
+ free(full_prefix);
free(tree->buffer);
tree->buffer = NULL;
}
@@ -147,6 +170,7 @@ void traverse_commit_list(struct rev_info *revs,
int i;
struct commit *commit;
+ diff_tree_setup_exclude_list(&revs->diffopt);
while ((commit = get_revision(revs)) != NULL) {
add_pending_tree(revs, commit->tree);
show_commit(commit, data);
@@ -181,4 +205,5 @@ void traverse_commit_list(struct rev_info *revs,
revs->pending.alloc = 0;
revs->pending.objects = NULL;
}
+ free(revs->diffopt.el.excludes);
}
diff --git a/revision.c b/revision.c
index b1c1890..55c4586 100644
--- a/revision.c
+++ b/revision.c
@@ -16,7 +16,7 @@
volatile show_early_output_fn_t show_early_output;
-char *path_name(const struct name_path *path, const char *name)
+char *path_name_impl(const struct name_path *path, const char *name, int isdir)
{
const struct name_path *p;
char *n, *m;
@@ -27,7 +27,7 @@ char *path_name(const struct name_path *path, const char *name)
if (p->elem_len)
len += p->elem_len + 1;
}
- n = xmalloc(len);
+ n = xmalloc(len + !!isdir);
m = n + len - (nlen + 1);
strcpy(m, name);
for (p = path; p; p = p->up) {
@@ -37,6 +37,10 @@ char *path_name(const struct name_path *path, const char *name)
m[p->elem_len] = '/';
}
}
+ if (isdir && len > 1) {
+ n[len-1] = '/';
+ n[len] = '\0';
+ }
return n;
}
diff --git a/revision.h b/revision.h
index 05659c6..92f4feb 100644
--- a/revision.h
+++ b/revision.h
@@ -173,7 +173,8 @@ struct name_path {
const char *elem;
};
-char *path_name(const struct name_path *path, const char *name);
+char *path_name_impl(const struct name_path *path, const char *name, int isdir);
+#define path_name(path, name) path_name_impl(path, name, 0)
extern void add_object(struct object *obj,
struct object_array *p,
diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh
index b3c1dd8..b10685a 100755
--- a/t/t6000-rev-list-misc.sh
+++ b/t/t6000-rev-list-misc.sh
@@ -11,13 +11,13 @@ test_expect_success setup '
git commit -m one
'
-test_expect_failure 'rev-list --objects heeds pathspecs' '
+test_expect_success 'rev-list --objects heeds pathspecs' '
git rev-list --objects HEAD -- wanted_file >output &&
grep wanted_file output &&
! grep unwanted_file output
'
-test_expect_failure 'rev-list --objects with pathspecs and deeper paths' '
+test_expect_success 'rev-list --objects with pathspecs and deeper paths' '
mkdir foo &&
>foo/file &&
git add foo/file &&
@@ -31,7 +31,7 @@ test_expect_failure 'rev-list --objects with pathspecs and deeper paths' '
! grep unwanted_file output
'
-test_expect_failure 'rev-list --objects with pathspecs and copied files' '
+test_expect_success 'rev-list --objects with pathspecs and copied files' '
git checkout --orphan junio-testcase &&
git rm -rf . &&
--
1.7.1.rc1.69.g24c2f7
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 0/5] en/object-list-with-pathspec (v3?)
2010-09-07 15:47 [PATCH 0/5] en/object-list-with-pathspec (v3?) Nguyễn Thái Ngọc Duy
` (4 preceding siblings ...)
2010-09-07 15:48 ` [PATCH 5/5] Make rev-list --objects work together with pathspecs Nguyễn Thái Ngọc Duy
@ 2010-09-08 7:47 ` Elijah Newren
2010-09-08 9:58 ` Nguyen Thai Ngoc Duy
5 siblings, 1 reply; 8+ messages in thread
From: Elijah Newren @ 2010-09-08 7:47 UTC (permalink / raw)
To: Nguyễn Thái Ngọc Duy; +Cc: git, Junio C Hamano
2010/9/7 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>:
> Changes from last time is tree_entry_interesting() now takes
> struct exclude * as the pathspecs.
>
> I think there'll be a bit of performance loss because diff_options.el
> is not initialized from the beginning. But that requires more changes
> outside tree-diff.c (makes sure that diff_options.el is copied properly,
> makes sure that diff_tree_setup_* is called ...) So one step at a time.
> I'm working on it.
Looks reasonable to me so far. I believe your series already makes
nr_paths, paths, and pathlens fields from diff_options unused (other
than via exclude_list) -- yes? If so, that suggests that we could
just modify diff_tree_setup_paths() to do the work that your new
diff_tree_setup_exclude_lists() is doing (and to take an exclude_list*
instead of a diff_options*). Then you wouldn't need to worry about
doing the setup "on-the-fly" and the performance differences should go
away.
Am I understanding correctly, and is that the route you're going?
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/5] en/object-list-with-pathspec (v3?)
2010-09-08 7:47 ` [PATCH 0/5] en/object-list-with-pathspec (v3?) Elijah Newren
@ 2010-09-08 9:58 ` Nguyen Thai Ngoc Duy
0 siblings, 0 replies; 8+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2010-09-08 9:58 UTC (permalink / raw)
To: Elijah Newren; +Cc: git, Junio C Hamano
2010/9/8 Elijah Newren <newren@gmail.com>:
> 2010/9/7 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>:
>> Changes from last time is tree_entry_interesting() now takes
>> struct exclude * as the pathspecs.
>>
>> I think there'll be a bit of performance loss because diff_options.el
>> is not initialized from the beginning. But that requires more changes
>> outside tree-diff.c (makes sure that diff_options.el is copied properly,
>> makes sure that diff_tree_setup_* is called ...) So one step at a time.
>> I'm working on it.
>
> Looks reasonable to me so far. I believe your series already makes
> nr_paths, paths, and pathlens fields from diff_options unused (other
> than via exclude_list) -- yes? If so, that suggests that we could
> just modify diff_tree_setup_paths() to do the work that your new
> diff_tree_setup_exclude_lists() is doing (and to take an exclude_list*
> instead of a diff_options*). Then you wouldn't need to worry about
> doing the setup "on-the-fly" and the performance differences should go
> away.
They are used elsewhere, passed around as prune data, even fed to
read_cache_preload().. so they won't go away soon.
> Am I understanding correctly, and is that the route you're going?
Yes. Except that both nr_paths, paths and pathlens will stay along with
exclude_list. Getting rid of "paths" takes time (the other two fields are
easier to deal with).
--
Duy
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2010-09-08 10:03 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-07 15:47 [PATCH 0/5] en/object-list-with-pathspec (v3?) Nguyễn Thái Ngọc Duy
2010-09-07 15:47 ` [PATCH 1/5] diff-no-index.c: rename read_directory() to read_dir() Nguyễn Thái Ngọc Duy
2010-09-07 15:48 ` [PATCH 2/5] Add testcases showing how pathspecs are ignored with rev-list --objects Nguyễn Thái Ngọc Duy
2010-09-07 15:48 ` [PATCH 3/5] tree-walk: move tree_entry_interesting() from tree-diff.c Nguyễn Thái Ngọc Duy
2010-09-07 15:48 ` [PATCH 4/5] tree_entry_interesting(): remove dependency on struct diff_options Nguyễn Thái Ngọc Duy
2010-09-07 15:48 ` [PATCH 5/5] Make rev-list --objects work together with pathspecs Nguyễn Thái Ngọc Duy
2010-09-08 7:47 ` [PATCH 0/5] en/object-list-with-pathspec (v3?) Elijah Newren
2010-09-08 9:58 ` Nguyen Thai Ngoc Duy
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).