Mercurial > hg
changeset 4347:70d1491d3db2
Merge with crew
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Sun, 15 Apr 2007 18:42:51 -0500 |
parents | c593e502f7fd (current diff) ec64f263e49a (diff) |
children | 69109aa0cddd |
files | |
diffstat | 4 files changed, 720 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/sample.hgrc Sun Apr 15 18:42:38 2007 -0500 +++ b/contrib/sample.hgrc Sun Apr 15 18:42:51 2007 -0500 @@ -43,6 +43,11 @@ # hgext.gpg = +### graphlog - ASCII graph log +### hg help glog + +# hgext.graphlog = + ### hgk - GUI repository browser ### hg help view
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgext/graphlog.py Sun Apr 15 18:42:51 2007 -0500 @@ -0,0 +1,266 @@ +# ASCII graph log extension for Mercurial +# +# Copyright 2007 Joel Rosdahl <joel@rosdahl.net> +# +# This software may be used and distributed according to the terms of +# the GNU General Public License, incorporated herein by reference. + +import sys +from mercurial.cmdutil import revrange, show_changeset +from mercurial.i18n import _ +from mercurial.node import nullid, nullrev +from mercurial.util import Abort + +def revision_grapher(repo, start_rev, stop_rev): + """incremental revision grapher + + This generator function walks through the revision history from + revision start_rev to revision stop_rev (which must be less than + or equal to start_rev) and for each revision emits tuples with the + following elements: + + - Current revision. + - Current node. + - Column of the current node in the set of ongoing edges. + - Edges; a list of (col, next_col) indicating the edges between + the current node and its parents. + - Number of columns (ongoing edges) in the current revision. + - The difference between the number of columns (ongoing edges) + in the next revision and the number of columns (ongoing edges) + in the current revision. That is: -1 means one column removed; + 0 means no columns added or removed; 1 means one column added. + """ + + assert start_rev >= stop_rev + curr_rev = start_rev + revs = [] + while curr_rev >= stop_rev: + node = repo.changelog.node(curr_rev) + + # Compute revs and next_revs. + if curr_rev not in revs: + # New head. + revs.append(curr_rev) + rev_index = revs.index(curr_rev) + next_revs = revs[:] + + # Add parents to next_revs. + parents = get_rev_parents(repo, curr_rev) + parents_to_add = [] + for parent in parents: + if parent not in next_revs: + parents_to_add.append(parent) + parents_to_add.sort() + next_revs[rev_index:rev_index + 1] = parents_to_add + + edges = [] + for parent in parents: + edges.append((rev_index, next_revs.index(parent))) + + n_columns_diff = len(next_revs) - len(revs) + yield (curr_rev, node, rev_index, edges, len(revs), n_columns_diff) + + revs = next_revs + curr_rev -= 1 + +def get_rev_parents(repo, rev): + return [x for x in repo.changelog.parentrevs(rev) if x != nullrev] + +def fix_long_right_edges(edges): + for (i, (start, end)) in enumerate(edges): + if end > start: + edges[i] = (start, end + 1) + +def draw_edges(edges, nodeline, interline): + for (start, end) in edges: + if start == end + 1: + interline[2 * end + 1] = "/" + elif start == end - 1: + interline[2 * start + 1] = "\\" + elif start == end: + interline[2 * start] = "|" + else: + nodeline[2 * end] = "+" + if start > end: + (start, end) = (end,start) + for i in range(2 * start + 1, 2 * end): + if nodeline[i] != "+": + nodeline[i] = "-" + +def format_line(line, level, logstr): + text = "%-*s %s" % (2 * level, "".join(line), logstr) + return "%s\n" % text.rstrip() + +def get_nodeline_edges_tail( + node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail): + if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0: + # Still going in the same non-vertical direction. + if n_columns_diff == -1: + start = max(node_index + 1, p_node_index) + tail = ["|", " "] * (start - node_index - 1) + tail.extend(["/", " "] * (n_columns - start)) + return tail + else: + return ["\\", " "] * (n_columns - node_index - 1) + else: + return ["|", " "] * (n_columns - node_index - 1) + +def get_padding_line(ni, n_columns, edges): + line = [] + line.extend(["|", " "] * ni) + if (ni, ni - 1) in edges or (ni, ni) in edges: + # (ni, ni - 1) (ni, ni) + # | | | | | | | | + # +---o | | o---+ + # | | c | | c | | + # | |/ / | |/ / + # | | | | | | + c = "|" + else: + c = " " + line.extend([c, " "]) + line.extend(["|", " "] * (n_columns - ni - 1)) + return line + +def get_limit(limit_opt): + if limit_opt: + try: + limit = int(limit_opt) + except ValueError: + raise Abort(_("limit must be a positive integer")) + if limit <= 0: + raise Abort(_("limit must be positive")) + else: + limit = sys.maxint + return limit + +def get_revs(repo, rev_opt): + if rev_opt: + revs = revrange(repo, rev_opt) + return (max(revs), min(revs)) + else: + return (repo.changelog.count() - 1, 0) + +def graphlog(ui, repo, *args, **opts): + """show revision history alongside an ASCII revision graph + + Print a revision history alongside a revision graph drawn with + ASCII characters. + + Nodes printed as an @ character are parents of the working + directory. + """ + + limit = get_limit(opts["limit"]) + (start_rev, stop_rev) = get_revs(repo, opts["rev"]) + stop_rev = max(stop_rev, start_rev - limit + 1) + if start_rev == nullrev: + return + cs_printer = show_changeset(ui, repo, opts) + grapher = revision_grapher(repo, start_rev, stop_rev) + repo_parents = repo.dirstate.parents() + prev_n_columns_diff = 0 + prev_node_index = 0 + + for (rev, node, node_index, edges, n_columns, n_columns_diff) in grapher: + # log_strings is the list of all log strings to draw alongside + # the graph. + ui.pushbuffer() + cs_printer.show(rev, node) + log_strings = ui.popbuffer().split("\n")[:-1] + + if n_columns_diff == -1: + # Transform + # + # | | | | | | + # o | | into o---+ + # |X / |/ / + # | | | | + fix_long_right_edges(edges) + + # add_padding_line says whether to rewrite + # + # | | | | | | | | + # | o---+ into | o---+ + # | / / | | | # <--- padding line + # o | | | / / + # o | | + add_padding_line = \ + len(log_strings) > 2 and \ + n_columns_diff == -1 and \ + [x for (x, y) in edges if x + 1 < y] + + # fix_nodeline_tail says whether to rewrite + # + # | | o | | | | o | | + # | | |/ / | | |/ / + # | o | | into | o / / # <--- fixed nodeline tail + # | |/ / | |/ / + # o | | o | | + fix_nodeline_tail = len(log_strings) <= 2 and not add_padding_line + + # nodeline is the line containing the node character (@ or o). + nodeline = ["|", " "] * node_index + if node in repo_parents: + node_ch = "@" + else: + node_ch = "o" + nodeline.extend([node_ch, " "]) + + nodeline.extend( + get_nodeline_edges_tail( + node_index, prev_node_index, n_columns, n_columns_diff, + prev_n_columns_diff, fix_nodeline_tail)) + + # shift_interline is the line containing the non-vertical + # edges between this entry and the next. + shift_interline = ["|", " "] * node_index + if n_columns_diff == -1: + n_spaces = 1 + edge_ch = "/" + elif n_columns_diff == 0: + n_spaces = 2 + edge_ch = "|" + else: + n_spaces = 3 + edge_ch = "\\" + shift_interline.extend(n_spaces * [" "]) + shift_interline.extend([edge_ch, " "] * (n_columns - node_index - 1)) + + # Draw edges from the current node to its parents. + draw_edges(edges, nodeline, shift_interline) + + # lines is the list of all graph lines to print. + lines = [nodeline] + if add_padding_line: + lines.append(get_padding_line(node_index, n_columns, edges)) + lines.append(shift_interline) + + # Make sure that there are as many graph lines as there are + # log strings. + while len(log_strings) < len(lines): + log_strings.append("") + if len(lines) < len(log_strings): + extra_interline = ["|", " "] * (n_columns + n_columns_diff) + while len(lines) < len(log_strings): + lines.append(extra_interline) + + # Print lines. + indentation_level = max(n_columns, n_columns + n_columns_diff) + for (line, logstr) in zip(lines, log_strings): + ui.write(format_line(line, indentation_level, logstr)) + + # ...and start over. + prev_node_index = node_index + prev_n_columns_diff = n_columns_diff + +cmdtable = { + "glog": + (graphlog, + [("l", "limit", "", _("limit number of changes displayed")), + ("p", "patch", False, _("show patch")), + ("r", "rev", [], _("show the specified revision or range")), + ("", "style", "", _("display using template map file")), + ("", "template", "", _("display with template"))], + "hg glog [OPTIONS]"), +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-glog Sun Apr 15 18:42:51 2007 -0500 @@ -0,0 +1,140 @@ +#!/bin/sh + +# @ (34) head +# | +# | o (33) head +# | | +# o | (32) expand +# |\ \ +# | o \ (31) expand +# | |\ \ +# | | o \ (30) expand +# | | |\ \ +# | | | o | (29) regular commit +# | | | | | +# | | o | | (28) merge zero known +# | | |\ \ \ +# o | | | | | (27) collapse +# |/ / / / / +# | | o---+ (26) merge one known; far right +# | | | | | +# +---o | | (25) merge one known; far left +# | | | | | +# | | o | | (24) merge one known; immediate right +# | | |\| | +# | | o | | (23) merge one known; immediate left +# | |/| | | +# +---o---+ (22) merge two known; one far left, one far right +# | | / / +# o | | | (21) expand +# |\ \ \ \ +# | o---+-+ (20) merge two known; two far right +# | / / / +# o | | | (19) expand +# |\ \ \ \ +# +---+---o (18) merge two known; two far left +# | | | | +# | o | | (17) expand +# | |\ \ \ +# | | o---+ (16) merge two known; one immediate right, one near right +# | | |/ / +# o | | | (15) expand +# |\ \ \ \ +# | o-----+ (14) merge two known; one immediate right, one far right +# | |/ / / +# o | | | (13) expand +# |\ \ \ \ +# +---o | | (12) merge two known; one immediate right, one far left +# | | |/ / +# | o | | (11) expand +# | |\ \ \ +# | | o---+ (10) merge two known; one immediate left, one near right +# | |/ / / +# o | | | (9) expand +# |\ \ \ \ +# | o-----+ (8) merge two known; one immediate left, one far right +# |/ / / / +# o | | | (7) expand +# |\ \ \ \ +# +---o | | (6) merge two known; one immediate left, one far left +# | |/ / / +# | o | | (5) expand +# | |\ \ \ +# | | o | | (4) merge two known; one immediate left, one immediate right +# | |/|/ / +# | o / / (3) collapse +# |/ / / +# o / / (2) collapse +# |/ / +# o / (1) collapse +# |/ +# o (0) root + +set -e + +commit() +{ + rev=$1 + msg=$2 + shift 2 + if [ "$#" -gt 0 ]; then + hg debugsetparents "$@" + fi + echo $rev > $rev + hg add $rev + hg ci -d "$rev 0" -m "($rev) $msg" +} + +echo "[extensions]" >> $HGRCPATH +echo "graphlog=" >> $HGRCPATH + +echo % init +hg init repo + +cd repo + +echo % empty repo +hg glog + +echo % building tree +commit 0 "root" +commit 1 "collapse" 0 +commit 2 "collapse" 1 +commit 3 "collapse" 2 +commit 4 "merge two known; one immediate left, one immediate right" 1 3 +commit 5 "expand" 3 4 +commit 6 "merge two known; one immediate left, one far left" 2 5 +commit 7 "expand" 2 5 +commit 8 "merge two known; one immediate left, one far right" 0 7 +commit 9 "expand" 7 8 +commit 10 "merge two known; one immediate left, one near right" 0 6 +commit 11 "expand" 6 10 +commit 12 "merge two known; one immediate right, one far left" 1 9 +commit 13 "expand" 9 11 +commit 14 "merge two known; one immediate right, one far right" 0 12 +commit 15 "expand" 13 14 +commit 16 "merge two known; one immediate right, one near right" 0 1 +commit 17 "expand" 12 16 +commit 18 "merge two known; two far left" 1 15 +commit 19 "expand" 15 17 +commit 20 "merge two known; two far right" 0 18 +commit 21 "expand" 19 20 +commit 22 "merge two known; one far left, one far right" 18 21 +commit 23 "merge one known; immediate left" 1 22 +commit 24 "merge one known; immediate right" 0 23 +commit 25 "merge one known; far left" 21 24 +commit 26 "merge one known; far right" 18 25 +commit 27 "collapse" 21 +commit 28 "merge zero known" 1 26 +commit 29 "regular commit" 0 +commit 30 "expand" 28 29 +commit 31 "expand" 21 30 +commit 32 "expand" 27 31 +commit 33 "head" 18 +commit 34 "head" 32 + +echo % glog -q +hg glog -q + +echo % glog +hg glog
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-glog.out Sun Apr 15 18:42:51 2007 -0500 @@ -0,0 +1,309 @@ +% init +% empty repo +% building tree +% glog -q +@ 34:0eed7cd895e0 +| +| o 33:2e9d1b521374 +| | +o | 32:77f7d8438a3c +|\ \ +| o \ 31:82ee55204a79 +| |\ \ +| | o \ 30:777dfc428649 +| | |\ \ +| | | o | 29:f8e7fee63353 +| | | | | +| | o | | 28:4b6e9bd48cf9 +| | |\ \ \ +o | | | | | 27:e9e08174cd30 +|/ / / / / +| | o---+ 26:720dc079a855 +| | | | | ++---o | | 25:9d4ed048d013 +| | | | | +| | o | | 24:4a68967db00d +| | |\| | +| | o | | 23:bc31393cabdf +| |/| | | ++---o---+ 22:a37f2ea6ebc6 +| | / / +o | | | 21:e758e8f4ace9 +|\ \ \ \ +| o---+-+ 20:aeccadad74b4 +| / / / +o | | | 19:138069b5dad7 +|\ \ \ \ ++---+---o 18:5a8c9a29ef81 +| | | | +| o | | 17:43e52b935494 +| |\ \ \ +| | o---+ 16:449a2f9562a4 +| | |/ / +o | | | 15:c0b4283d4c1d +|\ \ \ \ +| o-----+ 14:9d533950abf0 +| |/ / / +o | | | 13:c39d0a2b8165 +|\ \ \ \ ++---o | | 12:74dc7aea4494 +| | |/ / +| o | | 11:c3c395dd8b98 +| |\ \ \ +| | o---+ 10:8094c50149ef +| |/ / / +o | | | 9:79ab1812f961 +|\ \ \ \ +| o-----+ 8:d7aa38594334 +|/ / / / +o | | | 7:699392d1259e +|\ \ \ \ ++---o | | 6:0ca7c061cf45 +| |/ / / +| o | | 5:3589c3c477ab +| |\ \ \ +| | o | | 4:e2cad8233c77 +| |/|/ / +| o / / 3:02173ffbf857 +|/ / / +o / / 2:e8ea2256f9ec +|/ / +o / 1:3cae7826a707 +|/ +o 0:7aa22e58e8c1 + +% glog +@ changeset: 34:0eed7cd895e0 +| tag: tip +| parent: 32:77f7d8438a3c +| user: test +| date: Thu Jan 01 00:00:34 1970 +0000 +| summary: (34) head +| +| o changeset: 33:2e9d1b521374 +| | parent: 18:5a8c9a29ef81 +| | user: test +| | date: Thu Jan 01 00:00:33 1970 +0000 +| | summary: (33) head +| | +o | changeset: 32:77f7d8438a3c +|\ \ parent: 27:e9e08174cd30 +| | | parent: 31:82ee55204a79 +| | | user: test +| | | date: Thu Jan 01 00:00:32 1970 +0000 +| | | summary: (32) expand +| | | +| o | changeset: 31:82ee55204a79 +| |\ \ parent: 21:e758e8f4ace9 +| | | | parent: 30:777dfc428649 +| | | | user: test +| | | | date: Thu Jan 01 00:00:31 1970 +0000 +| | | | summary: (31) expand +| | | | +| | o | changeset: 30:777dfc428649 +| | |\ \ parent: 28:4b6e9bd48cf9 +| | | | | parent: 29:f8e7fee63353 +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:30 1970 +0000 +| | | | | summary: (30) expand +| | | | | +| | | o | changeset: 29:f8e7fee63353 +| | | | | parent: 0:7aa22e58e8c1 +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:29 1970 +0000 +| | | | | summary: (29) regular commit +| | | | | +| | o | | changeset: 28:4b6e9bd48cf9 +| | |\ \ \ parent: 1:3cae7826a707 +| | | | | | parent: 26:720dc079a855 +| | | | | | user: test +| | | | | | date: Thu Jan 01 00:00:28 1970 +0000 +| | | | | | summary: (28) merge zero known +| | | | | | +o | | | | | changeset: 27:e9e08174cd30 +|/ / / / / parent: 21:e758e8f4ace9 +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:27 1970 +0000 +| | | | | summary: (27) collapse +| | | | | +| | o---+ changeset: 26:720dc079a855 +| | | | | parent: 18:5a8c9a29ef81 +| | | | | parent: 25:9d4ed048d013 +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:26 1970 +0000 +| | | | | summary: (26) merge one known; far right +| | | | | ++---o | | changeset: 25:9d4ed048d013 +| | | | | parent: 21:e758e8f4ace9 +| | | | | parent: 24:4a68967db00d +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:25 1970 +0000 +| | | | | summary: (25) merge one known; far left +| | | | | +| | o | | changeset: 24:4a68967db00d +| | |\| | parent: 0:7aa22e58e8c1 +| | | | | parent: 23:bc31393cabdf +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:24 1970 +0000 +| | | | | summary: (24) merge one known; immediate right +| | | | | +| | o | | changeset: 23:bc31393cabdf +| |/| | | parent: 1:3cae7826a707 +| | | | | parent: 22:a37f2ea6ebc6 +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:23 1970 +0000 +| | | | | summary: (23) merge one known; immediate left +| | | | | ++---o---+ changeset: 22:a37f2ea6ebc6 +| | | | parent: 18:5a8c9a29ef81 +| | / / parent: 21:e758e8f4ace9 +| | | | user: test +| | | | date: Thu Jan 01 00:00:22 1970 +0000 +| | | | summary: (22) merge two known; one far left, one far right +| | | | +o | | | changeset: 21:e758e8f4ace9 +|\ \ \ \ parent: 19:138069b5dad7 +| | | | | parent: 20:aeccadad74b4 +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:21 1970 +0000 +| | | | | summary: (21) expand +| | | | | +| o---+-+ changeset: 20:aeccadad74b4 +| | | | parent: 0:7aa22e58e8c1 +| / / / parent: 18:5a8c9a29ef81 +| | | | user: test +| | | | date: Thu Jan 01 00:00:20 1970 +0000 +| | | | summary: (20) merge two known; two far right +| | | | +o | | | changeset: 19:138069b5dad7 +|\ \ \ \ parent: 15:c0b4283d4c1d +| | | | | parent: 17:43e52b935494 +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:19 1970 +0000 +| | | | | summary: (19) expand +| | | | | ++---+---o changeset: 18:5a8c9a29ef81 +| | | | parent: 1:3cae7826a707 +| | | | parent: 15:c0b4283d4c1d +| | | | user: test +| | | | date: Thu Jan 01 00:00:18 1970 +0000 +| | | | summary: (18) merge two known; two far left +| | | | +| o | | changeset: 17:43e52b935494 +| |\ \ \ parent: 12:74dc7aea4494 +| | | | | parent: 16:449a2f9562a4 +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:17 1970 +0000 +| | | | | summary: (17) expand +| | | | | +| | o---+ changeset: 16:449a2f9562a4 +| | | | | parent: 0:7aa22e58e8c1 +| | |/ / parent: 1:3cae7826a707 +| | | | user: test +| | | | date: Thu Jan 01 00:00:16 1970 +0000 +| | | | summary: (16) merge two known; one immediate right, one near right +| | | | +o | | | changeset: 15:c0b4283d4c1d +|\ \ \ \ parent: 13:c39d0a2b8165 +| | | | | parent: 14:9d533950abf0 +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:15 1970 +0000 +| | | | | summary: (15) expand +| | | | | +| o-----+ changeset: 14:9d533950abf0 +| | | | | parent: 0:7aa22e58e8c1 +| |/ / / parent: 12:74dc7aea4494 +| | | | user: test +| | | | date: Thu Jan 01 00:00:14 1970 +0000 +| | | | summary: (14) merge two known; one immediate right, one far right +| | | | +o | | | changeset: 13:c39d0a2b8165 +|\ \ \ \ parent: 9:79ab1812f961 +| | | | | parent: 11:c3c395dd8b98 +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:13 1970 +0000 +| | | | | summary: (13) expand +| | | | | ++---o | | changeset: 12:74dc7aea4494 +| | |/ / parent: 1:3cae7826a707 +| | | | parent: 9:79ab1812f961 +| | | | user: test +| | | | date: Thu Jan 01 00:00:12 1970 +0000 +| | | | summary: (12) merge two known; one immediate right, one far left +| | | | +| o | | changeset: 11:c3c395dd8b98 +| |\ \ \ parent: 6:0ca7c061cf45 +| | | | | parent: 10:8094c50149ef +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:11 1970 +0000 +| | | | | summary: (11) expand +| | | | | +| | o---+ changeset: 10:8094c50149ef +| | | | | parent: 0:7aa22e58e8c1 +| |/ / / parent: 6:0ca7c061cf45 +| | | | user: test +| | | | date: Thu Jan 01 00:00:10 1970 +0000 +| | | | summary: (10) merge two known; one immediate left, one near right +| | | | +o | | | changeset: 9:79ab1812f961 +|\ \ \ \ parent: 7:699392d1259e +| | | | | parent: 8:d7aa38594334 +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:09 1970 +0000 +| | | | | summary: (9) expand +| | | | | +| o-----+ changeset: 8:d7aa38594334 +| | | | | parent: 0:7aa22e58e8c1 +|/ / / / parent: 7:699392d1259e +| | | | user: test +| | | | date: Thu Jan 01 00:00:08 1970 +0000 +| | | | summary: (8) merge two known; one immediate left, one far right +| | | | +o | | | changeset: 7:699392d1259e +|\ \ \ \ parent: 2:e8ea2256f9ec +| | | | | parent: 5:3589c3c477ab +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:07 1970 +0000 +| | | | | summary: (7) expand +| | | | | ++---o | | changeset: 6:0ca7c061cf45 +| |/ / / parent: 2:e8ea2256f9ec +| | | | parent: 5:3589c3c477ab +| | | | user: test +| | | | date: Thu Jan 01 00:00:06 1970 +0000 +| | | | summary: (6) merge two known; one immediate left, one far left +| | | | +| o | | changeset: 5:3589c3c477ab +| |\ \ \ parent: 3:02173ffbf857 +| | | | | parent: 4:e2cad8233c77 +| | | | | user: test +| | | | | date: Thu Jan 01 00:00:05 1970 +0000 +| | | | | summary: (5) expand +| | | | | +| | o | | changeset: 4:e2cad8233c77 +| |/|/ / parent: 1:3cae7826a707 +| | | | parent: 3:02173ffbf857 +| | | | user: test +| | | | date: Thu Jan 01 00:00:04 1970 +0000 +| | | | summary: (4) merge two known; one immediate left, one immediate right +| | | | +| o | | changeset: 3:02173ffbf857 +|/ / / user: test +| | | date: Thu Jan 01 00:00:03 1970 +0000 +| | | summary: (3) collapse +| | | +o | | changeset: 2:e8ea2256f9ec +|/ / user: test +| | date: Thu Jan 01 00:00:02 1970 +0000 +| | summary: (2) collapse +| | +o | changeset: 1:3cae7826a707 +|/ user: test +| date: Thu Jan 01 00:00:01 1970 +0000 +| summary: (1) collapse +| +o changeset: 0:7aa22e58e8c1 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: (0) root +