#include "cache.h"
+#include "config.h"
#include "commit.h"
#include "color.h"
#include "graph.h"
-#include "diff.h"
#include "revision.h"
+#include "argv-array.h"
/* Internal API */
* responsible for printing this line's graph (perhaps via
* graph_show_commit() or graph_show_oneline()) before calling
* graph_show_strbuf().
+ *
+ * Note that unlike some other graph display functions, you must pass the file
+ * handle directly. It is assumed that this is the same file handle as the
+ * file specified by the graph diff options. This is necessary so that
+ * graph_show_strbuf can be called even with a NULL graph.
*/
-static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb);
+static void graph_show_strbuf(struct git_graph *graph,
+ FILE *file,
+ struct strbuf const *sb);
/*
* TODO:
GRAPH_COLLAPSING
};
+static void graph_show_line_prefix(const struct diff_options *diffopt)
+{
+ if (!diffopt || !diffopt->line_prefix)
+ return;
+
+ fwrite(diffopt->line_prefix,
+ sizeof(char),
+ diffopt->line_prefix_length,
+ diffopt->file);
+}
+
static const char **column_colors;
static unsigned short column_colors_max;
+static void parse_graph_colors_config(struct argv_array *colors, const char *string)
+{
+ const char *end, *start;
+
+ start = string;
+ end = string + strlen(string);
+ while (start < end) {
+ const char *comma = strchrnul(start, ',');
+ char color[COLOR_MAXLEN];
+
+ if (!color_parse_mem(start, comma - start, color))
+ argv_array_push(colors, color);
+ else
+ warning(_("ignore invalid color '%.*s' in log.graphColors"),
+ (int)(comma - start), start);
+ start = comma + 1;
+ }
+ argv_array_push(colors, GIT_COLOR_RESET);
+}
+
void graph_set_column_colors(const char **colors, unsigned short colors_max)
{
column_colors = colors;
static struct strbuf msgbuf = STRBUF_INIT;
assert(opt);
- assert(graph);
- opt->output_prefix_length = graph->width;
strbuf_reset(&msgbuf);
- graph_padding_line(graph, &msgbuf);
+ if (opt->line_prefix)
+ strbuf_add(&msgbuf, opt->line_prefix,
+ opt->line_prefix_length);
+ if (graph)
+ graph_padding_line(graph, &msgbuf);
return &msgbuf;
}
+static const struct diff_options *default_diffopt;
+
+void graph_setup_line_prefix(struct diff_options *diffopt)
+{
+ default_diffopt = diffopt;
+
+ /* setup an output prefix callback if necessary */
+ if (diffopt && !diffopt->output_prefix)
+ diffopt->output_prefix = diff_output_prefix_callback;
+}
+
+
struct git_graph *graph_init(struct rev_info *opt)
{
struct git_graph *graph = xmalloc(sizeof(struct git_graph));
- if (!column_colors)
- graph_set_column_colors(column_colors_ansi,
- column_colors_ansi_max);
+ if (!column_colors) {
+ char *string;
+ if (git_config_get_string("log.graphcolors", &string)) {
+ /* not configured -- use default */
+ graph_set_column_colors(column_colors_ansi,
+ column_colors_ansi_max);
+ } else {
+ static struct argv_array custom_colors = ARGV_ARRAY_INIT;
+ argv_array_clear(&custom_colors);
+ parse_graph_colors_config(&custom_colors, string);
+ free(string);
+ /* graph_set_column_colors takes a max-index, not a count */
+ graph_set_column_colors(custom_colors.argv,
+ custom_colors.argc - 1);
+ }
+ }
graph->commit = NULL;
graph->revs = opt;
*/
opt->diffopt.output_prefix = diff_output_prefix_callback;
opt->diffopt.output_prefix_data = graph;
- opt->diffopt.output_prefix_length = 0;
return graph;
}
static void graph_update_columns(struct git_graph *graph)
{
struct commit_list *parent;
- struct column *tmp_columns;
int max_new_columns;
int mapping_idx;
int i, seen_this, is_commit_in_columns;
* We'll re-use the old columns array as storage to compute the new
* columns list for the commit after this one.
*/
- tmp_columns = graph->columns;
- graph->columns = graph->new_columns;
+ SWAP(graph->columns, graph->new_columns);
graph->num_columns = graph->num_new_columns;
-
- graph->new_columns = tmp_columns;
graph->num_new_columns = 0;
/*
* This way, fields printed to the right of the graph will remain
* aligned for the entire commit.
*/
- int extra;
- if (chars_written >= graph->width)
- return;
-
- extra = graph->width - chars_written;
- strbuf_addf(sb, "%*s", (int) extra, "");
+ if (chars_written < graph->width)
+ strbuf_addchars(sb, ' ', graph->width - chars_written);
}
static void graph_output_padding_line(struct git_graph *graph,
if (col->commit == graph->commit) {
seen_this = 1;
strbuf_write_column(sb, col, '|');
- strbuf_addf(sb, "%*s", graph->expansion_row, "");
+ strbuf_addchars(sb, ' ', graph->expansion_row);
chars_written += 1 + graph->expansion_row;
} else if (seen_this && (graph->expansion_row == 0)) {
/*
static void graph_output_collapsing_line(struct git_graph *graph, struct strbuf *sb)
{
int i;
- int *tmp_mapping;
short used_horizontal = 0;
int horizontal_edge = -1;
int horizontal_edge_target = -1;
/*
* Swap mapping and new_mapping
*/
- tmp_mapping = graph->mapping;
- graph->mapping = graph->new_mapping;
- graph->new_mapping = tmp_mapping;
+ SWAP(graph->mapping, graph->new_mapping);
/*
* If graph->mapping indicates that all of the branch lines
struct strbuf msgbuf = STRBUF_INIT;
int shown_commit_line = 0;
+ graph_show_line_prefix(default_diffopt);
+
if (!graph)
return;
shown_commit_line = graph_next_line(graph, &msgbuf);
fwrite(msgbuf.buf, sizeof(char), msgbuf.len,
graph->revs->diffopt.file);
- if (!shown_commit_line)
+ if (!shown_commit_line) {
putc('\n', graph->revs->diffopt.file);
+ graph_show_line_prefix(&graph->revs->diffopt);
+ }
strbuf_setlen(&msgbuf, 0);
}
{
struct strbuf msgbuf = STRBUF_INIT;
+ graph_show_line_prefix(default_diffopt);
+
if (!graph)
return;
{
struct strbuf msgbuf = STRBUF_INIT;
+ graph_show_line_prefix(default_diffopt);
+
if (!graph)
return;
struct strbuf msgbuf = STRBUF_INIT;
int shown = 0;
+ graph_show_line_prefix(default_diffopt);
+
if (!graph)
return 0;
strbuf_setlen(&msgbuf, 0);
shown = 1;
- if (!graph_is_commit_finished(graph))
+ if (!graph_is_commit_finished(graph)) {
putc('\n', graph->revs->diffopt.file);
- else
+ graph_show_line_prefix(&graph->revs->diffopt);
+ } else {
break;
+ }
}
strbuf_release(&msgbuf);
return shown;
}
-
-static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb)
+static void graph_show_strbuf(struct git_graph *graph,
+ FILE *file,
+ struct strbuf const *sb)
{
char *p;
- if (!graph) {
- fwrite(sb->buf, sizeof(char), sb->len,
- graph->revs->diffopt.file);
- return;
- }
-
/*
* Print the strbuf line by line,
* and display the graph info before each line but the first.
} else {
len = (sb->buf + sb->len) - p;
}
- fwrite(p, sizeof(char), len, graph->revs->diffopt.file);
+ fwrite(p, sizeof(char), len, file);
if (next_p && *next_p != '\0')
graph_show_oneline(graph);
p = next_p;
}
void graph_show_commit_msg(struct git_graph *graph,
+ FILE *file,
struct strbuf const *sb)
{
int newline_terminated;
- if (!graph) {
- /*
- * If there's no graph, just print the message buffer.
- *
- * The message buffer for CMIT_FMT_ONELINE and
- * CMIT_FMT_USERFORMAT are already missing a terminating
- * newline. All of the other formats should have it.
- */
- fwrite(sb->buf, sizeof(char), sb->len,
- graph->revs->diffopt.file);
- return;
- }
-
- newline_terminated = (sb->len && sb->buf[sb->len - 1] == '\n');
-
/*
* Show the commit message
*/
- graph_show_strbuf(graph, sb);
+ graph_show_strbuf(graph, file, sb);
+
+ if (!graph)
+ return;
+
+ newline_terminated = (sb->len && sb->buf[sb->len - 1] == '\n');
/*
* If there is more output needed for this commit, show it now
* new line.
*/
if (!newline_terminated)
- putc('\n', graph->revs->diffopt.file);
+ putc('\n', file);
graph_show_remainder(graph);
* If sb ends with a newline, our output should too.
*/
if (newline_terminated)
- putc('\n', graph->revs->diffopt.file);
+ putc('\n', file);
}
}