revision.c: add BOTTOM flag for commits

When performing edge-based operations on the revision graph, it can be useful to be able to identify the INTERESTING graph's connection(s) to the bottom commit(s) specified by the user. Conceptually when the user specifies "A..B" (== B ^A), they are asking for the history from A to B. The first connection from A onto the INTERESTING graph is part of that history, and should be considered. If we consider only INTERESTING nodes and their connections, then we're really only considering the history from A's immediate descendants to B. This patch does not change behaviour, but adds a new BOTTOM flag to indicate the bottom commits specified by the user, ready to be used by following patches. We immediately use the BOTTOM flag to return collect_bottom_commits() to its original approach of examining the pending commit list rather than the command line. This will ensure alignment of the definition of "bottom" with future patches. Signed-off-by: Kevin Bracey <kevin@bracey.fi> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Kevin Bracey committed May 16, 2013 at 18:32 UTC 7f34a46ff57121910c9ad697c2809a2d01ed1673
2 files changed +18 -19
revision.c
+16 -18
@@ -909,16 +909,12 @@ static void limit_to_ancestry(struct commit_list *bottom, struct commit_list *li
909 * to filter the result of "A..B" further to the ones that can actually
910 * reach A.
911 */
912 -static struct commit_list *collect_bottom_commits(struct rev_info *revs)
912 +static struct commit_list *collect_bottom_commits(struct commit_list *list)
913 {
914 - struct commit_list *bottom = NULL;
915 - int i;
916 - for (i = 0; i < revs->cmdline.nr; i++) {
917 - struct rev_cmdline_entry *elem = &revs->cmdline.rev[i];
918 - if ((elem->flags & UNINTERESTING) &&
919 - elem->item->type == OBJ_COMMIT)
920 - commit_list_insert((struct commit *)elem->item, &bottom);
921 - }
914 + struct commit_list *elem, *bottom = NULL;
915 + for (elem = list; elem; elem = elem->next)
916 + if (elem->item->object.flags & BOTTOM)
917 + commit_list_insert(elem->item, &bottom);
918 return bottom;
919 }
920
@@ -949,7 +945,7 @@ static int limit_list(struct rev_info *revs)
945 struct commit_list *bottom = NULL;
946
947 if (revs->ancestry_path) {
952 - bottom = collect_bottom_commits(revs);
948 + bottom = collect_bottom_commits(list);
949 if (!bottom)
950 die("--ancestry-path given but there are no bottom commits");
951 }
@@ -1121,7 +1117,7 @@ static int add_parents_only(struct rev_info *revs, const char *arg_, int flags)
1117 const char *arg = arg_;
1118
1119 if (*arg == '^') {
1124 - flags ^= UNINTERESTING;
1120 + flags ^= UNINTERESTING | BOTTOM;
1121 arg++;
1122 }
1123 if (get_sha1_committish(arg, sha1))
@@ -1213,8 +1209,8 @@ static void prepare_show_merge(struct rev_info *revs)
1209 add_pending_object(revs, &head->object, "HEAD");
1210 add_pending_object(revs, &other->object, "MERGE_HEAD");
1211 bases = get_merge_bases(head, other, 1);
1216 - add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING);
1217 - add_pending_commit_list(revs, bases, UNINTERESTING);
1212 + add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING | BOTTOM);
1213 + add_pending_commit_list(revs, bases, UNINTERESTING | BOTTOM);
1214 free_commit_list(bases);
1215 head->object.flags |= SYMMETRIC_LEFT;
1216
@@ -1250,13 +1246,15 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi
1246 int cant_be_filename = revarg_opt & REVARG_CANNOT_BE_FILENAME;
1247 unsigned get_sha1_flags = 0;
1248
1249 + flags = flags & UNINTERESTING ? flags | BOTTOM : flags & ~BOTTOM;
1250 +
1251 dotdot = strstr(arg, "..");
1252 if (dotdot) {
1253 unsigned char from_sha1[20];
1254 const char *next = dotdot + 2;
1255 const char *this = arg;
1256 int symmetric = *next == '.';
1259 - unsigned int flags_exclude = flags ^ UNINTERESTING;
1257 + unsigned int flags_exclude = flags ^ (UNINTERESTING | BOTTOM);
1258 static const char head_by_default[] = "HEAD";
1259 unsigned int a_flags;
1260
@@ -1332,13 +1330,13 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi
1330 dotdot = strstr(arg, "^!");
1331 if (dotdot && !dotdot[2]) {
1332 *dotdot = 0;
1335 - if (!add_parents_only(revs, arg, flags ^ UNINTERESTING))
1333 + if (!add_parents_only(revs, arg, flags ^ (UNINTERESTING | BOTTOM)))
1334 *dotdot = '^';
1335 }
1336
1337 local_flags = 0;
1338 if (*arg == '^') {
1341 - local_flags = UNINTERESTING;
1339 + local_flags = UNINTERESTING | BOTTOM;
1340 arg++;
1341 }
1342
@@ -1815,7 +1813,7 @@ static int handle_revision_pseudo_opt(const char *submodule,
1813 handle_refs(submodule, revs, *flags, for_each_branch_ref_submodule);
1814 } else if (!strcmp(arg, "--bisect")) {
1815 handle_refs(submodule, revs, *flags, for_each_bad_bisect_ref);
1818 - handle_refs(submodule, revs, *flags ^ UNINTERESTING, for_each_good_bisect_ref);
1816 + handle_refs(submodule, revs, *flags ^ (UNINTERESTING | BOTTOM), for_each_good_bisect_ref);
1817 revs->bisect = 1;
1818 } else if (!strcmp(arg, "--tags")) {
1819 handle_refs(submodule, revs, *flags, for_each_tag_ref_submodule);
@@ -1841,7 +1839,7 @@ static int handle_revision_pseudo_opt(const char *submodule,
1839 } else if (!strcmp(arg, "--reflog")) {
1840 handle_reflog(revs, *flags);
1841 } else if (!strcmp(arg, "--not")) {
1844 - *flags ^= UNINTERESTING;
1842 + *flags ^= UNINTERESTING | BOTTOM;
1843 } else if (!strcmp(arg, "--no-walk")) {
1844 revs->no_walk = REVISION_WALK_NO_WALK_SORTED;
1845 } else if (!prefixcmp(arg, "--no-walk=")) {
revision.h
+2 -1
@@ -15,7 +15,8 @@
15 #define ADDED (1u<<7) /* Parents already parsed and added? */
16 #define SYMMETRIC_LEFT (1u<<8)
17 #define PATCHSAME (1u<<9)
18 -#define ALL_REV_FLAGS ((1u<<10)-1)
18 +#define BOTTOM (1u<<10)
19 +#define ALL_REV_FLAGS ((1u<<11)-1)
20
21 #define DECORATE_SHORT_REFS 1
22 #define DECORATE_FULL_REFS 2