summaryrefslogtreecommitdiff
path: root/revision.c
diff options
context:
space:
mode:
authorRene Scharfe <rene.scharfe@lsrfire.ath.cx>2006-07-01 23:29:37 (GMT)
committerJunio C Hamano <junkio@cox.net>2006-07-02 01:13:47 (GMT)
commit0d2c9d67d9e1a2fd87b2daeefffffaff0b3f3a49 (patch)
tree30ea078fdd6661fa0b1f469dbc1570f41a245a93 /revision.c
parent31609c17251f368584f7b94d44b06194112b4251 (diff)
downloadgit-0d2c9d67d9e1a2fd87b2daeefffffaff0b3f3a49.zip
git-0d2c9d67d9e1a2fd87b2daeefffffaff0b3f3a49.tar.gz
git-0d2c9d67d9e1a2fd87b2daeefffffaff0b3f3a49.tar.bz2
Add '...' operator for revisions
'A...B' is a shortcut for 'A B --not $(git-merge-base --all A B)'. This XOR-like operation is called symmetric difference in set theory. The symbol '...' has been chosen because it's rather similar to the existing '..' operator and the somewhat more natural caret ('^') is already taken. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'revision.c')
-rw-r--r--revision.c48
1 files changed, 39 insertions, 9 deletions
diff --git a/revision.c b/revision.c
index b963f2a..9eb0b6d 100644
--- a/revision.c
+++ b/revision.c
@@ -536,6 +536,18 @@ void init_revisions(struct rev_info *revs)
diff_setup(&revs->diffopt);
}
+static void add_pending_commit_list(struct rev_info *revs,
+ struct commit_list *commit_list,
+ unsigned int flags)
+{
+ while (commit_list) {
+ struct object *object = &commit_list->item->object;
+ object->flags |= flags;
+ add_pending_object(revs, object, sha1_to_hex(object->sha1));
+ commit_list = commit_list->next;
+ }
+}
+
/*
* Parse revision information, filling in the "rev_info" structure,
* and removing the used arguments from the argument list.
@@ -771,27 +783,45 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
unsigned char from_sha1[20];
const char *next = dotdot + 2;
const char *this = arg;
+ int symmetric = *next == '.';
+ unsigned int flags_exclude = flags ^ UNINTERESTING;
+
*dotdot = 0;
+ next += symmetric;
+
if (!*next)
next = "HEAD";
if (dotdot == arg)
this = "HEAD";
if (!get_sha1(this, from_sha1) &&
!get_sha1(next, sha1)) {
- struct object *exclude;
- struct object *include;
-
- 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);
+ struct commit *a, *b;
+ struct commit_list *exclude;
+
+ a = lookup_commit_reference(from_sha1);
+ b = lookup_commit_reference(sha1);
+ if (!a || !b) {
+ die(symmetric ?
+ "Invalid symmetric difference expression %s...%s" :
+ "Invalid revision range %s..%s",
+ arg, next);
+ }
if (!seen_dashdash) {
*dotdot = '.';
verify_non_filename(revs->prefix, arg);
}
- add_pending_object(revs, exclude, this);
- add_pending_object(revs, include, next);
+
+ if (symmetric) {
+ exclude = get_merge_bases_clean(a, b);
+ add_pending_commit_list(revs, exclude,
+ flags_exclude);
+ a->object.flags |= flags;
+ } else
+ a->object.flags |= flags_exclude;
+ b->object.flags |= flags;
+ add_pending_object(revs, &a->object, this);
+ add_pending_object(revs, &b->object, next);
continue;
}
*dotdot = '.';