summaryrefslogtreecommitdiff
path: root/graph.c
diff options
context:
space:
mode:
authorJames Coglan <jcoglan@gmail.com>2019-10-15 23:47:58 (GMT)
committerJunio C Hamano <gitster@pobox.com>2019-10-16 02:11:25 (GMT)
commit92beecc136ad51f358baacf948b4c4b734fd5a4c (patch)
tree47608c2298e0f54ca5966b331ec9415de3dea899 /graph.c
parent479db18bc0c38ed610fba56f3cc98abd7977e695 (diff)
downloadgit-92beecc136ad51f358baacf948b4c4b734fd5a4c.zip
git-92beecc136ad51f358baacf948b4c4b734fd5a4c.tar.gz
git-92beecc136ad51f358baacf948b4c4b734fd5a4c.tar.bz2
graph: flatten edges that fuse with their right neighbor
When a merge commit is printed and its final parent is the same commit that occupies the column to the right of the merge, this results in a kink in the displayed edges: * | |\ \ | |/ | * Graphs containing these shapes can be hard to read, as the expansion to the right followed immediately by collapsing back to the left creates a lot of zig-zagging edges, especially when many columns are present. We can improve this by eliminating the zig-zag and having the merge's final parent edge fuse immediately with its neighbor: * | |\| | * This reduces the horizontal width for the current commit by 2, and requires one less row, making the graph display more compact. Taken in combination with other graph-smoothing enhancements, it greatly compresses the space needed to display certain histories: * |\ | * * | |\ |\ | | * | * | | | | |\ | | \ | | * | *-. \ | * | | |\ \ \ => |/|\| |/ / / / | | * | | | / | * | | | |/ | |/ | | * * / | * | |/ | |/ * * | |/ * One of the test cases here cannot be correctly rendered in Git v2.23.0; it produces this output following commit E: | | *-. \ 5_E | | |\ \ \ | |/ / / / | | | / _ | |_|/ |/| | The new implementation makes sure that the rightmost edge in this history is not left dangling as above. Signed-off-by: James Coglan <jcoglan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'graph.c')
-rw-r--r--graph.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/graph.c b/graph.c
index 63f8d18..80db74a 100644
--- a/graph.c
+++ b/graph.c
@@ -557,8 +557,24 @@ static void graph_insert_into_new_columns(struct git_graph *graph,
shift = (dist > 1) ? 2 * dist - 3 : 1;
graph->merge_layout = (dist > 0) ? 0 : 1;
+ graph->edges_added = graph->num_parents + graph->merge_layout - 2;
+
mapping_idx = graph->width + (graph->merge_layout - 1) * shift;
graph->width += 2 * graph->merge_layout;
+
+ } else if (graph->edges_added > 0 && i == graph->mapping[graph->width - 2]) {
+ /*
+ * If some columns have been added by a merge, but this commit
+ * was found in the last existing column, then adjust the
+ * numbers so that the two edges immediately join, i.e.:
+ *
+ * * | * |
+ * |\ \ => |\|
+ * | |/ | *
+ * | *
+ */
+ mapping_idx = graph->width - 2;
+ graph->edges_added = -1;
} else {
mapping_idx = graph->width;
graph->width += 2;
@@ -604,6 +620,8 @@ static void graph_update_columns(struct git_graph *graph)
graph->mapping[i] = -1;
graph->width = 0;
+ graph->prev_edges_added = graph->edges_added;
+ graph->edges_added = 0;
/*
* Populate graph->new_columns and graph->mapping
@@ -731,9 +749,6 @@ void graph_update(struct git_graph *graph, struct commit *commit)
*/
graph_update_columns(graph);
- graph->prev_edges_added = graph->edges_added;
- graph->edges_added = graph->num_parents + graph->merge_layout - 2;
-
graph->expansion_row = 0;
/*
@@ -1041,7 +1056,7 @@ const char merge_chars[] = {'/', '|', '\\'};
static void graph_output_post_merge_line(struct git_graph *graph, struct graph_line *line)
{
int seen_this = 0;
- int i;
+ int i, j;
struct commit_list *first_parent = first_interesting_parent(graph);
int seen_parent = 0;
@@ -1073,16 +1088,19 @@ static void graph_output_post_merge_line(struct git_graph *graph, struct graph_l
char c;
seen_this = 1;
- for (; parents; parents = next_interesting_parent(graph, parents)) {
+ for (j = 0; j < graph->num_parents; j++) {
par_column = graph_find_new_column_by_commit(graph, parents->item);
assert(par_column >= 0);
c = merge_chars[idx];
graph_line_write_column(line, &graph->new_columns[par_column], c);
- if (idx == 2)
- graph_line_addch(line, ' ');
- else
+ if (idx == 2) {
+ if (graph->edges_added > 0 || j < graph->num_parents - 1)
+ graph_line_addch(line, ' ');
+ } else {
idx++;
+ }
+ parents = next_interesting_parent(graph, parents);
}
if (graph->edges_added == 0)
graph_line_addch(line, ' ');