X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=graph.c;h=dc2c1ec5d77932dc1e30057603d02a79b4d60f94;hb=7528f27dd677bed65d758667a621034b853595b4;hp=616e18b13f496cd97bce5333b6c7655ae3cfa2f0;hpb=c12172d2eab91b79b8181b04ab5a5332a96e34a8;p=git.git diff --git a/graph.c b/graph.c index 616e18b13..dc2c1ec5d 100644 --- a/graph.c +++ b/graph.c @@ -54,12 +54,22 @@ struct git_graph { * The commit currently being processed */ struct commit *commit; + /* The rev-info used for the current traversal */ + struct rev_info *revs; /* - * The number of parents this commit has. - * (Stored so we don't have to walk over them each time we need - * this number) + * The number of interesting parents that this commit has. + * + * Note that this is not the same as the actual number of parents. + * This count excludes parents that won't be printed in the graph + * output, as determined by graph_is_interesting(). */ int num_parents; + /* + * The width of the graph output for this commit. + * All rows for this commit are padded to this width, so that + * messages printed after the graph output are aligned. + */ + int width; /* * The next expansion row to print * when state is GRAPH_PRE_COMMIT @@ -119,10 +129,11 @@ struct git_graph { int *new_mapping; }; -struct git_graph *graph_init(void) +struct git_graph *graph_init(struct rev_info *opt) { struct git_graph *graph = xmalloc(sizeof(struct git_graph)); graph->commit = NULL; + graph->revs = opt; graph->num_parents = 0; graph->expansion_row = 0; graph->state = GRAPH_PADDING; @@ -174,6 +185,18 @@ static void graph_ensure_capacity(struct git_graph *graph, int num_columns) sizeof(int) * 2 * graph->column_capacity); } +/* + * Returns 1 if the commit will be printed in the graph output, + * and 0 otherwise. + */ +static int graph_is_interesting(struct commit *commit) +{ + /* + * Uninteresting and pruned commits won't be printed + */ + return (commit->object.flags & (UNINTERESTING | TREESAME)) ? 0 : 1; +} + static void graph_insert_into_new_columns(struct git_graph *graph, struct commit *commit, int *mapping_index) @@ -181,9 +204,9 @@ static void graph_insert_into_new_columns(struct git_graph *graph, int i; /* - * Ignore uinteresting and pruned commits + * Ignore uinteresting commits */ - if (commit->object.flags & (UNINTERESTING | TREESAME)) + if (!graph_is_interesting(commit)) return; /* @@ -207,13 +230,48 @@ static void graph_insert_into_new_columns(struct git_graph *graph, graph->num_new_columns++; } +static void graph_update_width(struct git_graph *graph, + int is_commit_in_existing_columns) +{ + /* + * Compute the width needed to display the graph for this commit. + * This is the maximum width needed for any row. All other rows + * will be padded to this width. + * + * Compute the number of columns in the widest row: + * Count each existing column (graph->num_columns), and each new + * column added by this commit. + */ + int max_cols = graph->num_columns + graph->num_parents; + + /* + * Even if the current commit has no parents to be printed, it + * still takes up a column for itself. + */ + if (graph->num_parents < 1) + max_cols++; + + /* + * We added a column for the the current commit as part of + * graph->num_parents. If the current commit was already in + * graph->columns, then we have double counted it. + */ + if (is_commit_in_existing_columns) + max_cols--; + + /* + * Each column takes up 2 spaces + */ + graph->width = max_cols * 2; +} + 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; + int i, seen_this, is_commit_in_columns; /* * Swap graph->columns with graph->new_columns @@ -259,17 +317,20 @@ static void graph_update_columns(struct git_graph *graph) */ seen_this = 0; mapping_idx = 0; + is_commit_in_columns = 1; for (i = 0; i <= graph->num_columns; i++) { struct commit *col_commit; if (i == graph->num_columns) { if (seen_this) break; + is_commit_in_columns = 0; col_commit = graph->commit; } else { col_commit = graph->columns[i].commit; } if (col_commit == graph->commit) { + int old_mapping_idx = mapping_idx; seen_this = 1; for (parent = graph->commit->parents; parent; @@ -278,6 +339,14 @@ static void graph_update_columns(struct git_graph *graph) parent->item, &mapping_idx); } + /* + * We always need to increment mapping_idx by at + * least 2, even if it has no interesting parents. + * The current commit always takes up at least 2 + * spaces. + */ + if (mapping_idx == old_mapping_idx) + mapping_idx += 2; } else { graph_insert_into_new_columns(graph, col_commit, &mapping_idx); @@ -290,6 +359,11 @@ static void graph_update_columns(struct git_graph *graph) while (graph->mapping_size > 1 && graph->mapping[graph->mapping_size - 1] < 0) graph->mapping_size--; + + /* + * Compute graph->width for this commit + */ + graph_update_width(graph, is_commit_in_columns); } void graph_update(struct git_graph *graph, struct commit *commit) @@ -302,11 +376,13 @@ void graph_update(struct git_graph *graph, struct commit *commit) graph->commit = commit; /* - * Count how many parents this commit has + * Count how many interesting parents this commit has */ graph->num_parents = 0; - for (parent = commit->parents; parent; parent = parent->next) - graph->num_parents++; + for (parent = commit->parents; parent; parent = parent->next) { + if (graph_is_interesting(parent->item)) + graph->num_parents++; + } /* * Call graph_update_columns() to update @@ -368,22 +444,12 @@ static void graph_pad_horizontally(struct git_graph *graph, struct strbuf *sb) * * This way, fields printed to the right of the graph will remain * aligned for the entire commit. - * - * This computation results in 3 extra space to the right in most - * cases, but only 1 extra space if the commit doesn't have any - * children that have already been displayed in the graph (i.e., - * if the current commit isn't in graph->columns). */ - size_t extra; - size_t final_width = graph->num_columns + graph->num_parents; - if (graph->num_parents < 1) - final_width++; - final_width *= 2; - - if (sb->len >= final_width) + int extra; + if (sb->len >= graph->width) return; - extra = final_width - sb->len; + extra = graph->width - sb->len; strbuf_addf(sb, "%*s", (int) extra, ""); } @@ -502,7 +568,13 @@ void graph_output_commit_line(struct git_graph *graph, struct strbuf *sb) if (col_commit == graph->commit) { seen_this = 1; - if (graph->num_parents > 1) + + if (graph->revs && graph->revs->left_right) { + if (graph->commit->object.flags & SYMMETRIC_LEFT) + strbuf_addch(sb, '<'); + else + strbuf_addch(sb, '>'); + } else if (graph->num_parents > 1) strbuf_addch(sb, 'M'); else strbuf_addch(sb, '*');