* [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 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.