graph API: improve display of merge commits
[git] / graph.c
1 #include "cache.h"
2 #include "commit.h"
3 #include "graph.h"
4 #include "diff.h"
5 #include "revision.h"
6
7 /*
8  * TODO:
9  * - Add colors to the graph.
10  *   Pick a color for each column, and print all characters
11  *   in that column with the specified color.
12  *
13  * - Limit the number of columns, similar to the way gitk does.
14  *   If we reach more than a specified number of columns, omit
15  *   sections of some columns.
16  *
17  * - The output during the GRAPH_PRE_COMMIT and GRAPH_COLLAPSING states
18  *   could be made more compact by printing horizontal lines, instead of
19  *   long diagonal lines.  For example, during collapsing, something like
20  *   this:          instead of this:
21  *   | | | | |      | | | | |
22  *   | |_|_|/       | | | |/
23  *   |/| | |        | | |/|
24  *   | | | |        | |/| |
25  *                  |/| | |
26  *                  | | | |
27  *
28  *   If there are several parallel diagonal lines, they will need to be
29  *   replaced with horizontal lines on subsequent rows.
30  */
31
32 struct column {
33         /*
34          * The parent commit of this column.
35          */
36         struct commit *commit;
37         /*
38          * XXX: Once we add support for colors, struct column could also
39          * contain the color of its branch line.
40          */
41 };
42
43 enum graph_state {
44         GRAPH_PADDING,
45         GRAPH_SKIP,
46         GRAPH_PRE_COMMIT,
47         GRAPH_COMMIT,
48         GRAPH_POST_MERGE,
49         GRAPH_COLLAPSING
50 };
51
52 struct git_graph {
53         /*
54          * The commit currently being processed
55          */
56         struct commit *commit;
57         /* The rev-info used for the current traversal */
58         struct rev_info *revs;
59         /*
60          * The number of interesting parents that this commit has.
61          *
62          * Note that this is not the same as the actual number of parents.
63          * This count excludes parents that won't be printed in the graph
64          * output, as determined by graph_is_interesting().
65          */
66         int num_parents;
67         /*
68          * The width of the graph output for this commit.
69          * All rows for this commit are padded to this width, so that
70          * messages printed after the graph output are aligned.
71          */
72         int width;
73         /*
74          * The next expansion row to print
75          * when state is GRAPH_PRE_COMMIT
76          */
77         int expansion_row;
78         /*
79          * The current output state.
80          * This tells us what kind of line graph_next_line() should output.
81          */
82         enum graph_state state;
83         /*
84          * The output state for the previous line of output.
85          * This is primarily used to determine how the first merge line
86          * should appear, based on the last line of the previous commit.
87          */
88         enum graph_state prev_state;
89         /*
90          * The index of the column that refers to this commit.
91          *
92          * If none of the incoming columns refer to this commit,
93          * this will be equal to num_columns.
94          */
95         int commit_index;
96         /*
97          * The commit_index for the previously displayed commit.
98          *
99          * This is used to determine how the first line of a merge
100          * graph output should appear, based on the last line of the
101          * previous commit.
102          */
103         int prev_commit_index;
104         /*
105          * The maximum number of columns that can be stored in the columns
106          * and new_columns arrays.  This is also half the number of entries
107          * that can be stored in the mapping and new_mapping arrays.
108          */
109         int column_capacity;
110         /*
111          * The number of columns (also called "branch lines" in some places)
112          */
113         int num_columns;
114         /*
115          * The number of columns in the new_columns array
116          */
117         int num_new_columns;
118         /*
119          * The number of entries in the mapping array
120          */
121         int mapping_size;
122         /*
123          * The column state before we output the current commit.
124          */
125         struct column *columns;
126         /*
127          * The new column state after we output the current commit.
128          * Only valid when state is GRAPH_COLLAPSING.
129          */
130         struct column *new_columns;
131         /*
132          * An array that tracks the current state of each
133          * character in the output line during state GRAPH_COLLAPSING.
134          * Each entry is -1 if this character is empty, or a non-negative
135          * integer if the character contains a branch line.  The value of
136          * the integer indicates the target position for this branch line.
137          * (I.e., this array maps the current column positions to their
138          * desired positions.)
139          *
140          * The maximum capacity of this array is always
141          * sizeof(int) * 2 * column_capacity.
142          */
143         int *mapping;
144         /*
145          * A temporary array for computing the next mapping state
146          * while we are outputting a mapping line.  This is stored as part
147          * of the git_graph simply so we don't have to allocate a new
148          * temporary array each time we have to output a collapsing line.
149          */
150         int *new_mapping;
151 };
152
153 struct git_graph *graph_init(struct rev_info *opt)
154 {
155         struct git_graph *graph = xmalloc(sizeof(struct git_graph));
156         graph->commit = NULL;
157         graph->revs = opt;
158         graph->num_parents = 0;
159         graph->expansion_row = 0;
160         graph->state = GRAPH_PADDING;
161         graph->prev_state = GRAPH_PADDING;
162         graph->commit_index = 0;
163         graph->prev_commit_index = 0;
164         graph->num_columns = 0;
165         graph->num_new_columns = 0;
166         graph->mapping_size = 0;
167
168         /*
169          * Allocate a reasonably large default number of columns
170          * We'll automatically grow columns later if we need more room.
171          */
172         graph->column_capacity = 30;
173         graph->columns = xmalloc(sizeof(struct column) *
174                                  graph->column_capacity);
175         graph->new_columns = xmalloc(sizeof(struct column) *
176                                      graph->column_capacity);
177         graph->mapping = xmalloc(sizeof(int) * 2 * graph->column_capacity);
178         graph->new_mapping = xmalloc(sizeof(int) * 2 * graph->column_capacity);
179
180         return graph;
181 }
182
183 void graph_release(struct git_graph *graph)
184 {
185         free(graph->columns);
186         free(graph->new_columns);
187         free(graph->mapping);
188         free(graph);
189 }
190
191 static void graph_update_state(struct git_graph *graph, enum graph_state s)
192 {
193         graph->prev_state = graph->state;
194         graph->state = s;
195 }
196
197 static void graph_ensure_capacity(struct git_graph *graph, int num_columns)
198 {
199         if (graph->column_capacity >= num_columns)
200                 return;
201
202         do {
203                 graph->column_capacity *= 2;
204         } while (graph->column_capacity < num_columns);
205
206         graph->columns = xrealloc(graph->columns,
207                                   sizeof(struct column) *
208                                   graph->column_capacity);
209         graph->new_columns = xrealloc(graph->new_columns,
210                                       sizeof(struct column) *
211                                       graph->column_capacity);
212         graph->mapping = xrealloc(graph->mapping,
213                                   sizeof(int) * 2 * graph->column_capacity);
214         graph->new_mapping = xrealloc(graph->new_mapping,
215                                       sizeof(int) * 2 * graph->column_capacity);
216 }
217
218 /*
219  * Returns 1 if the commit will be printed in the graph output,
220  * and 0 otherwise.
221  */
222 static int graph_is_interesting(struct git_graph *graph, struct commit *commit)
223 {
224         /*
225          * If revs->boundary is set, commits whose children have
226          * been shown are always interesting, even if they have the
227          * UNINTERESTING or TREESAME flags set.
228          */
229         if (graph->revs && graph->revs->boundary) {
230                 if (commit->object.flags & CHILD_SHOWN)
231                         return 1;
232         }
233
234         /*
235          * Uninteresting and pruned commits won't be printed
236          */
237         return (commit->object.flags & (UNINTERESTING | TREESAME)) ? 0 : 1;
238 }
239
240 static void graph_insert_into_new_columns(struct git_graph *graph,
241                                           struct commit *commit,
242                                           int *mapping_index)
243 {
244         int i;
245
246         /*
247          * Ignore uinteresting commits
248          */
249         if (!graph_is_interesting(graph, commit))
250                 return;
251
252         /*
253          * If the commit is already in the new_columns list, we don't need to
254          * add it.  Just update the mapping correctly.
255          */
256         for (i = 0; i < graph->num_new_columns; i++) {
257                 if (graph->new_columns[i].commit == commit) {
258                         graph->mapping[*mapping_index] = i;
259                         *mapping_index += 2;
260                         return;
261                 }
262         }
263
264         /*
265          * This commit isn't already in new_columns.  Add it.
266          */
267         graph->new_columns[graph->num_new_columns].commit = commit;
268         graph->mapping[*mapping_index] = graph->num_new_columns;
269         *mapping_index += 2;
270         graph->num_new_columns++;
271 }
272
273 static void graph_update_width(struct git_graph *graph,
274                                int is_commit_in_existing_columns)
275 {
276         /*
277          * Compute the width needed to display the graph for this commit.
278          * This is the maximum width needed for any row.  All other rows
279          * will be padded to this width.
280          *
281          * Compute the number of columns in the widest row:
282          * Count each existing column (graph->num_columns), and each new
283          * column added by this commit.
284          */
285         int max_cols = graph->num_columns + graph->num_parents;
286
287         /*
288          * Even if the current commit has no parents to be printed, it
289          * still takes up a column for itself.
290          */
291         if (graph->num_parents < 1)
292                 max_cols++;
293
294         /*
295          * We added a column for the the current commit as part of
296          * graph->num_parents.  If the current commit was already in
297          * graph->columns, then we have double counted it.
298          */
299         if (is_commit_in_existing_columns)
300                 max_cols--;
301
302         /*
303          * Each column takes up 2 spaces
304          */
305         graph->width = max_cols * 2;
306 }
307
308 static void graph_update_columns(struct git_graph *graph)
309 {
310         struct commit_list *parent;
311         struct column *tmp_columns;
312         int max_new_columns;
313         int mapping_idx;
314         int i, seen_this, is_commit_in_columns;
315
316         /*
317          * Swap graph->columns with graph->new_columns
318          * graph->columns contains the state for the previous commit,
319          * and new_columns now contains the state for our commit.
320          *
321          * We'll re-use the old columns array as storage to compute the new
322          * columns list for the commit after this one.
323          */
324         tmp_columns = graph->columns;
325         graph->columns = graph->new_columns;
326         graph->num_columns = graph->num_new_columns;
327
328         graph->new_columns = tmp_columns;
329         graph->num_new_columns = 0;
330
331         /*
332          * Now update new_columns and mapping with the information for the
333          * commit after this one.
334          *
335          * First, make sure we have enough room.  At most, there will
336          * be graph->num_columns + graph->num_parents columns for the next
337          * commit.
338          */
339         max_new_columns = graph->num_columns + graph->num_parents;
340         graph_ensure_capacity(graph, max_new_columns);
341
342         /*
343          * Clear out graph->mapping
344          */
345         graph->mapping_size = 2 * max_new_columns;
346         for (i = 0; i < graph->mapping_size; i++)
347                 graph->mapping[i] = -1;
348
349         /*
350          * Populate graph->new_columns and graph->mapping
351          *
352          * Some of the parents of this commit may already be in
353          * graph->columns.  If so, graph->new_columns should only contain a
354          * single entry for each such commit.  graph->mapping should
355          * contain information about where each current branch line is
356          * supposed to end up after the collapsing is performed.
357          */
358         seen_this = 0;
359         mapping_idx = 0;
360         is_commit_in_columns = 1;
361         for (i = 0; i <= graph->num_columns; i++) {
362                 struct commit *col_commit;
363                 if (i == graph->num_columns) {
364                         if (seen_this)
365                                 break;
366                         is_commit_in_columns = 0;
367                         col_commit = graph->commit;
368                 } else {
369                         col_commit = graph->columns[i].commit;
370                 }
371
372                 if (col_commit == graph->commit) {
373                         int old_mapping_idx = mapping_idx;
374                         seen_this = 1;
375                         graph->commit_index = i;
376                         for (parent = graph->commit->parents;
377                              parent;
378                              parent = parent->next) {
379                                 graph_insert_into_new_columns(graph,
380                                                               parent->item,
381                                                               &mapping_idx);
382                         }
383                         /*
384                          * We always need to increment mapping_idx by at
385                          * least 2, even if it has no interesting parents.
386                          * The current commit always takes up at least 2
387                          * spaces.
388                          */
389                         if (mapping_idx == old_mapping_idx)
390                                 mapping_idx += 2;
391                 } else {
392                         graph_insert_into_new_columns(graph, col_commit,
393                                                       &mapping_idx);
394                 }
395         }
396
397         /*
398          * Shrink mapping_size to be the minimum necessary
399          */
400         while (graph->mapping_size > 1 &&
401                graph->mapping[graph->mapping_size - 1] < 0)
402                 graph->mapping_size--;
403
404         /*
405          * Compute graph->width for this commit
406          */
407         graph_update_width(graph, is_commit_in_columns);
408 }
409
410 void graph_update(struct git_graph *graph, struct commit *commit)
411 {
412         struct commit_list *parent;
413
414         /*
415          * Set the new commit
416          */
417         graph->commit = commit;
418
419         /*
420          * Count how many interesting parents this commit has
421          */
422         graph->num_parents = 0;
423         for (parent = commit->parents; parent; parent = parent->next) {
424                 if (graph_is_interesting(graph, parent->item))
425                         graph->num_parents++;
426         }
427
428         /*
429          * Store the old commit_index in prev_commit_index.
430          * graph_update_columns() will update graph->commit_index for this
431          * commit.
432          */
433         graph->prev_commit_index = graph->commit_index;
434
435         /*
436          * Call graph_update_columns() to update
437          * columns, new_columns, and mapping.
438          */
439         graph_update_columns(graph);
440
441         graph->expansion_row = 0;
442
443         /*
444          * Update graph->state.
445          * Note that we don't call graph_update_state() here, since
446          * we don't want to update graph->prev_state.  No line for
447          * graph->state was ever printed.
448          *
449          * If the previous commit didn't get to the GRAPH_PADDING state,
450          * it never finished its output.  Goto GRAPH_SKIP, to print out
451          * a line to indicate that portion of the graph is missing.
452          *
453          * Otherwise, if there are 3 or more parents, we need to print
454          * extra rows before the commit, to expand the branch lines around
455          * it and make room for it.
456          *
457          * If there are less than 3 parents, we can immediately print the
458          * commit line.
459          */
460         if (graph->state != GRAPH_PADDING)
461                 graph->state = GRAPH_SKIP;
462         else if (graph->num_parents >= 3)
463                 graph->state = GRAPH_PRE_COMMIT;
464         else
465                 graph->state = GRAPH_COMMIT;
466 }
467
468 static int graph_is_mapping_correct(struct git_graph *graph)
469 {
470         int i;
471
472         /*
473          * The mapping is up to date if each entry is at its target,
474          * or is 1 greater than its target.
475          * (If it is 1 greater than the target, '/' will be printed, so it
476          * will look correct on the next row.)
477          */
478         for (i = 0; i < graph->mapping_size; i++) {
479                 int target = graph->mapping[i];
480                 if (target < 0)
481                         continue;
482                 if (target == (i / 2))
483                         continue;
484                 return 0;
485         }
486
487         return 1;
488 }
489
490 static void graph_pad_horizontally(struct git_graph *graph, struct strbuf *sb)
491 {
492         /*
493          * Add additional spaces to the end of the strbuf, so that all
494          * lines for a particular commit have the same width.
495          *
496          * This way, fields printed to the right of the graph will remain
497          * aligned for the entire commit.
498          */
499         int extra;
500         if (sb->len >= graph->width)
501                 return;
502
503         extra = graph->width - sb->len;
504         strbuf_addf(sb, "%*s", (int) extra, "");
505 }
506
507 static void graph_output_padding_line(struct git_graph *graph,
508                                       struct strbuf *sb)
509 {
510         int i;
511
512         /*
513          * We could conceivable be called with a NULL commit
514          * if our caller has a bug, and invokes graph_next_line()
515          * immediately after graph_init(), without first calling
516          * graph_update().  Return without outputting anything in this
517          * case.
518          */
519         if (!graph->commit)
520                 return;
521
522         /*
523          * Output a padding row, that leaves all branch lines unchanged
524          */
525         for (i = 0; i < graph->num_new_columns; i++) {
526                 strbuf_addstr(sb, "| ");
527         }
528
529         graph_pad_horizontally(graph, sb);
530 }
531
532 static void graph_output_skip_line(struct git_graph *graph, struct strbuf *sb)
533 {
534         /*
535          * Output an ellipsis to indicate that a portion
536          * of the graph is missing.
537          */
538         strbuf_addstr(sb, "...");
539         graph_pad_horizontally(graph, sb);
540
541         if (graph->num_parents >= 3)
542                 graph_update_state(graph, GRAPH_PRE_COMMIT);
543         else
544                 graph_update_state(graph, GRAPH_COMMIT);
545 }
546
547 static void graph_output_pre_commit_line(struct git_graph *graph,
548                                          struct strbuf *sb)
549 {
550         int num_expansion_rows;
551         int i, seen_this;
552
553         /*
554          * This function formats a row that increases the space around a commit
555          * with multiple parents, to make room for it.  It should only be
556          * called when there are 3 or more parents.
557          *
558          * We need 2 extra rows for every parent over 2.
559          */
560         assert(graph->num_parents >= 3);
561         num_expansion_rows = (graph->num_parents - 2) * 2;
562
563         /*
564          * graph->expansion_row tracks the current expansion row we are on.
565          * It should be in the range [0, num_expansion_rows - 1]
566          */
567         assert(0 <= graph->expansion_row &&
568                graph->expansion_row < num_expansion_rows);
569
570         /*
571          * Output the row
572          */
573         seen_this = 0;
574         for (i = 0; i < graph->num_columns; i++) {
575                 struct column *col = &graph->columns[i];
576                 if (col->commit == graph->commit) {
577                         seen_this = 1;
578                         strbuf_addf(sb, "| %*s", graph->expansion_row, "");
579                 } else if (seen_this && (graph->expansion_row == 0)) {
580                         /*
581                          * This is the first line of the pre-commit output.
582                          * If the previous commit was a merge commit and
583                          * ended in the GRAPH_POST_MERGE state, all branch
584                          * lines after graph->prev_commit_index were
585                          * printed as "\" on the previous line.  Continue
586                          * to print them as "\" on this line.  Otherwise,
587                          * print the branch lines as "|".
588                          */
589                         if (graph->prev_state == GRAPH_POST_MERGE &&
590                             graph->prev_commit_index < i)
591                                 strbuf_addstr(sb, "\\ ");
592                         else
593                                 strbuf_addstr(sb, "| ");
594                 } else if (seen_this && (graph->expansion_row > 0)) {
595                         strbuf_addstr(sb, "\\ ");
596                 } else {
597                         strbuf_addstr(sb, "| ");
598                 }
599         }
600
601         graph_pad_horizontally(graph, sb);
602
603         /*
604          * Increment graph->expansion_row,
605          * and move to state GRAPH_COMMIT if necessary
606          */
607         graph->expansion_row++;
608         if (graph->expansion_row >= num_expansion_rows)
609                 graph_update_state(graph, GRAPH_COMMIT);
610 }
611
612 static void graph_output_commit_char(struct git_graph *graph, struct strbuf *sb)
613 {
614         /*
615          * For boundary commits, print 'o'
616          * (We should only see boundary commits when revs->boundary is set.)
617          */
618         if (graph->commit->object.flags & BOUNDARY) {
619                 assert(graph->revs->boundary);
620                 strbuf_addch(sb, 'o');
621                 return;
622         }
623
624         /*
625          * If revs->left_right is set, print '<' for commits that
626          * come from the left side, and '>' for commits from the right
627          * side.
628          */
629         if (graph->revs && graph->revs->left_right) {
630                 if (graph->commit->object.flags & SYMMETRIC_LEFT)
631                         strbuf_addch(sb, '<');
632                 else
633                         strbuf_addch(sb, '>');
634                 return;
635         }
636
637         /*
638          * Print 'M' for merge commits
639          *
640          * Note that we don't check graph->num_parents to determine if the
641          * commit is a merge, since that only tracks the number of
642          * "interesting" parents.  We want to print 'M' for merge commits
643          * even if they have less than 2 interesting parents.
644          */
645         if (graph->commit->parents != NULL &&
646             graph->commit->parents->next != NULL) {
647                 strbuf_addch(sb, 'M');
648                 return;
649         }
650
651         /*
652          * Print '*' in all other cases
653          */
654         strbuf_addch(sb, '*');
655 }
656
657 void graph_output_commit_line(struct git_graph *graph, struct strbuf *sb)
658 {
659         int seen_this = 0;
660         int i, j;
661
662         /*
663          * Output the row containing this commit
664          * Iterate up to and including graph->num_columns,
665          * since the current commit may not be in any of the existing
666          * columns.  (This happens when the current commit doesn't have any
667          * children that we have already processed.)
668          */
669         seen_this = 0;
670         for (i = 0; i <= graph->num_columns; i++) {
671                 struct commit *col_commit;
672                 if (i == graph->num_columns) {
673                         if (seen_this)
674                                 break;
675                         col_commit = graph->commit;
676                 } else {
677                         col_commit = graph->columns[i].commit;
678                 }
679
680                 if (col_commit == graph->commit) {
681                         seen_this = 1;
682                         graph_output_commit_char(graph, sb);
683
684                         if (graph->num_parents < 3)
685                                 strbuf_addch(sb, ' ');
686                         else {
687                                 int num_dashes =
688                                         ((graph->num_parents - 2) * 2) - 1;
689                                 for (j = 0; j < num_dashes; j++)
690                                         strbuf_addch(sb, '-');
691                                 strbuf_addstr(sb, ". ");
692                         }
693                 } else if (seen_this && (graph->num_parents > 2)) {
694                         strbuf_addstr(sb, "\\ ");
695                 } else if (seen_this && (graph->num_parents == 2)) {
696                         /*
697                          * This is a 2-way merge commit.
698                          * There is no GRAPH_PRE_COMMIT stage for 2-way
699                          * merges, so this is the first line of output
700                          * for this commit.  Check to see what the previous
701                          * line of output was.
702                          *
703                          * If it was GRAPH_POST_MERGE, the branch line
704                          * coming into this commit may have been '\',
705                          * and not '|' or '/'.  If so, output the branch
706                          * line as '\' on this line, instead of '|'.  This
707                          * makes the output look nicer.
708                          */
709                         if (graph->prev_state == GRAPH_POST_MERGE &&
710                             graph->prev_commit_index < i)
711                                 strbuf_addstr(sb, "\\ ");
712                         else
713                                 strbuf_addstr(sb, "| ");
714                 } else {
715                         strbuf_addstr(sb, "| ");
716                 }
717         }
718
719         graph_pad_horizontally(graph, sb);
720
721         /*
722          * Update graph->state
723          */
724         if (graph->num_parents > 1)
725                 graph_update_state(graph, GRAPH_POST_MERGE);
726         else if (graph_is_mapping_correct(graph))
727                 graph_update_state(graph, GRAPH_PADDING);
728         else
729                 graph_update_state(graph, GRAPH_COLLAPSING);
730 }
731
732 void graph_output_post_merge_line(struct git_graph *graph, struct strbuf *sb)
733 {
734         int seen_this = 0;
735         int i, j;
736
737         /*
738          * Output the post-merge row
739          */
740         for (i = 0; i <= graph->num_columns; i++) {
741                 struct commit *col_commit;
742                 if (i == graph->num_columns) {
743                         if (seen_this)
744                                 break;
745                         col_commit = graph->commit;
746                 } else {
747                         col_commit = graph->columns[i].commit;
748                 }
749
750                 if (col_commit == graph->commit) {
751                         seen_this = 1;
752                         strbuf_addch(sb, '|');
753                         for (j = 0; j < graph->num_parents - 1; j++)
754                                 strbuf_addstr(sb, "\\ ");
755                 } else if (seen_this) {
756                         strbuf_addstr(sb, "\\ ");
757                 } else {
758                         strbuf_addstr(sb, "| ");
759                 }
760         }
761
762         graph_pad_horizontally(graph, sb);
763
764         /*
765          * Update graph->state
766          */
767         if (graph_is_mapping_correct(graph))
768                 graph_update_state(graph, GRAPH_PADDING);
769         else
770                 graph_update_state(graph, GRAPH_COLLAPSING);
771 }
772
773 void graph_output_collapsing_line(struct git_graph *graph, struct strbuf *sb)
774 {
775         int i;
776         int *tmp_mapping;
777
778         /*
779          * Clear out the new_mapping array
780          */
781         for (i = 0; i < graph->mapping_size; i++)
782                 graph->new_mapping[i] = -1;
783
784         for (i = 0; i < graph->mapping_size; i++) {
785                 int target = graph->mapping[i];
786                 if (target < 0)
787                         continue;
788
789                 /*
790                  * Since update_columns() always inserts the leftmost
791                  * column first, each branch's target location should
792                  * always be either its current location or to the left of
793                  * its current location.
794                  *
795                  * We never have to move branches to the right.  This makes
796                  * the graph much more legible, since whenever branches
797                  * cross, only one is moving directions.
798                  */
799                 assert(target * 2 <= i);
800
801                 if (target * 2 == i) {
802                         /*
803                          * This column is already in the
804                          * correct place
805                          */
806                         assert(graph->new_mapping[i] == -1);
807                         graph->new_mapping[i] = target;
808                 } else if (graph->new_mapping[i - 1] < 0) {
809                         /*
810                          * Nothing is to the left.
811                          * Move to the left by one
812                          */
813                         graph->new_mapping[i - 1] = target;
814                 } else if (graph->new_mapping[i - 1] == target) {
815                         /*
816                          * There is a branch line to our left
817                          * already, and it is our target.  We
818                          * combine with this line, since we share
819                          * the same parent commit.
820                          *
821                          * We don't have to add anything to the
822                          * output or new_mapping, since the
823                          * existing branch line has already taken
824                          * care of it.
825                          */
826                 } else {
827                         /*
828                          * There is a branch line to our left,
829                          * but it isn't our target.  We need to
830                          * cross over it.
831                          *
832                          * The space just to the left of this
833                          * branch should always be empty.
834                          */
835                         assert(graph->new_mapping[i - 1] > target);
836                         assert(graph->new_mapping[i - 2] < 0);
837                         graph->new_mapping[i - 2] = target;
838                 }
839         }
840
841         /*
842          * The new mapping may be 1 smaller than the old mapping
843          */
844         if (graph->new_mapping[graph->mapping_size - 1] < 0)
845                 graph->mapping_size--;
846
847         /*
848          * Output out a line based on the new mapping info
849          */
850         for (i = 0; i < graph->mapping_size; i++) {
851                 int target = graph->new_mapping[i];
852                 if (target < 0)
853                         strbuf_addch(sb, ' ');
854                 else if (target * 2 == i)
855                         strbuf_addch(sb, '|');
856                 else
857                         strbuf_addch(sb, '/');
858         }
859
860         graph_pad_horizontally(graph, sb);
861
862         /*
863          * Swap mapping and new_mapping
864          */
865         tmp_mapping = graph->mapping;
866         graph->mapping = graph->new_mapping;
867         graph->new_mapping = tmp_mapping;
868
869         /*
870          * If graph->mapping indicates that all of the branch lines
871          * are already in the correct positions, we are done.
872          * Otherwise, we need to collapse some branch lines together.
873          */
874         if (graph_is_mapping_correct(graph))
875                 graph_update_state(graph, GRAPH_PADDING);
876 }
877
878 int graph_next_line(struct git_graph *graph, struct strbuf *sb)
879 {
880         switch (graph->state) {
881         case GRAPH_PADDING:
882                 graph_output_padding_line(graph, sb);
883                 return 0;
884         case GRAPH_SKIP:
885                 graph_output_skip_line(graph, sb);
886                 return 0;
887         case GRAPH_PRE_COMMIT:
888                 graph_output_pre_commit_line(graph, sb);
889                 return 0;
890         case GRAPH_COMMIT:
891                 graph_output_commit_line(graph, sb);
892                 return 1;
893         case GRAPH_POST_MERGE:
894                 graph_output_post_merge_line(graph, sb);
895                 return 0;
896         case GRAPH_COLLAPSING:
897                 graph_output_collapsing_line(graph, sb);
898                 return 0;
899         }
900
901         assert(0);
902         return 0;
903 }
904
905 void graph_padding_line(struct git_graph *graph, struct strbuf *sb)
906 {
907         int i, j;
908
909         if (graph->state != GRAPH_COMMIT) {
910                 graph_next_line(graph, sb);
911                 return;
912         }
913
914         /*
915          * Output the row containing this commit
916          * Iterate up to and including graph->num_columns,
917          * since the current commit may not be in any of the existing
918          * columns.  (This happens when the current commit doesn't have any
919          * children that we have already processed.)
920          */
921         for (i = 0; i < graph->num_columns; i++) {
922                 struct commit *col_commit = graph->columns[i].commit;
923                 if (col_commit == graph->commit) {
924                         strbuf_addch(sb, '|');
925
926                         if (graph->num_parents < 3)
927                                 strbuf_addch(sb, ' ');
928                         else {
929                                 int num_spaces = ((graph->num_parents - 2) * 2);
930                                 for (j = 0; j < num_spaces; j++)
931                                         strbuf_addch(sb, ' ');
932                         }
933                 } else {
934                         strbuf_addstr(sb, "| ");
935                 }
936         }
937
938         graph_pad_horizontally(graph, sb);
939
940         /*
941          * Update graph->prev_state since we have output a padding line
942          */
943         graph->prev_state = GRAPH_PADDING;
944 }
945
946 int graph_is_commit_finished(struct git_graph const *graph)
947 {
948         return (graph->state == GRAPH_PADDING);
949 }
950
951 void graph_show_commit(struct git_graph *graph)
952 {
953         struct strbuf msgbuf;
954         int shown_commit_line = 0;
955
956         if (!graph)
957                 return;
958
959         strbuf_init(&msgbuf, 0);
960
961         while (!shown_commit_line) {
962                 shown_commit_line = graph_next_line(graph, &msgbuf);
963                 fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout);
964                 if (!shown_commit_line)
965                         putchar('\n');
966                 strbuf_setlen(&msgbuf, 0);
967         }
968
969         strbuf_release(&msgbuf);
970 }
971
972 void graph_show_oneline(struct git_graph *graph)
973 {
974         struct strbuf msgbuf;
975
976         if (!graph)
977                 return;
978
979         strbuf_init(&msgbuf, 0);
980         graph_next_line(graph, &msgbuf);
981         fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout);
982         strbuf_release(&msgbuf);
983 }
984
985 void graph_show_padding(struct git_graph *graph)
986 {
987         struct strbuf msgbuf;
988
989         if (!graph)
990                 return;
991
992         strbuf_init(&msgbuf, 0);
993         graph_padding_line(graph, &msgbuf);
994         fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout);
995         strbuf_release(&msgbuf);
996 }
997
998 int graph_show_remainder(struct git_graph *graph)
999 {
1000         struct strbuf msgbuf;
1001         int shown = 0;
1002
1003         if (!graph)
1004                 return 0;
1005
1006         if (graph_is_commit_finished(graph))
1007                 return 0;
1008
1009         strbuf_init(&msgbuf, 0);
1010         for (;;) {
1011                 graph_next_line(graph, &msgbuf);
1012                 fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout);
1013                 strbuf_setlen(&msgbuf, 0);
1014                 shown = 1;
1015
1016                 if (!graph_is_commit_finished(graph))
1017                         putchar('\n');
1018                 else
1019                         break;
1020         }
1021         strbuf_release(&msgbuf);
1022
1023         return shown;
1024 }
1025
1026
1027 void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb)
1028 {
1029         char *p;
1030
1031         if (!graph) {
1032                 fwrite(sb->buf, sizeof(char), sb->len, stdout);
1033                 return;
1034         }
1035
1036         /*
1037          * Print the strbuf line by line,
1038          * and display the graph info before each line but the first.
1039          */
1040         p = sb->buf;
1041         while (p) {
1042                 size_t len;
1043                 char *next_p = strchr(p, '\n');
1044                 if (next_p) {
1045                         next_p++;
1046                         len = next_p - p;
1047                 } else {
1048                         len = (sb->buf + sb->len) - p;
1049                 }
1050                 fwrite(p, sizeof(char), len, stdout);
1051                 if (next_p && *next_p != '\0')
1052                         graph_show_oneline(graph);
1053                 p = next_p;
1054         }
1055 }
1056
1057 void graph_show_commit_msg(struct git_graph *graph,
1058                            struct strbuf const *sb)
1059 {
1060         int newline_terminated;
1061
1062         if (!graph) {
1063                 /*
1064                  * If there's no graph, just print the message buffer.
1065                  *
1066                  * The message buffer for CMIT_FMT_ONELINE and
1067                  * CMIT_FMT_USERFORMAT are already missing a terminating
1068                  * newline.  All of the other formats should have it.
1069                  */
1070                 fwrite(sb->buf, sizeof(char), sb->len, stdout);
1071                 return;
1072         }
1073
1074         newline_terminated = (sb->len && sb->buf[sb->len - 1] == '\n');
1075
1076         /*
1077          * Show the commit message
1078          */
1079         graph_show_strbuf(graph, sb);
1080
1081         /*
1082          * If there is more output needed for this commit, show it now
1083          */
1084         if (!graph_is_commit_finished(graph)) {
1085                 /*
1086                  * If sb doesn't have a terminating newline, print one now,
1087                  * so we can start the remainder of the graph output on a
1088                  * new line.
1089                  */
1090                 if (!newline_terminated)
1091                         putchar('\n');
1092
1093                 graph_show_remainder(graph);
1094
1095                 /*
1096                  * If sb ends with a newline, our output should too.
1097                  */
1098                 if (newline_terminated)
1099                         putchar('\n');
1100         }
1101 }