Skip to content

Commit 660e113

Browse files
jacob-kellergitster
authored andcommitted
graph: add support for --line-prefix on all graph-aware output
Add an extension to git-diff and git-log (and any other graph-aware displayable output) such that "--line-prefix=<string>" will print the additional line-prefix on every line of output. To make this work, we have to fix a few bugs in the graph API that force graph_show_commit_msg to be used only when you have a valid graph. Additionally, we extend the default_diff_output_prefix handler to work even when no graph is enabled. This is somewhat of a hack on top of the graph API, but I think it should be acceptable here. This will be used by a future extension of submodule display which displays the submodule diff as the actual diff between the pre and post commit in the submodule project. Add some tests for both git-log and git-diff to ensure that the prefix is honored correctly. Signed-off-by: Jacob Keller <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent cd48dad commit 660e113

11 files changed

+504
-80
lines changed

Documentation/diff-options.txt

+3
Original file line numberDiff line numberDiff line change
@@ -569,5 +569,8 @@ endif::git-format-patch[]
569569
--no-prefix::
570570
Do not show any source or destination prefix.
571571

572+
--line-prefix=<prefix>::
573+
Prepend an additional prefix to every line of output.
574+
572575
For more detailed explanation on these common options, see also
573576
linkgit:gitdiffcore[7].

builtin/rev-list.c

+33-41
Original file line numberDiff line numberDiff line change
@@ -122,48 +122,40 @@ static void show_commit(struct commit *commit, void *data)
122122
ctx.fmt = revs->commit_format;
123123
ctx.output_encoding = get_log_output_encoding();
124124
pretty_print_commit(&ctx, commit, &buf);
125-
if (revs->graph) {
126-
if (buf.len) {
127-
if (revs->commit_format != CMIT_FMT_ONELINE)
128-
graph_show_oneline(revs->graph);
129-
130-
graph_show_commit_msg(revs->graph, &buf);
131-
132-
/*
133-
* Add a newline after the commit message.
134-
*
135-
* Usually, this newline produces a blank
136-
* padding line between entries, in which case
137-
* we need to add graph padding on this line.
138-
*
139-
* However, the commit message may not end in a
140-
* newline. In this case the newline simply
141-
* ends the last line of the commit message,
142-
* and we don't need any graph output. (This
143-
* always happens with CMIT_FMT_ONELINE, and it
144-
* happens with CMIT_FMT_USERFORMAT when the
145-
* format doesn't explicitly end in a newline.)
146-
*/
147-
if (buf.len && buf.buf[buf.len - 1] == '\n')
148-
graph_show_padding(revs->graph);
149-
putchar('\n');
150-
} else {
151-
/*
152-
* If the message buffer is empty, just show
153-
* the rest of the graph output for this
154-
* commit.
155-
*/
156-
if (graph_show_remainder(revs->graph))
157-
putchar('\n');
158-
if (revs->commit_format == CMIT_FMT_ONELINE)
159-
putchar('\n');
160-
}
125+
if (buf.len) {
126+
if (revs->commit_format != CMIT_FMT_ONELINE)
127+
graph_show_oneline(revs->graph);
128+
129+
graph_show_commit_msg(revs->graph, stdout, &buf);
130+
131+
/*
132+
* Add a newline after the commit message.
133+
*
134+
* Usually, this newline produces a blank
135+
* padding line between entries, in which case
136+
* we need to add graph padding on this line.
137+
*
138+
* However, the commit message may not end in a
139+
* newline. In this case the newline simply
140+
* ends the last line of the commit message,
141+
* and we don't need any graph output. (This
142+
* always happens with CMIT_FMT_ONELINE, and it
143+
* happens with CMIT_FMT_USERFORMAT when the
144+
* format doesn't explicitly end in a newline.)
145+
*/
146+
if (buf.len && buf.buf[buf.len - 1] == '\n')
147+
graph_show_padding(revs->graph);
148+
putchar('\n');
161149
} else {
162-
if (revs->commit_format != CMIT_FMT_USERFORMAT ||
163-
buf.len) {
164-
fwrite(buf.buf, 1, buf.len, stdout);
165-
putchar(info->hdr_termination);
166-
}
150+
/*
151+
* If the message buffer is empty, just show
152+
* the rest of the graph output for this
153+
* commit.
154+
*/
155+
if (graph_show_remainder(revs->graph))
156+
putchar('\n');
157+
if (revs->commit_format == CMIT_FMT_ONELINE)
158+
putchar('\n');
167159
}
168160
strbuf_release(&buf);
169161
} else {

diff.c

+7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "ll-merge.h"
1919
#include "string-list.h"
2020
#include "argv-array.h"
21+
#include "graph.h"
2122

2223
#ifdef NO_FAST_WORKING_DIRECTORY
2324
#define FAST_WORKING_DIRECTORY 0
@@ -3966,6 +3967,12 @@ int diff_opt_parse(struct diff_options *options,
39663967
options->a_prefix = optarg;
39673968
return argcount;
39683969
}
3970+
else if ((argcount = parse_long_opt("line-prefix", av, &optarg))) {
3971+
options->line_prefix = optarg;
3972+
options->line_prefix_length = strlen(options->line_prefix);
3973+
graph_setup_line_prefix(options);
3974+
return argcount;
3975+
}
39693976
else if ((argcount = parse_long_opt("dst-prefix", av, &optarg))) {
39703977
options->b_prefix = optarg;
39713978
return argcount;

diff.h

+2
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ struct diff_options {
115115
const char *pickaxe;
116116
const char *single_follow;
117117
const char *a_prefix, *b_prefix;
118+
const char *line_prefix;
119+
size_t line_prefix_length;
118120
unsigned flags;
119121
unsigned touched_flags;
120122

graph.c

+64-34
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#include "commit.h"
33
#include "color.h"
44
#include "graph.h"
5-
#include "diff.h"
65
#include "revision.h"
76

87
/* Internal API */
@@ -28,8 +27,15 @@ static void graph_padding_line(struct git_graph *graph, struct strbuf *sb);
2827
* responsible for printing this line's graph (perhaps via
2928
* graph_show_commit() or graph_show_oneline()) before calling
3029
* graph_show_strbuf().
30+
*
31+
* Note that unlike some other graph display functions, you must pass the file
32+
* handle directly. It is assumed that this is the same file handle as the
33+
* file specified by the graph diff options. This is necessary so that
34+
* graph_show_strbuf can be called even with a NULL graph.
3135
*/
32-
static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb);
36+
static void graph_show_strbuf(struct git_graph *graph,
37+
FILE *file,
38+
struct strbuf const *sb);
3339

3440
/*
3541
* TODO:
@@ -59,6 +65,17 @@ enum graph_state {
5965
GRAPH_COLLAPSING
6066
};
6167

68+
static void graph_show_line_prefix(const struct diff_options *diffopt)
69+
{
70+
if (!diffopt || !diffopt->line_prefix)
71+
return;
72+
73+
fwrite(diffopt->line_prefix,
74+
sizeof(char),
75+
diffopt->line_prefix_length,
76+
diffopt->file);
77+
}
78+
6279
static const char **column_colors;
6380
static unsigned short column_colors_max;
6481

@@ -195,13 +212,28 @@ static struct strbuf *diff_output_prefix_callback(struct diff_options *opt, void
195212
static struct strbuf msgbuf = STRBUF_INIT;
196213

197214
assert(opt);
198-
assert(graph);
199215

200216
strbuf_reset(&msgbuf);
201-
graph_padding_line(graph, &msgbuf);
217+
if (opt->line_prefix)
218+
strbuf_add(&msgbuf, opt->line_prefix,
219+
opt->line_prefix_length);
220+
if (graph)
221+
graph_padding_line(graph, &msgbuf);
202222
return &msgbuf;
203223
}
204224

225+
static const struct diff_options *default_diffopt;
226+
227+
void graph_setup_line_prefix(struct diff_options *diffopt)
228+
{
229+
default_diffopt = diffopt;
230+
231+
/* setup an output prefix callback if necessary */
232+
if (diffopt && !diffopt->output_prefix)
233+
diffopt->output_prefix = diff_output_prefix_callback;
234+
}
235+
236+
205237
struct git_graph *graph_init(struct rev_info *opt)
206238
{
207239
struct git_graph *graph = xmalloc(sizeof(struct git_graph));
@@ -1183,6 +1215,8 @@ void graph_show_commit(struct git_graph *graph)
11831215
struct strbuf msgbuf = STRBUF_INIT;
11841216
int shown_commit_line = 0;
11851217

1218+
graph_show_line_prefix(default_diffopt);
1219+
11861220
if (!graph)
11871221
return;
11881222

@@ -1200,8 +1234,10 @@ void graph_show_commit(struct git_graph *graph)
12001234
shown_commit_line = graph_next_line(graph, &msgbuf);
12011235
fwrite(msgbuf.buf, sizeof(char), msgbuf.len,
12021236
graph->revs->diffopt.file);
1203-
if (!shown_commit_line)
1237+
if (!shown_commit_line) {
12041238
putc('\n', graph->revs->diffopt.file);
1239+
graph_show_line_prefix(&graph->revs->diffopt);
1240+
}
12051241
strbuf_setlen(&msgbuf, 0);
12061242
}
12071243

@@ -1212,6 +1248,8 @@ void graph_show_oneline(struct git_graph *graph)
12121248
{
12131249
struct strbuf msgbuf = STRBUF_INIT;
12141250

1251+
graph_show_line_prefix(default_diffopt);
1252+
12151253
if (!graph)
12161254
return;
12171255

@@ -1224,6 +1262,8 @@ void graph_show_padding(struct git_graph *graph)
12241262
{
12251263
struct strbuf msgbuf = STRBUF_INIT;
12261264

1265+
graph_show_line_prefix(default_diffopt);
1266+
12271267
if (!graph)
12281268
return;
12291269

@@ -1237,6 +1277,8 @@ int graph_show_remainder(struct git_graph *graph)
12371277
struct strbuf msgbuf = STRBUF_INIT;
12381278
int shown = 0;
12391279

1280+
graph_show_line_prefix(default_diffopt);
1281+
12401282
if (!graph)
12411283
return 0;
12421284

@@ -1250,27 +1292,24 @@ int graph_show_remainder(struct git_graph *graph)
12501292
strbuf_setlen(&msgbuf, 0);
12511293
shown = 1;
12521294

1253-
if (!graph_is_commit_finished(graph))
1295+
if (!graph_is_commit_finished(graph)) {
12541296
putc('\n', graph->revs->diffopt.file);
1255-
else
1297+
graph_show_line_prefix(&graph->revs->diffopt);
1298+
} else {
12561299
break;
1300+
}
12571301
}
12581302
strbuf_release(&msgbuf);
12591303

12601304
return shown;
12611305
}
12621306

1263-
1264-
static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb)
1307+
static void graph_show_strbuf(struct git_graph *graph,
1308+
FILE *file,
1309+
struct strbuf const *sb)
12651310
{
12661311
char *p;
12671312

1268-
if (!graph) {
1269-
fwrite(sb->buf, sizeof(char), sb->len,
1270-
graph->revs->diffopt.file);
1271-
return;
1272-
}
1273-
12741313
/*
12751314
* Print the strbuf line by line,
12761315
* and display the graph info before each line but the first.
@@ -1285,37 +1324,28 @@ static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb)
12851324
} else {
12861325
len = (sb->buf + sb->len) - p;
12871326
}
1288-
fwrite(p, sizeof(char), len, graph->revs->diffopt.file);
1327+
fwrite(p, sizeof(char), len, file);
12891328
if (next_p && *next_p != '\0')
12901329
graph_show_oneline(graph);
12911330
p = next_p;
12921331
}
12931332
}
12941333

12951334
void graph_show_commit_msg(struct git_graph *graph,
1335+
FILE *file,
12961336
struct strbuf const *sb)
12971337
{
12981338
int newline_terminated;
12991339

1300-
if (!graph) {
1301-
/*
1302-
* If there's no graph, just print the message buffer.
1303-
*
1304-
* The message buffer for CMIT_FMT_ONELINE and
1305-
* CMIT_FMT_USERFORMAT are already missing a terminating
1306-
* newline. All of the other formats should have it.
1307-
*/
1308-
fwrite(sb->buf, sizeof(char), sb->len,
1309-
graph->revs->diffopt.file);
1310-
return;
1311-
}
1312-
1313-
newline_terminated = (sb->len && sb->buf[sb->len - 1] == '\n');
1314-
13151340
/*
13161341
* Show the commit message
13171342
*/
1318-
graph_show_strbuf(graph, sb);
1343+
graph_show_strbuf(graph, file, sb);
1344+
1345+
if (!graph)
1346+
return;
1347+
1348+
newline_terminated = (sb->len && sb->buf[sb->len - 1] == '\n');
13191349

13201350
/*
13211351
* If there is more output needed for this commit, show it now
@@ -1327,14 +1357,14 @@ void graph_show_commit_msg(struct git_graph *graph,
13271357
* new line.
13281358
*/
13291359
if (!newline_terminated)
1330-
putc('\n', graph->revs->diffopt.file);
1360+
putc('\n', file);
13311361

13321362
graph_show_remainder(graph);
13331363

13341364
/*
13351365
* If sb ends with a newline, our output should too.
13361366
*/
13371367
if (newline_terminated)
1338-
putc('\n', graph->revs->diffopt.file);
1368+
putc('\n', file);
13391369
}
13401370
}

graph.h

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
11
#ifndef GRAPH_H
22
#define GRAPH_H
3+
#include "diff.h"
34

45
/* A graph is a pointer to this opaque structure */
56
struct git_graph;
67

8+
/*
9+
* Called to setup global display of line_prefix diff option.
10+
*
11+
* Passed a diff_options structure which indicates the line_prefix and the
12+
* file to output the prefix to. This is sort of a hack used so that the
13+
* line_prefix will be honored by all flows which also honor "--graph"
14+
* regardless of whether a graph has actually been setup. The normal graph
15+
* flow will honor the exact diff_options passed, but a NULL graph will cause
16+
* display of a line_prefix to stdout.
17+
*/
18+
void graph_setup_line_prefix(struct diff_options *diffopt);
19+
720
/*
821
* Set up a custom scheme for column colors.
922
*
@@ -113,7 +126,14 @@ int graph_show_remainder(struct git_graph *graph);
113126
* missing a terminating newline (including if it is empty), the output
114127
* printed by graph_show_commit_msg() will also be missing a terminating
115128
* newline.
129+
*
130+
* Note that unlike some other graph display functions, you must pass the file
131+
* handle directly. It is assumed that this is the same file handle as the
132+
* file specified by the graph diff options. This is necessary so that
133+
* graph_show_commit_msg can be called even with a NULL graph.
116134
*/
117-
void graph_show_commit_msg(struct git_graph *graph, struct strbuf const *sb);
135+
void graph_show_commit_msg(struct git_graph *graph,
136+
FILE *file,
137+
struct strbuf const *sb);
118138

119139
#endif /* GRAPH_H */

log-tree.c

+1-4
Original file line numberDiff line numberDiff line change
@@ -715,10 +715,7 @@ void show_log(struct rev_info *opt)
715715
else
716716
opt->missing_newline = 0;
717717

718-
if (opt->graph)
719-
graph_show_commit_msg(opt->graph, &msgbuf);
720-
else
721-
fwrite(msgbuf.buf, sizeof(char), msgbuf.len, opt->diffopt.file);
718+
graph_show_commit_msg(opt->graph, opt->diffopt.file, &msgbuf);
722719
if (opt->use_terminator && !commit_format_is_empty(opt->commit_format)) {
723720
if (!opt->missing_newline)
724721
graph_show_padding(opt->graph);

0 commit comments

Comments
 (0)