Skip to content

Commit cfb35b5

Browse files
pabloosabaterrgitster
authored andcommitted
graph: truncate graph visual output
When '--graph-lane-limit' is set, lanes over the limit should not be drawn. Teach each graph state to stop rendering at the lane limit and print a '.' truncation mark, so users know that there are hidden lanes. On the commit line, if the commit lives on a visible lane, show the normal commit mark and truncate after it, if the commit lives on the first hidden lane (the truncation mark lane) show the "*" instead of the truncation mark so it is known that this commit sits on the first hidden lane. Commits on deeper lanes don't leave a mark. For merges, the post-merge lane is only needed when the commit or the first parent lives on a visible lane (to draw the connection between them), when both are on hidden lanes, post-merge carries no useful information, skip it and go to collapsing or padding state. Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent c50ee29 commit cfb35b5

1 file changed

Lines changed: 106 additions & 16 deletions

File tree

graph.c

Lines changed: 106 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,20 @@ static void graph_update_columns(struct git_graph *graph)
705705
}
706706
}
707707

708+
/*
709+
* If graph_max_lanes is set, cap the padding from the branches
710+
*/
711+
if (graph->revs->graph_max_lanes > 0) {
712+
/*
713+
* Get the maximum width by multiplying the maximum number of
714+
* lanes by the size of the lane "| " and adds the truncation
715+
* mark ". "
716+
*/
717+
int max_columns_width = graph->revs->graph_max_lanes * 2 + 2;
718+
if (graph->width > max_columns_width)
719+
graph->width = max_columns_width;
720+
}
721+
708722
/*
709723
* Shrink mapping_size to be the minimum necessary
710724
*/
@@ -855,6 +869,10 @@ static void graph_output_padding_line(struct git_graph *graph,
855869
* Output a padding row, that leaves all branch lines unchanged
856870
*/
857871
for (i = 0; i < graph->num_new_columns; i++) {
872+
if (graph_needs_truncation(graph, i)) {
873+
graph_line_addstr(line, ". ");
874+
break;
875+
}
858876
graph_line_write_column(line, &graph->new_columns[i], '|');
859877
graph_line_addch(line, ' ');
860878
}
@@ -912,6 +930,9 @@ static void graph_output_pre_commit_line(struct git_graph *graph,
912930
seen_this = 1;
913931
graph_line_write_column(line, col, '|');
914932
graph_line_addchars(line, ' ', graph->expansion_row);
933+
} else if (seen_this && graph_needs_truncation(graph, i)) {
934+
graph_line_addstr(line, ". ");
935+
break;
915936
} else if (seen_this && (graph->expansion_row == 0)) {
916937
/*
917938
* This is the first line of the pre-commit output.
@@ -1022,6 +1043,7 @@ static void graph_output_commit_line(struct git_graph *graph, struct graph_line
10221043
* children that we have already processed.)
10231044
*/
10241045
seen_this = 0;
1046+
10251047
for (i = 0; i <= graph->num_columns; i++) {
10261048
struct column *col = &graph->columns[i];
10271049
struct commit *col_commit;
@@ -1037,8 +1059,17 @@ static void graph_output_commit_line(struct git_graph *graph, struct graph_line
10371059
seen_this = 1;
10381060
graph_output_commit_char(graph, line);
10391061

1062+
if (graph_needs_truncation(graph, i)) {
1063+
graph_line_addch(line, ' ');
1064+
break;
1065+
}
1066+
10401067
if (graph->num_parents > 2)
10411068
graph_draw_octopus_merge(graph, line);
1069+
} else if (graph_needs_truncation(graph, i)) {
1070+
graph_line_addstr(line, ". ");
1071+
seen_this = 1;
1072+
break;
10421073
} else if (seen_this && (graph->edges_added > 1)) {
10431074
graph_line_write_column(line, col, '\\');
10441075
} else if (seen_this && (graph->edges_added == 1)) {
@@ -1074,10 +1105,32 @@ static void graph_output_commit_line(struct git_graph *graph, struct graph_line
10741105

10751106
/*
10761107
* Update graph->state
1108+
*
1109+
* If the commit is a merge and the first parent is in a visible lane,
1110+
* then the GRAPH_POST_MERGE is needed to draw the merge lane.
1111+
*
1112+
* If the commit is over the truncation limit, but the first parent is on
1113+
* a visible lane, then we still need the merge lane but truncated.
1114+
*
1115+
* If both commit and first parent are over the truncation limit, then
1116+
* there's no need to draw the merge lane because it would work as a
1117+
* padding lane.
10771118
*/
1078-
if (graph->num_parents > 1)
1079-
graph_update_state(graph, GRAPH_POST_MERGE);
1080-
else if (graph_is_mapping_correct(graph))
1119+
if (graph->num_parents > 1) {
1120+
if (!graph_needs_truncation(graph, graph->commit_index)) {
1121+
graph_update_state(graph, GRAPH_POST_MERGE);
1122+
} else {
1123+
struct commit_list *first_parent = first_interesting_parent(graph);
1124+
int first_parent_col = graph_find_new_column_by_commit(graph, first_parent->item);
1125+
1126+
if (!graph_needs_truncation(graph, first_parent_col))
1127+
graph_update_state(graph, GRAPH_POST_MERGE);
1128+
else if (graph_is_mapping_correct(graph))
1129+
graph_update_state(graph, GRAPH_PADDING);
1130+
else
1131+
graph_update_state(graph, GRAPH_COLLAPSING);
1132+
}
1133+
} else if (graph_is_mapping_correct(graph))
10811134
graph_update_state(graph, GRAPH_PADDING);
10821135
else
10831136
graph_update_state(graph, GRAPH_COLLAPSING);
@@ -1118,14 +1171,28 @@ static void graph_output_post_merge_line(struct git_graph *graph, struct graph_l
11181171
int par_column;
11191172
int idx = graph->merge_layout;
11201173
char c;
1174+
int truncated = 0;
11211175
seen_this = 1;
11221176

11231177
for (j = 0; j < graph->num_parents; j++) {
1178+
unsigned int truncation_max = i + (j > 1 ? j - 1 : 0);
11241179
par_column = graph_find_new_column_by_commit(graph, parents->item);
11251180
assert(par_column >= 0);
11261181

11271182
c = merge_chars[idx];
11281183
graph_line_write_column(line, &graph->new_columns[par_column], c);
1184+
1185+
if (j >= 2)
1186+
truncation_max -= 1;
1187+
1188+
if (graph_needs_truncation(graph, truncation_max)) {
1189+
if (j > 0 && !(graph->edges_added > 0))
1190+
graph_line_addch(line, ' ');
1191+
graph_line_addstr(line, ". ");
1192+
truncated = 1;
1193+
break;
1194+
}
1195+
11291196
if (idx == 2) {
11301197
if (graph->edges_added > 0 || j < graph->num_parents - 1)
11311198
graph_line_addch(line, ' ');
@@ -1134,15 +1201,24 @@ static void graph_output_post_merge_line(struct git_graph *graph, struct graph_l
11341201
}
11351202
parents = next_interesting_parent(graph, parents);
11361203
}
1204+
if (truncated)
1205+
break;
11371206
if (graph->edges_added == 0)
11381207
graph_line_addch(line, ' ');
1139-
1208+
} else if (graph_needs_truncation(graph, i)) {
1209+
graph_line_addstr(line, ". ");
1210+
break;
11401211
} else if (seen_this) {
11411212
if (graph->edges_added > 0)
11421213
graph_line_write_column(line, col, '\\');
11431214
else
11441215
graph_line_write_column(line, col, '|');
1145-
graph_line_addch(line, ' ');
1216+
/*
1217+
* If it's between two lanes and next would be truncated,
1218+
* don't add space padding.
1219+
*/
1220+
if (!graph_needs_truncation(graph, i + 1))
1221+
graph_line_addch(line, ' ');
11461222
} else {
11471223
graph_line_write_column(line, col, '|');
11481224
if (graph->merge_layout != 0 || i != graph->commit_index - 1) {
@@ -1173,6 +1249,7 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct graph_l
11731249
short used_horizontal = 0;
11741250
int horizontal_edge = -1;
11751251
int horizontal_edge_target = -1;
1252+
int truncated = 0;
11761253

11771254
/*
11781255
* Swap the mapping and old_mapping arrays
@@ -1288,26 +1365,35 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct graph_l
12881365
*/
12891366
for (i = 0; i < graph->mapping_size; i++) {
12901367
int target = graph->mapping[i];
1291-
if (target < 0)
1292-
graph_line_addch(line, ' ');
1293-
else if (target * 2 == i)
1294-
graph_line_write_column(line, &graph->new_columns[target], '|');
1295-
else if (target == horizontal_edge_target &&
1296-
i != horizontal_edge - 1) {
1368+
1369+
if (!truncated && graph_needs_truncation(graph, i / 2)) {
1370+
graph_line_addstr(line, ". ");
1371+
truncated = 1;
1372+
}
1373+
1374+
if (target < 0) {
1375+
if (!truncated)
1376+
graph_line_addch(line, ' ');
1377+
} else if (target * 2 == i) {
1378+
if (!truncated)
1379+
graph_line_write_column(line, &graph->new_columns[target], '|');
1380+
} else if (target == horizontal_edge_target &&
1381+
i != horizontal_edge - 1) {
12971382
/*
12981383
* Set the mappings for all but the
12991384
* first segment to -1 so that they
13001385
* won't continue into the next line.
13011386
*/
13021387
if (i != (target * 2)+3)
13031388
graph->mapping[i] = -1;
1304-
used_horizontal = 1;
1305-
graph_line_write_column(line, &graph->new_columns[target], '_');
1389+
used_horizontal = 1;
1390+
if (!truncated)
1391+
graph_line_write_column(line, &graph->new_columns[target], '_');
13061392
} else {
13071393
if (used_horizontal && i < horizontal_edge)
13081394
graph->mapping[i] = -1;
1309-
graph_line_write_column(line, &graph->new_columns[target], '/');
1310-
1395+
if (!truncated)
1396+
graph_line_write_column(line, &graph->new_columns[target], '/');
13111397
}
13121398
}
13131399

@@ -1356,7 +1442,6 @@ int graph_next_line(struct git_graph *graph, struct strbuf *sb)
13561442
graph_output_collapsing_line(graph, &line);
13571443
break;
13581444
}
1359-
13601445
graph_pad_horizontally(graph, &line);
13611446
return shown_commit_line;
13621447
}
@@ -1381,6 +1466,11 @@ static void graph_padding_line(struct git_graph *graph, struct strbuf *sb)
13811466
for (i = 0; i < graph->num_columns; i++) {
13821467
struct column *col = &graph->columns[i];
13831468

1469+
if (graph_needs_truncation(graph, i)) {
1470+
graph_line_addch(&line, '.');
1471+
break;
1472+
}
1473+
13841474
graph_line_write_column(&line, col, '|');
13851475

13861476
if (col->commit == graph->commit && graph->num_parents > 2) {

0 commit comments

Comments
 (0)