82
static const char **column_colors;
83
static unsigned short column_colors_max;
84
85
+static unsigned int max_lanes = 15;
86
+
87
static void parse_graph_colors_config(struct strvec *colors, const char *string)
88
{
89
const char *end, *start;
319
struct strbuf prefix_buf;
320
};
321
322
+static inline int graph_needs_truncation(int lane)
323
+{
324
+ return lane >= max_lanes;
325
+}
326
+
327
static const char *diff_output_prefix_callback(struct diff_options *opt, void *data)
328
{
329
struct git_graph *graph = data;
614
{
615
struct commit_list *parent;
616
int max_new_columns;
610
- int i, seen_this, is_commit_in_columns;
617
+ int i, seen_this, is_commit_in_columns, max;
618
619
/*
620
* Swap graph->columns with graph->new_columns
703
}
704
}
705
706
+ /*
707
+ * Cap to the hard-coded limit.
708
+ * Allow commits from merges to align to the merged lane.
709
+ */
710
+ max = max_lanes * 2 + 2;
711
+ if (graph->width > max)
712
+ graph->width = max;
713
+
714
/*
715
* Shrink mapping_size to be the minimum necessary
716
*/
861
* Output a padding row, that leaves all branch lines unchanged
862
*/
863
for (i = 0; i < graph->num_new_columns; i++) {
864
+ if (graph_needs_truncation(i))
865
+ break;
866
graph_line_write_column(line, &graph->new_columns[i], '|');
867
graph_line_addch(line, ' ');
868
}
920
seen_this = 1;
921
graph_line_write_column(line, col, '|');
922
graph_line_addchars(line, ' ', graph->expansion_row);
923
+ } else if (seen_this && graph_needs_truncation(i)) {
924
+ break;
925
} else if (seen_this && (graph->expansion_row == 0)) {
926
/*
927
* This is the first line of the pre-commit output.
1013
col = &graph->new_columns[j];
1014
1015
graph_line_write_column(line, col, '-');
1016
+
1017
+ /*
1018
+ * Commit is at commit_index, each iteration move one lane to
1019
+ * the right from the commit.
1020
+ */
1021
+ if (graph_needs_truncation(graph->commit_index + 1 + i))
1022
+ break;
1023
+
1024
graph_line_write_column(line, col, (i == dashed_parents - 1) ? '.' : '-');
1025
}
1026
1055
seen_this = 1;
1056
graph_output_commit_char(graph, line);
1057
1058
+ if (graph_needs_truncation(i)) {
1059
+ graph_line_addch(line, ' ');
1060
+ break;
1061
+ }
1062
+
1063
if (graph->num_parents > 2)
1064
graph_draw_octopus_merge(graph, line);
1065
+ } else if (graph_needs_truncation(i)) {
1066
+ seen_this = 1;
1067
+ break;
1068
} else if (seen_this && (graph->edges_added > 1)) {
1069
graph_line_write_column(line, col, '\\');
1070
} else if (seen_this && (graph->edges_added == 1)) {
1100
1101
/*
1102
* Update graph->state
1103
+ *
1104
+ * If the commit is a merge and the first parent is in a visible lane,
1105
+ * then the GRAPH_POST_MERGE is needed to draw the merge lane.
1106
+ *
1107
+ * If the commit is over the truncation limit, but the first parent is on
1108
+ * a visible lane, then we still need the merge lane but truncated.
1109
+ *
1110
+ * If both commit and first parent are over the truncation limit, then
1111
+ * there's no need to draw the merge lane because it would work as a
1112
+ * padding lane.
1113
*/
1069
- if (graph->num_parents > 1)
1070
- graph_update_state(graph, GRAPH_POST_MERGE);
1071
- else if (graph_is_mapping_correct(graph))
1114
+ if (graph->num_parents > 1) {
1115
+ if (!graph_needs_truncation(graph->commit_index)) {
1116
+ graph_update_state(graph, GRAPH_POST_MERGE);
1117
+ } else {
1118
+ struct commit_list *p = first_interesting_parent(graph);
1119
+ int lane;
1120
+
1121
+ /*
1122
+ * graph->num_parents are found using first_interesting_parent
1123
+ * and next_interesting_parent so it can't be a scenario
1124
+ * where num_parents > 1 and there are no interesting parents
1125
+ */
1126
+ if (!p)
1127
+ BUG("num_parents > 1 but no interesting parent");
1128
+
1129
+ lane = graph_find_new_column_by_commit(graph, p->item);
1130
+
1131
+ if (!graph_needs_truncation(lane))
1132
+ graph_update_state(graph, GRAPH_POST_MERGE);
1133
+ else if (graph_is_mapping_correct(graph))
1134
+ graph_update_state(graph, GRAPH_PADDING);
1135
+ else
1136
+ graph_update_state(graph, GRAPH_COLLAPSING);
1137
+ }
1138
+ } else if (graph_is_mapping_correct(graph)) {
1139
graph_update_state(graph, GRAPH_PADDING);
1073
- else
1140
+ } else {
1141
graph_update_state(graph, GRAPH_COLLAPSING);
1142
+ }
1143
}
1144
1145
static const char merge_chars[] = {'/', '|', '\\'};
1177
int par_column;
1178
int idx = graph->merge_layout;
1179
char c;
1180
+ int truncated = 0;
1181
seen_this = 1;
1182
1183
for (j = 0; j < graph->num_parents; j++) {
1186
1187
c = merge_chars[idx];
1188
graph_line_write_column(line, &graph->new_columns[par_column], c);
1189
+
1190
+ /*
1191
+ * j counts parents, it needs to be halved to be
1192
+ * comparable with i. Don't truncate if there are
1193
+ * no more lanes to print (end of the lane)
1194
+ */
1195
+ if (graph_needs_truncation(j / 2 + i) &&
1196
+ j / 2 + i <= graph->num_columns) {
1197
+ if ((j + i * 2) % 2 != 0)
1198
+ graph_line_addch(line, ' ');
1199
+ truncated = 1;
1200
+ break;
1201
+ }
1202
+
1203
if (idx == 2) {
1121
- if (graph->edges_added > 0 || j < graph->num_parents - 1)
1204
+ /*
1205
+ * Check if the next lane needs truncation
1206
+ * to avoid having the padding doubled
1207
+ */
1208
+ if (graph_needs_truncation((j + 1) / 2 + i) &&
1209
+ j < graph->num_parents - 1) {
1210
+ truncated = 1;
1211
+ break;
1212
+ } else if (graph->edges_added > 0 || j < graph->num_parents - 1)
1213
graph_line_addch(line, ' ');
1214
} else {
1215
idx++;
1216
}
1217
parents = next_interesting_parent(graph, parents);
1218
}
1219
+ if (truncated)
1220
+ break;
1221
if (graph->edges_added == 0)
1222
graph_line_addch(line, ' ');
1130
-
1223
+ } else if (graph_needs_truncation(i)) {
1224
+ break;
1225
} else if (seen_this) {
1226
if (graph->edges_added > 0)
1227
graph_line_write_column(line, col, '\\');
1228
else
1229
graph_line_write_column(line, col, '|');
1136
- graph_line_addch(line, ' ');
1230
+ /*
1231
+ * If it's between two lanes and next would be truncated,
1232
+ * don't add space padding.
1233
+ */
1234
+ if (!graph_needs_truncation(i + 1))
1235
+ graph_line_addch(line, ' ');
1236
} else {
1237
graph_line_write_column(line, col, '|');
1238
if (graph->merge_layout != 0 || i != graph->commit_index - 1) {
1263
short used_horizontal = 0;
1264
int horizontal_edge = -1;
1265
int horizontal_edge_target = -1;
1266
+ int truncated = 0;
1267
1268
/*
1269
* Swap the mapping and old_mapping arrays
1379
*/
1380
for (i = 0; i < graph->mapping_size; i++) {
1381
int target = graph->mapping[i];
1282
- if (target < 0)
1283
- graph_line_addch(line, ' ');
1284
- else if (target * 2 == i)
1285
- graph_line_write_column(line, &graph->new_columns[target], '|');
1286
- else if (target == horizontal_edge_target &&
1287
- i != horizontal_edge - 1) {
1288
- /*
1289
- * Set the mappings for all but the
1290
- * first segment to -1 so that they
1291
- * won't continue into the next line.
1292
- */
1293
- if (i != (target * 2)+3)
1294
- graph->mapping[i] = -1;
1295
- used_horizontal = 1;
1296
- graph_line_write_column(line, &graph->new_columns[target], '_');
1382
+
1383
+ if (!truncated && graph_needs_truncation(i / 2)) {
1384
+ truncated = 1;
1385
+ }
1386
+
1387
+ if (target < 0) {
1388
+ if (!truncated)
1389
+ graph_line_addch(line, ' ');
1390
+ } else if (target * 2 == i) {
1391
+ if (!truncated)
1392
+ graph_line_write_column(line, &graph->new_columns[target], '|');
1393
+ } else if (target == horizontal_edge_target &&
1394
+ i != horizontal_edge - 1) {
1395
+ /*
1396
+ * Set the mappings for all but the
1397
+ * first segment to -1 so that they
1398
+ * won't continue into the next line.
1399
+ */
1400
+ if (i != (target * 2)+3)
1401
+ graph->mapping[i] = -1;
1402
+ used_horizontal = 1;
1403
+ if (!truncated)
1404
+ graph_line_write_column(line, &graph->new_columns[target], '_');
1405
} else {
1406
if (used_horizontal && i < horizontal_edge)
1407
graph->mapping[i] = -1;
1300
- graph_line_write_column(line, &graph->new_columns[target], '/');
1301
-
1408
+ if (!truncated)
1409
+ graph_line_write_column(line, &graph->new_columns[target], '/');
1410
}
1411
}
1412
1480
for (i = 0; i < graph->num_columns; i++) {
1481
struct column *col = &graph->columns[i];
1482
1483
+ if (graph_needs_truncation(i))
1484
+ break;
1485
+
1486
graph_line_write_column(&line, col, '|');
1487
1488
if (col->commit == graph->commit && graph->num_parents > 2) {