@@ -317,6 +317,15 @@ struct git_graph {
317317 struct strbuf prefix_buf ;
318318};
319319
320+ static int graph_needs_truncation (struct git_graph * graph , int lane )
321+ {
322+ int max = graph -> revs -> graph_max_lanes ;
323+ /*
324+ * Ignore values <= 0, meaning no limit.
325+ */
326+ return max > 0 && lane >= max ;
327+ }
328+
320329static const char * diff_output_prefix_callback (struct diff_options * opt , void * data )
321330{
322331 struct git_graph * graph = data ;
@@ -696,6 +705,18 @@ static void graph_update_columns(struct git_graph *graph)
696705 }
697706 }
698707
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+ * width of "| " per lanes plus truncation mark "~ ".
714+ */
715+ int max_columns_width = graph -> revs -> graph_max_lanes * 2 + 2 ;
716+ if (graph -> width > max_columns_width )
717+ graph -> width = max_columns_width ;
718+ }
719+
699720 /*
700721 * Shrink mapping_size to be the minimum necessary
701722 */
@@ -846,6 +867,10 @@ static void graph_output_padding_line(struct git_graph *graph,
846867 * Output a padding row, that leaves all branch lines unchanged
847868 */
848869 for (i = 0 ; i < graph -> num_new_columns ; i ++ ) {
870+ if (graph_needs_truncation (graph , i )) {
871+ graph_line_addstr (line , "~ " );
872+ break ;
873+ }
849874 graph_line_write_column (line , & graph -> new_columns [i ], '|' );
850875 graph_line_addch (line , ' ' );
851876 }
@@ -903,6 +928,9 @@ static void graph_output_pre_commit_line(struct git_graph *graph,
903928 seen_this = 1 ;
904929 graph_line_write_column (line , col , '|' );
905930 graph_line_addchars (line , ' ' , graph -> expansion_row );
931+ } else if (seen_this && graph_needs_truncation (graph , i )) {
932+ graph_line_addstr (line , "~ " );
933+ break ;
906934 } else if (seen_this && (graph -> expansion_row == 0 )) {
907935 /*
908936 * This is the first line of the pre-commit output.
@@ -994,6 +1022,12 @@ static void graph_draw_octopus_merge(struct git_graph *graph, struct graph_line
9941022 col = & graph -> new_columns [j ];
9951023
9961024 graph_line_write_column (line , col , '-' );
1025+
1026+ if (graph_needs_truncation (graph , j / 2 + i )) {
1027+ graph_line_addstr (line , "~ " );
1028+ break ;
1029+ }
1030+
9971031 graph_line_write_column (line , col , (i == dashed_parents - 1 ) ? '.' : '-' );
9981032 }
9991033
@@ -1028,8 +1062,17 @@ static void graph_output_commit_line(struct git_graph *graph, struct graph_line
10281062 seen_this = 1 ;
10291063 graph_output_commit_char (graph , line );
10301064
1065+ if (graph_needs_truncation (graph , i )) {
1066+ graph_line_addch (line , ' ' );
1067+ break ;
1068+ }
1069+
10311070 if (graph -> num_parents > 2 )
10321071 graph_draw_octopus_merge (graph , line );
1072+ } else if (graph_needs_truncation (graph , i )) {
1073+ graph_line_addstr (line , "~ " );
1074+ seen_this = 1 ;
1075+ break ;
10331076 } else if (seen_this && (graph -> edges_added > 1 )) {
10341077 graph_line_write_column (line , col , '\\' );
10351078 } else if (seen_this && (graph -> edges_added == 1 )) {
@@ -1065,10 +1108,32 @@ static void graph_output_commit_line(struct git_graph *graph, struct graph_line
10651108
10661109 /*
10671110 * Update graph->state
1111+ *
1112+ * If the commit is a merge and the first parent is in a visible lane,
1113+ * then the GRAPH_POST_MERGE is needed to draw the merge lane.
1114+ *
1115+ * If the commit is over the truncation limit, but the first parent is on
1116+ * a visible lane, then we still need the merge lane but truncated.
1117+ *
1118+ * If both commit and first parent are over the truncation limit, then
1119+ * there's no need to draw the merge lane because it would work as a
1120+ * padding lane.
10681121 */
1069- if (graph -> num_parents > 1 )
1070- graph_update_state (graph , GRAPH_POST_MERGE );
1071- else if (graph_is_mapping_correct (graph ))
1122+ if (graph -> num_parents > 1 ) {
1123+ if (!graph_needs_truncation (graph , graph -> commit_index )) {
1124+ graph_update_state (graph , GRAPH_POST_MERGE );
1125+ } else {
1126+ struct commit_list * first_parent = first_interesting_parent (graph );
1127+ int first_parent_col = graph_find_new_column_by_commit (graph , first_parent -> item );
1128+
1129+ if (!graph_needs_truncation (graph , first_parent_col ))
1130+ graph_update_state (graph , GRAPH_POST_MERGE );
1131+ else if (graph_is_mapping_correct (graph ))
1132+ graph_update_state (graph , GRAPH_PADDING );
1133+ else
1134+ graph_update_state (graph , GRAPH_COLLAPSING );
1135+ }
1136+ } else if (graph_is_mapping_correct (graph ))
10721137 graph_update_state (graph , GRAPH_PADDING );
10731138 else
10741139 graph_update_state (graph , GRAPH_COLLAPSING );
@@ -1109,6 +1174,7 @@ static void graph_output_post_merge_line(struct git_graph *graph, struct graph_l
11091174 int par_column ;
11101175 int idx = graph -> merge_layout ;
11111176 char c ;
1177+ int truncated = 0 ;
11121178 seen_this = 1 ;
11131179
11141180 for (j = 0 ; j < graph -> num_parents ; j ++ ) {
@@ -1117,23 +1183,46 @@ static void graph_output_post_merge_line(struct git_graph *graph, struct graph_l
11171183
11181184 c = merge_chars [idx ];
11191185 graph_line_write_column (line , & graph -> new_columns [par_column ], c );
1186+ if (graph_needs_truncation (graph , j / 2 + i ) &&
1187+ j / 2 + i <= graph -> num_columns ) {
1188+ if ((j + i * 2 ) % 2 != 0 )
1189+ graph_line_addch (line , ' ' );
1190+ graph_line_addstr (line , "~ " );
1191+ truncated = 1 ;
1192+ break ;
1193+ }
1194+
11201195 if (idx == 2 ) {
1121- if (graph -> edges_added > 0 || j < graph -> num_parents - 1 )
1196+ if (graph_needs_truncation (graph , (j + 1 ) / 2 + i ) &&
1197+ j < graph -> num_parents - 1 ) {
1198+ graph_line_addstr (line , "~ " );
1199+ truncated = 1 ;
1200+ break ;
1201+ } else if (graph -> edges_added > 0 || j < graph -> num_parents - 1 )
11221202 graph_line_addch (line , ' ' );
11231203 } else {
11241204 idx ++ ;
11251205 }
11261206 parents = next_interesting_parent (graph , parents );
11271207 }
1208+ if (truncated )
1209+ break ;
11281210 if (graph -> edges_added == 0 )
11291211 graph_line_addch (line , ' ' );
1130-
1212+ } else if (graph_needs_truncation (graph , i )) {
1213+ graph_line_addstr (line , "~ " );
1214+ break ;
11311215 } else if (seen_this ) {
11321216 if (graph -> edges_added > 0 )
11331217 graph_line_write_column (line , col , '\\' );
11341218 else
11351219 graph_line_write_column (line , col , '|' );
1136- graph_line_addch (line , ' ' );
1220+ /*
1221+ * If it's between two lanes and next would be truncated,
1222+ * don't add space padding.
1223+ */
1224+ if (!graph_needs_truncation (graph , i + 1 ))
1225+ graph_line_addch (line , ' ' );
11371226 } else {
11381227 graph_line_write_column (line , col , '|' );
11391228 if (graph -> merge_layout != 0 || i != graph -> commit_index - 1 ) {
@@ -1164,6 +1253,7 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct graph_l
11641253 short used_horizontal = 0 ;
11651254 int horizontal_edge = -1 ;
11661255 int horizontal_edge_target = -1 ;
1256+ int truncated = 0 ;
11671257
11681258 /*
11691259 * Swap the mapping and old_mapping arrays
@@ -1279,26 +1369,35 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct graph_l
12791369 */
12801370 for (i = 0 ; i < graph -> mapping_size ; i ++ ) {
12811371 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 ], '_' );
1372+
1373+ if (!truncated && graph_needs_truncation (graph , i / 2 )) {
1374+ graph_line_addstr (line , "~ " );
1375+ truncated = 1 ;
1376+ }
1377+
1378+ if (target < 0 ) {
1379+ if (!truncated )
1380+ graph_line_addch (line , ' ' );
1381+ } else if (target * 2 == i ) {
1382+ if (!truncated )
1383+ graph_line_write_column (line , & graph -> new_columns [target ], '|' );
1384+ } else if (target == horizontal_edge_target &&
1385+ i != horizontal_edge - 1 ) {
1386+ /*
1387+ * Set the mappings for all but the
1388+ * first segment to -1 so that they
1389+ * won't continue into the next line.
1390+ */
1391+ if (i != (target * 2 )+ 3 )
1392+ graph -> mapping [i ] = -1 ;
1393+ used_horizontal = 1 ;
1394+ if (!truncated )
1395+ graph_line_write_column (line , & graph -> new_columns [target ], '_' );
12971396 } else {
12981397 if (used_horizontal && i < horizontal_edge )
12991398 graph -> mapping [i ] = -1 ;
1300- graph_line_write_column ( line , & graph -> new_columns [ target ], '/' );
1301-
1399+ if (! truncated )
1400+ graph_line_write_column ( line , & graph -> new_columns [ target ], '/' );
13021401 }
13031402 }
13041403
@@ -1372,6 +1471,11 @@ static void graph_padding_line(struct git_graph *graph, struct strbuf *sb)
13721471 for (i = 0 ; i < graph -> num_columns ; i ++ ) {
13731472 struct column * col = & graph -> columns [i ];
13741473
1474+ if (graph_needs_truncation (graph , i )) {
1475+ graph_line_addch (& line , '~' );
1476+ break ;
1477+ }
1478+
13751479 graph_line_write_column (& line , col , '|' );
13761480
13771481 if (col -> commit == graph -> commit && graph -> num_parents > 2 ) {
0 commit comments