112
return column_colors[color];
113
}
114
115
-static void strbuf_write_column(struct strbuf *sb, const struct column *c,
116
- char col_char)
115
+struct graph_line {
116
+ struct strbuf *buf;
117
+ size_t width;
118
+};
119
+
120
+static inline void graph_line_addch(struct graph_line *line, int c)
121
+{
122
+ strbuf_addch(line->buf, c);
123
+ line->width++;
124
+}
125
+
126
+static inline void graph_line_addchars(struct graph_line *line, int c, size_t n)
127
+{
128
+ strbuf_addchars(line->buf, c, n);
129
+ line->width += n;
130
+}
131
+
132
+static inline void graph_line_addstr(struct graph_line *line, const char *s)
133
+{
134
+ strbuf_addstr(line->buf, s);
135
+ line->width += strlen(s);
136
+}
137
+
138
+static inline void graph_line_addcolor(struct graph_line *line, unsigned short color)
139
+{
140
+ strbuf_addstr(line->buf, column_get_color_code(color));
141
+}
142
+
143
+static void graph_line_write_column(struct graph_line *line, const struct column *c,
144
+ char col_char)
145
{
146
if (c->color < column_colors_max)
119
- strbuf_addstr(sb, column_get_color_code(c->color));
120
- strbuf_addch(sb, col_char);
147
+ graph_line_addcolor(line, c->color);
148
+ graph_line_addch(line, col_char);
149
if (c->color < column_colors_max)
122
- strbuf_addstr(sb, column_get_color_code(column_colors_max));
150
+ graph_line_addcolor(line, column_colors_max);
151
}
152
153
struct git_graph {
714
return 1;
715
}
716
689
-static void graph_pad_horizontally(struct git_graph *graph, struct strbuf *sb,
690
- int chars_written)
717
+static void graph_pad_horizontally(struct git_graph *graph, struct graph_line *line)
718
{
719
/*
720
* Add additional spaces to the end of the strbuf, so that all
723
* This way, fields printed to the right of the graph will remain
724
* aligned for the entire commit.
725
*/
699
- if (chars_written < graph->width)
700
- strbuf_addchars(sb, ' ', graph->width - chars_written);
726
+ if (line->width < graph->width)
727
+ graph_line_addchars(line, ' ', graph->width - line->width);
728
}
729
730
static void graph_output_padding_line(struct git_graph *graph,
704
- struct strbuf *sb)
731
+ struct graph_line *line)
732
{
733
int i;
734
746
* Output a padding row, that leaves all branch lines unchanged
747
*/
748
for (i = 0; i < graph->num_new_columns; i++) {
722
- strbuf_write_column(sb, &graph->new_columns[i], '|');
723
- strbuf_addch(sb, ' ');
749
+ graph_line_write_column(line, &graph->new_columns[i], '|');
750
+ graph_line_addch(line, ' ');
751
}
752
726
- graph_pad_horizontally(graph, sb, graph->num_new_columns * 2);
753
+ graph_pad_horizontally(graph, line);
754
}
755
756
760
}
761
762
736
-static void graph_output_skip_line(struct git_graph *graph, struct strbuf *sb)
763
+static void graph_output_skip_line(struct git_graph *graph, struct graph_line *line)
764
{
765
/*
766
* Output an ellipsis to indicate that a portion
767
* of the graph is missing.
768
*/
742
- strbuf_addstr(sb, "...");
743
- graph_pad_horizontally(graph, sb, 3);
769
+ graph_line_addstr(line, "...");
770
+ graph_pad_horizontally(graph, line);
771
772
if (graph->num_parents >= 3 &&
773
graph->commit_index < (graph->num_columns - 1))
777
}
778
779
static void graph_output_pre_commit_line(struct git_graph *graph,
753
- struct strbuf *sb)
780
+ struct graph_line *line)
781
{
782
int num_expansion_rows;
783
int i, seen_this;
757
- int chars_written;
784
785
/*
786
* This function formats a row that increases the space around a commit
803
* Output the row
804
*/
805
seen_this = 0;
780
- chars_written = 0;
806
for (i = 0; i < graph->num_columns; i++) {
807
struct column *col = &graph->columns[i];
808
if (col->commit == graph->commit) {
809
seen_this = 1;
785
- strbuf_write_column(sb, col, '|');
786
- strbuf_addchars(sb, ' ', graph->expansion_row);
787
- chars_written += 1 + graph->expansion_row;
810
+ graph_line_write_column(line, col, '|');
811
+ graph_line_addchars(line, ' ', graph->expansion_row);
812
} else if (seen_this && (graph->expansion_row == 0)) {
813
/*
814
* This is the first line of the pre-commit output.
821
*/
822
if (graph->prev_state == GRAPH_POST_MERGE &&
823
graph->prev_commit_index < i)
800
- strbuf_write_column(sb, col, '\\');
824
+ graph_line_write_column(line, col, '\\');
825
else
802
- strbuf_write_column(sb, col, '|');
803
- chars_written++;
826
+ graph_line_write_column(line, col, '|');
827
} else if (seen_this && (graph->expansion_row > 0)) {
805
- strbuf_write_column(sb, col, '\\');
806
- chars_written++;
828
+ graph_line_write_column(line, col, '\\');
829
} else {
808
- strbuf_write_column(sb, col, '|');
809
- chars_written++;
830
+ graph_line_write_column(line, col, '|');
831
}
811
- strbuf_addch(sb, ' ');
812
- chars_written++;
832
+ graph_line_addch(line, ' ');
833
}
834
815
- graph_pad_horizontally(graph, sb, chars_written);
835
+ graph_pad_horizontally(graph, line);
836
837
/*
838
* Increment graph->expansion_row,
843
graph_update_state(graph, GRAPH_COMMIT);
844
}
845
826
-static void graph_output_commit_char(struct git_graph *graph, struct strbuf *sb)
846
+static void graph_output_commit_char(struct git_graph *graph, struct graph_line *line)
847
{
848
/*
849
* For boundary commits, print 'o'
851
*/
852
if (graph->commit->object.flags & BOUNDARY) {
853
assert(graph->revs->boundary);
834
- strbuf_addch(sb, 'o');
854
+ graph_line_addch(line, 'o');
855
return;
856
}
857
858
/*
859
* get_revision_mark() handles all other cases without assert()
860
*/
841
- strbuf_addstr(sb, get_revision_mark(graph->revs, graph->commit));
861
+ graph_line_addstr(line, get_revision_mark(graph->revs, graph->commit));
862
}
863
864
/*
845
- * Draw the horizontal dashes of an octopus merge and return the number of
846
- * characters written.
865
+ * Draw the horizontal dashes of an octopus merge.
866
*/
848
-static int graph_draw_octopus_merge(struct git_graph *graph,
849
- struct strbuf *sb)
867
+static void graph_draw_octopus_merge(struct git_graph *graph, struct graph_line *line)
868
{
869
/*
870
* Here dashless_parents represents the number of parents which don't
904
905
int i;
906
for (i = 0; i < dashful_parents; i++) {
889
- strbuf_write_column(sb, &graph->new_columns[i+first_col], '-');
890
- strbuf_write_column(sb, &graph->new_columns[i+first_col],
891
- i == dashful_parents-1 ? '.' : '-');
907
+ graph_line_write_column(line, &graph->new_columns[i+first_col], '-');
908
+ graph_line_write_column(line, &graph->new_columns[i+first_col],
909
+ i == dashful_parents-1 ? '.' : '-');
910
}
893
- return 2 * dashful_parents;
911
}
912
896
-static void graph_output_commit_line(struct git_graph *graph, struct strbuf *sb)
913
+static void graph_output_commit_line(struct git_graph *graph, struct graph_line *line)
914
{
915
int seen_this = 0;
899
- int i, chars_written;
916
+ int i;
917
918
/*
919
* Output the row containing this commit
923
* children that we have already processed.)
924
*/
925
seen_this = 0;
909
- chars_written = 0;
926
for (i = 0; i <= graph->num_columns; i++) {
927
struct column *col = &graph->columns[i];
928
struct commit *col_commit;
936
937
if (col_commit == graph->commit) {
938
seen_this = 1;
923
- graph_output_commit_char(graph, sb);
924
- chars_written++;
939
+ graph_output_commit_char(graph, line);
940
941
if (graph->num_parents > 2)
927
- chars_written += graph_draw_octopus_merge(graph,
928
- sb);
942
+ graph_draw_octopus_merge(graph, line);
943
} else if (seen_this && (graph->num_parents > 2)) {
930
- strbuf_write_column(sb, col, '\\');
931
- chars_written++;
944
+ graph_line_write_column(line, col, '\\');
945
} else if (seen_this && (graph->num_parents == 2)) {
946
/*
947
* This is a 2-way merge commit.
958
*/
959
if (graph->prev_state == GRAPH_POST_MERGE &&
960
graph->prev_commit_index < i)
948
- strbuf_write_column(sb, col, '\\');
961
+ graph_line_write_column(line, col, '\\');
962
else
950
- strbuf_write_column(sb, col, '|');
951
- chars_written++;
963
+ graph_line_write_column(line, col, '|');
964
} else {
953
- strbuf_write_column(sb, col, '|');
954
- chars_written++;
965
+ graph_line_write_column(line, col, '|');
966
}
956
- strbuf_addch(sb, ' ');
957
- chars_written++;
967
+ graph_line_addch(line, ' ');
968
}
969
960
- graph_pad_horizontally(graph, sb, chars_written);
970
+ graph_pad_horizontally(graph, line);
971
972
/*
973
* Update graph->state
991
return NULL;
992
}
993
984
-static void graph_output_post_merge_line(struct git_graph *graph, struct strbuf *sb)
994
+static void graph_output_post_merge_line(struct git_graph *graph, struct graph_line *line)
995
{
996
int seen_this = 0;
987
- int i, j, chars_written;
997
+ int i, j;
998
999
/*
1000
* Output the post-merge row
1001
*/
992
- chars_written = 0;
1002
for (i = 0; i <= graph->num_columns; i++) {
1003
struct column *col = &graph->columns[i];
1004
struct commit *col_commit;
1025
par_column = find_new_column_by_commit(graph, parents->item);
1026
assert(par_column);
1027
1019
- strbuf_write_column(sb, par_column, '|');
1020
- chars_written++;
1028
+ graph_line_write_column(line, par_column, '|');
1029
for (j = 0; j < graph->num_parents - 1; j++) {
1030
parents = next_interesting_parent(graph, parents);
1031
assert(parents);
1032
par_column = find_new_column_by_commit(graph, parents->item);
1033
assert(par_column);
1026
- strbuf_write_column(sb, par_column, '\\');
1027
- strbuf_addch(sb, ' ');
1034
+ graph_line_write_column(line, par_column, '\\');
1035
+ graph_line_addch(line, ' ');
1036
}
1029
- chars_written += j * 2;
1037
} else if (seen_this) {
1031
- strbuf_write_column(sb, col, '\\');
1032
- strbuf_addch(sb, ' ');
1033
- chars_written += 2;
1038
+ graph_line_write_column(line, col, '\\');
1039
+ graph_line_addch(line, ' ');
1040
} else {
1035
- strbuf_write_column(sb, col, '|');
1036
- strbuf_addch(sb, ' ');
1037
- chars_written += 2;
1041
+ graph_line_write_column(line, col, '|');
1042
+ graph_line_addch(line, ' ');
1043
}
1044
}
1045
1041
- graph_pad_horizontally(graph, sb, chars_written);
1046
+ graph_pad_horizontally(graph, line);
1047
1048
/*
1049
* Update graph->state
1054
graph_update_state(graph, GRAPH_COLLAPSING);
1055
}
1056
1052
-static void graph_output_collapsing_line(struct git_graph *graph, struct strbuf *sb)
1057
+static void graph_output_collapsing_line(struct git_graph *graph, struct graph_line *line)
1058
{
1059
int i;
1060
short used_horizontal = 0;
1164
for (i = 0; i < graph->mapping_size; i++) {
1165
int target = graph->new_mapping[i];
1166
if (target < 0)
1162
- strbuf_addch(sb, ' ');
1167
+ graph_line_addch(line, ' ');
1168
else if (target * 2 == i)
1164
- strbuf_write_column(sb, &graph->new_columns[target], '|');
1169
+ graph_line_write_column(line, &graph->new_columns[target], '|');
1170
else if (target == horizontal_edge_target &&
1171
i != horizontal_edge - 1) {
1172
/*
1177
if (i != (target * 2)+3)
1178
graph->new_mapping[i] = -1;
1179
used_horizontal = 1;
1175
- strbuf_write_column(sb, &graph->new_columns[target], '_');
1180
+ graph_line_write_column(line, &graph->new_columns[target], '_');
1181
} else {
1182
if (used_horizontal && i < horizontal_edge)
1183
graph->new_mapping[i] = -1;
1179
- strbuf_write_column(sb, &graph->new_columns[target], '/');
1184
+ graph_line_write_column(line, &graph->new_columns[target], '/');
1185
1186
}
1187
}
1188
1184
- graph_pad_horizontally(graph, sb, graph->mapping_size);
1189
+ graph_pad_horizontally(graph, line);
1190
1191
/*
1192
* Swap mapping and new_mapping
1204
1205
int graph_next_line(struct git_graph *graph, struct strbuf *sb)
1206
{
1207
+ struct graph_line line = { .buf = sb, .width = 0 };
1208
+
1209
switch (graph->state) {
1210
case GRAPH_PADDING:
1204
- graph_output_padding_line(graph, sb);
1211
+ graph_output_padding_line(graph, &line);
1212
return 0;
1213
case GRAPH_SKIP:
1207
- graph_output_skip_line(graph, sb);
1214
+ graph_output_skip_line(graph, &line);
1215
return 0;
1216
case GRAPH_PRE_COMMIT:
1210
- graph_output_pre_commit_line(graph, sb);
1217
+ graph_output_pre_commit_line(graph, &line);
1218
return 0;
1219
case GRAPH_COMMIT:
1213
- graph_output_commit_line(graph, sb);
1220
+ graph_output_commit_line(graph, &line);
1221
return 1;
1222
case GRAPH_POST_MERGE:
1216
- graph_output_post_merge_line(graph, sb);
1223
+ graph_output_post_merge_line(graph, &line);
1224
return 0;
1225
case GRAPH_COLLAPSING:
1219
- graph_output_collapsing_line(graph, sb);
1226
+ graph_output_collapsing_line(graph, &line);
1227
return 0;
1228
}
1229
1234
static void graph_padding_line(struct git_graph *graph, struct strbuf *sb)
1235
{
1236
int i;
1230
- int chars_written = 0;
1237
+ struct graph_line line = { .buf = sb, .width = 0 };
1238
1239
if (graph->state != GRAPH_COMMIT) {
1240
graph_next_line(graph, sb);
1251
for (i = 0; i < graph->num_columns; i++) {
1252
struct column *col = &graph->columns[i];
1253
1247
- strbuf_write_column(sb, col, '|');
1248
- chars_written++;
1254
+ graph_line_write_column(&line, col, '|');
1255
1256
if (col->commit == graph->commit && graph->num_parents > 2) {
1257
int len = (graph->num_parents - 2) * 2;
1252
- strbuf_addchars(sb, ' ', len);
1253
- chars_written += len;
1258
+ graph_line_addchars(&line, ' ', len);
1259
} else {
1255
- strbuf_addch(sb, ' ');
1256
- chars_written++;
1260
+ graph_line_addch(&line, ' ');
1261
}
1262
}
1263
1260
- graph_pad_horizontally(graph, sb, chars_written);
1264
+ graph_pad_horizontally(graph, &line);
1265
1266
/*
1267
* Update graph->prev_state since we have output a padding line