On Sat, Jul 01, 2006 at 07:45:33PM -0400, Daniel Barkalow wrote: > That is: (this only has the logic portion, and it's against master, so it > isn't actually a really working patch or anything; also, it doesn't handle > "--not a...b" correctly, whatever that should mean) [concept patch snipped] You mean something like the patch below? It seems to work, but in my unscientific tests it's significant slower than the version based on get_merge_bases() (0.17s vs 0.05s for "git-rev-list 89719209...262a6ef7 66ae0c77...ced9456a"). Did I do something wrong? You had no mark_parents_left_right() in your patch. I added it because otherwise it wouldn't remove any common commits. Was this supposed to work some other way? We still need an automatic test case, and a better benchmark. diff --git a/revision.c b/revision.c index ebee05a..8c494ee 100644 --- a/revision.c +++ b/revision.c @@ -339,6 +339,20 @@ static void try_to_simplify_commit(struc commit->object.flags |= TREECHANGE; } +static void mark_parents_left_right(struct commit *commit) +{ + unsigned int flags = commit->object.flags & (RIGHT_HALF | LEFT_HALF); + struct commit_list *parents = commit->parents; + + while (parents) { + struct commit *p = parents->item; + p->object.flags |= flags; + if (p->parents) + mark_parents_left_right(p); + parents = parents->next; + } +} + static void add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list) { struct commit_list *parent = commit->parents; @@ -347,6 +361,13 @@ static void add_parents_to_list(struct r return; commit->object.flags |= ADDED; + if (commit->object.flags & (RIGHT_HALF | LEFT_HALF)) { + if (commit->object.flags & RIGHT_HALF && + commit->object.flags & LEFT_HALF) + commit->object.flags |= UNINTERESTING; + mark_parents_left_right(commit); + } + /* * If the commit is uninteresting, don't try to * prune parents - we want the maximal uninteresting @@ -772,7 +793,10 @@ int setup_revisions(int argc, const char unsigned char from_sha1[20]; const char *next = dotdot + 2; const char *this = arg; + int symmetric = *next == '.'; + *dotdot = 0; + next += symmetric; if (!*next) next = "HEAD"; if (dotdot == arg) @@ -782,8 +806,13 @@ int setup_revisions(int argc, const char struct object *exclude; struct object *include; - exclude = get_reference(revs, this, from_sha1, flags ^ UNINTERESTING); - include = get_reference(revs, next, sha1, flags); + if (symmetric) { + exclude = get_reference(revs, this, from_sha1, flags | LEFT_HALF); + include = get_reference(revs, next, sha1, flags | RIGHT_HALF); + } else { + exclude = get_reference(revs, this, from_sha1, flags ^ UNINTERESTING); + include = get_reference(revs, next, sha1, flags); + } if (!exclude || !include) die("Invalid revision range %s..%s", arg, next); diff --git a/revision.h b/revision.h index c010a08..0090232 100644 --- a/revision.h +++ b/revision.h @@ -9,6 +9,8 @@ #define TMP_MARK (1u<<4) /* for isolated #define BOUNDARY (1u<<5) #define BOUNDARY_SHOW (1u<<6) #define ADDED (1u<<7) /* Parents already parsed and added? */ +#define RIGHT_HALF (1u<<8) +#define LEFT_HALF (1u<<9) struct rev_info; struct log_info; - : send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html