summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: d4a9ce7)
raw | patch | inline | side by side (parent: d4a9ce7)
author | Junio C Hamano <junkio@cox.net> | |
Tue, 30 Aug 2005 00:19:47 +0000 (17:19 -0700) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Tue, 30 Aug 2005 00:19:47 +0000 (17:19 -0700) |
Earlier show-branch gave names only to commits reachable via first
parent ancestry chain. Change the naming code to name everybody.
The original idea was to stop at the first merge point in the
topological order, and --more=<n> to show commits until we show <n>
more extra merge points. However depending on the order of how we
discover the commits, it additionally showed parents of the <n>th
merge points, which was unnecessary.
Signed-off-by: Junio C Hamano <junkio@cox.net>
parent ancestry chain. Change the naming code to name everybody.
The original idea was to stop at the first merge point in the
topological order, and --more=<n> to show commits until we show <n>
more extra merge points. However depending on the order of how we
discover the commits, it additionally showed parents of the <n>th
merge points, which was unnecessary.
Signed-off-by: Junio C Hamano <junkio@cox.net>
show-branch.c | patch | blob | history |
diff --git a/show-branch.c b/show-branch.c
index 2a4e1768adc88e25dc108d6c9b323da2c52f5b1c..958a5e884afdf8bc21d672242d6bbee8d3c7340a 100644 (file)
--- a/show-branch.c
+++ b/show-branch.c
}
struct commit_name {
- int head_rev; /* which head's ancestor? */
- int generation; /* how many parents away from head_rev */
+ const char *head_name; /* which head's ancestor? */
+ int generation; /* how many parents away from head_name */
};
-/* Name the commit as nth generation ancestor of head_rev;
+/* Name the commit as nth generation ancestor of head_name;
* we count only the first-parent relationship for naming purposes.
*/
-static void name_commit(struct commit *commit, int head_rev, int nth)
+static void name_commit(struct commit *commit, const char *head_name, int nth)
{
struct commit_name *name;
if (!commit->object.util)
commit->object.util = xmalloc(sizeof(struct commit_name));
name = commit->object.util;
- name->head_rev = head_rev;
+ name->head_name = head_name;
name->generation = nth;
}
/* Parent is the first parent of the commit. We may name it
- * as (n+1)th generation ancestor of the same head_rev as
+ * as (n+1)th generation ancestor of the same head_name as
* commit is nth generation ancestore of, if that generation
* number is better than the name it already has.
*/
return;
if (!parent_name ||
commit_name->generation + 1 < parent_name->generation)
- name_commit(parent, commit_name->head_rev,
+ name_commit(parent, commit_name->head_name,
commit_name->generation + 1);
}
+static int name_first_parent_chain(struct commit *c)
+{
+ int i = 0;
+ while (c) {
+ struct commit *p;
+ if (!c->object.util)
+ break;
+ if (!c->parents)
+ break;
+ p = c->parents->item;
+ if (!p->object.util) {
+ name_parent(c, p);
+ i++;
+ }
+ c = p;
+ }
+ return i;
+}
+
+static void name_commits(struct commit_list *list,
+ struct commit **rev,
+ char **ref_name,
+ int num_rev)
+{
+ struct commit_list *cl;
+ struct commit *c;
+ int i;
+
+ /* First give names to the given heads */
+ for (cl = list; cl; cl = cl->next) {
+ c = cl->item;
+ if (c->object.util)
+ continue;
+ for (i = 0; i < num_rev; i++) {
+ if (rev[i] == c) {
+ name_commit(c, ref_name[i], 0);
+ break;
+ }
+ }
+ }
+
+ /* Then commits on the first parent ancestry chain */
+ do {
+ i = 0;
+ for (cl = list; cl; cl = cl->next) {
+ i += name_first_parent_chain(cl->item);
+ }
+ } while (i);
+
+ /* Finally, any unnamed commits */
+ do {
+ i = 0;
+ for (cl = list; cl; cl = cl->next) {
+ struct commit_list *parents;
+ struct commit_name *n;
+ int nth;
+ c = cl->item;
+ if (!c->object.util)
+ continue;
+ n = c->object.util;
+ parents = c->parents;
+ nth = 0;
+ while (parents) {
+ struct commit *p = parents->item;
+ char newname[1000];
+ parents = parents->next;
+ nth++;
+ if (p->object.util)
+ continue;
+ sprintf(newname, "%s^%d", n->head_name, nth);
+ name_commit(p, strdup(newname), 0);
+ i++;
+ name_first_parent_chain(p);
+ }
+ }
+ } while (i);
+}
+
static int mark_seen(struct commit *commit, struct commit_list **seen_p)
{
if (!commit->object.flags) {
struct commit_list *parents;
struct commit *commit = pop_one_commit(list_p);
int flags = commit->object.flags & all_mask;
- int nth_parent = 0;
int still_interesting = !!interesting(*list_p);
if (!still_interesting && extra < 0)
struct commit *p = parents->item;
int this_flag = p->object.flags;
parents = parents->next;
- nth_parent++;
- if (nth_parent == 1)
- name_parent(commit, p);
-
if ((this_flag & flags) == flags)
continue;
parse_commit(p);
}
}
-static void show_one_commit(struct commit *commit, char **head_name)
+static void show_one_commit(struct commit *commit)
{
char pretty[128], *cp;
struct commit_name *name = commit->object.util;
cp = pretty + 8;
else
cp = pretty;
- if (name && head_name) {
- printf("[%s", head_name[name->head_rev]);
+ if (name && name->head_name) {
+ printf("[%s", name->head_name);
if (name->generation)
printf("~%d", name->generation);
printf("] ");
struct commit_list *list = NULL, *seen = NULL;
int num_rev, i, extra = 0;
int all_heads = 0, all_tags = 0;
+ int all_mask, all_revs, shown_merge_point;
char head_path[128];
int head_path_len;
unsigned char head_sha1[20];
die("cannot find commit %s (%s)",
ref_name[num_rev], revkey);
parse_commit(commit);
- if (!commit->object.util)
- name_commit(commit, num_rev, 0);
mark_seen(commit, &seen);
/* rev#0 uses bit REV_SHIFT, rev#1 uses bit REV_SHIFT+1,
for (j = 0; j < i; j++)
putchar(' ');
printf("%c [%s] ", is_head ? '*' : '!', ref_name[i]);
- show_one_commit(rev[i], NULL);
+ show_one_commit(rev[i]);
}
for (i = 0; i < num_rev; i++)
putchar('-');
putchar('\n');
}
- label = ref_name;
+ /* Sort topologically */
+ sort_in_topological_order(&seen);
+
+ /* Give names to commits */
+ name_commits(seen, rev, ref_name, num_rev);
+
+ all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
+ all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
+ shown_merge_point = 0;
+
while (seen) {
struct commit *commit = pop_one_commit(&seen);
int this_flag = commit->object.flags;
+ int is_merge_point = (this_flag & all_revs) == all_revs;
static char *obvious[] = { "" };
- if ((this_flag & UNINTERESTING) && (--extra < 0))
- break;
+ if (is_merge_point)
+ shown_merge_point = 1;
+
if (1 < num_rev) {
for (i = 0; i < num_rev; i++)
putchar((this_flag & (1u << (i + REV_SHIFT)))
? '+' : ' ');
putchar(' ');
}
- show_one_commit(commit, label);
+ show_one_commit(commit);
if (num_rev == 1)
label = obvious;
+ if (shown_merge_point && is_merge_point)
+ if (--extra < 0)
+ break;
}
return 0;
}