Merge branch 'js/log-to-diffopt-file'

The commands in the "log/diff" family have had an FILE* pointer in the
data structure they pass around for a long time, but some codepaths
used to always write to the standard output.  As a preparatory step
to make "git format-patch" available to the internal callers, these
codepaths have been updated to consistently write into that FILE*
instead.

* js/log-to-diffopt-file:
  mingw: fix the shortlog --output=<file> test
  diff: do not color output when --color=auto and --output=<file> is given
  t4211: ensure that log respects --output=<file>
  shortlog: respect the --output=<file> setting
  format-patch: use stdout directly
  format-patch: avoid freopen()
  format-patch: explicitly switch off color when writing to files
  shortlog: support outputting to streams other than stdout
  graph: respect the diffopt.file setting
  line-log: respect diffopt's configured output file stream
  log-tree: respect diffopt's configured output file stream
  log: prepare log/log-tree to reuse the diffopt.close_file attribute
This commit is contained in:
Junio C Hamano 2016-07-19 13:22:15 -07:00
Родитель 7725bebe21 bac233f2c2
Коммит 63641fb071
9 изменённых файлов: 144 добавлений и 107 удалений

Просмотреть файл

@ -238,16 +238,17 @@ static void show_early_header(struct rev_info *rev, const char *stage, int nr)
if (rev->commit_format != CMIT_FMT_ONELINE)
putchar(rev->diffopt.line_termination);
}
printf(_("Final output: %d %s\n"), nr, stage);
fprintf(rev->diffopt.file, _("Final output: %d %s\n"), nr, stage);
}
static struct itimerval early_output_timer;
static void log_show_early(struct rev_info *revs, struct commit_list *list)
{
int i = revs->early_output;
int i = revs->early_output, close_file = revs->diffopt.close_file;
int show_header = 1;
revs->diffopt.close_file = 0;
sort_in_topological_order(&list, revs->sort_order);
while (list && i) {
struct commit *commit = list->item;
@ -264,14 +265,19 @@ static void log_show_early(struct rev_info *revs, struct commit_list *list)
case commit_ignore:
break;
case commit_error:
if (close_file)
fclose(revs->diffopt.file);
return;
}
list = list->next;
}
/* Did we already get enough commits for the early output? */
if (!i)
if (!i) {
if (close_file)
fclose(revs->diffopt.file);
return;
}
/*
* ..if no, then repeat it twice a second until we
@ -333,7 +339,7 @@ static int cmd_log_walk(struct rev_info *rev)
{
struct commit *commit;
int saved_nrl = 0;
int saved_dcctc = 0;
int saved_dcctc = 0, close_file = rev->diffopt.close_file;
if (rev->early_output)
setup_early_output(rev);
@ -349,6 +355,7 @@ static int cmd_log_walk(struct rev_info *rev)
* and HAS_CHANGES being accumulated in rev->diffopt, so be careful to
* retain that state information if replacing rev->diffopt in this loop
*/
rev->diffopt.close_file = 0;
while ((commit = get_revision(rev)) != NULL) {
if (!log_tree_commit(rev, commit) && rev->max_count >= 0)
/*
@ -369,6 +376,8 @@ static int cmd_log_walk(struct rev_info *rev)
}
rev->diffopt.degraded_cc_to_c = saved_dcctc;
rev->diffopt.needed_rename_limit = saved_nrl;
if (close_file)
fclose(rev->diffopt.file);
if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&
DIFF_OPT_TST(&rev->diffopt, CHECK_FAILED)) {
@ -451,7 +460,7 @@ static void show_tagger(char *buf, int len, struct rev_info *rev)
pp.fmt = rev->commit_format;
pp.date_mode = rev->date_mode;
pp_user_info(&pp, "Tagger", &out, buf, get_log_output_encoding());
printf("%s", out.buf);
fprintf(rev->diffopt.file, "%s", out.buf);
strbuf_release(&out);
}
@ -462,7 +471,7 @@ static int show_blob_object(const unsigned char *sha1, struct rev_info *rev, con
char *buf;
unsigned long size;
fflush(stdout);
fflush(rev->diffopt.file);
if (!DIFF_OPT_TOUCHED(&rev->diffopt, ALLOW_TEXTCONV) ||
!DIFF_OPT_TST(&rev->diffopt, ALLOW_TEXTCONV))
return stream_blob_to_fd(1, sha1, NULL, 0);
@ -502,7 +511,7 @@ static int show_tag_object(const unsigned char *sha1, struct rev_info *rev)
}
if (offset < size)
fwrite(buf + offset, size - offset, 1, stdout);
fwrite(buf + offset, size - offset, 1, rev->diffopt.file);
free(buf);
return 0;
}
@ -511,7 +520,8 @@ static int show_tree_object(const unsigned char *sha1,
struct strbuf *base,
const char *pathname, unsigned mode, int stage, void *context)
{
printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
FILE *file = context;
fprintf(file, "%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
return 0;
}
@ -571,7 +581,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
if (rev.shown_one)
putchar('\n');
printf("%stag %s%s\n",
fprintf(rev.diffopt.file, "%stag %s%s\n",
diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
t->tag,
diff_get_color_opt(&rev.diffopt, DIFF_RESET));
@ -590,12 +600,12 @@ int cmd_show(int argc, const char **argv, const char *prefix)
case OBJ_TREE:
if (rev.shown_one)
putchar('\n');
printf("%stree %s%s\n\n",
fprintf(rev.diffopt.file, "%stree %s%s\n\n",
diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
name,
diff_get_color_opt(&rev.diffopt, DIFF_RESET));
read_tree_recursive((struct tree *)o, "", 0, 0, &match_all,
show_tree_object, NULL);
show_tree_object, rev.diffopt.file);
rev.shown_one = 1;
break;
case OBJ_COMMIT:
@ -801,11 +811,10 @@ static int git_format_config(const char *var, const char *value, void *cb)
return git_log_config(var, value, cb);
}
static FILE *realstdout = NULL;
static const char *output_directory = NULL;
static int outdir_offset;
static int reopen_stdout(struct commit *commit, const char *subject,
static int open_next_file(struct commit *commit, const char *subject,
struct rev_info *rev, int quiet)
{
struct strbuf filename = STRBUF_INIT;
@ -827,9 +836,9 @@ static int reopen_stdout(struct commit *commit, const char *subject,
fmt_output_subject(&filename, subject, rev);
if (!quiet)
fprintf(realstdout, "%s\n", filename.buf + outdir_offset);
printf("%s\n", filename.buf + outdir_offset);
if (freopen(filename.buf, "w", stdout) == NULL)
if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL)
return error(_("Cannot open patch file %s"), filename.buf);
strbuf_release(&filename);
@ -888,15 +897,15 @@ static void gen_message_id(struct rev_info *info, char *base)
info->message_id = strbuf_detach(&buf, NULL);
}
static void print_signature(void)
static void print_signature(FILE *file)
{
if (!signature || !*signature)
return;
printf("-- \n%s", signature);
fprintf(file, "-- \n%s", signature);
if (signature[strlen(signature)-1] != '\n')
putchar('\n');
putchar('\n');
putc('\n', file);
putc('\n', file);
}
static void add_branch_description(struct strbuf *buf, const char *branch_name)
@ -965,7 +974,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
committer = git_committer_info(0);
if (!use_stdout &&
reopen_stdout(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
return;
log_write_email_headers(rev, head, &pp.subject, &pp.after_subject,
@ -988,7 +997,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);
pp_remainder(&pp, &msg, &sb, 0);
add_branch_description(&sb, branch_name);
printf("%s\n", sb.buf);
fprintf(rev->diffopt.file, "%s\n", sb.buf);
strbuf_release(&sb);
@ -997,6 +1006,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
log.wrap = 72;
log.in1 = 2;
log.in2 = 4;
log.file = rev->diffopt.file;
for (i = 0; i < nr; i++)
shortlog_add_commit(&log, list[i]);
@ -1019,8 +1029,8 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
diffcore_std(&opts);
diff_flush(&opts);
printf("\n");
print_signature();
fprintf(rev->diffopt.file, "\n");
print_signature(rev->diffopt.file);
}
static const char *clean_message_id(const char *msg_id)
@ -1330,7 +1340,7 @@ static void prepare_bases(struct base_tree_info *bases,
}
}
static void print_bases(struct base_tree_info *bases)
static void print_bases(struct base_tree_info *bases, FILE *file)
{
int i;
@ -1339,11 +1349,11 @@ static void print_bases(struct base_tree_info *bases)
return;
/* Show the base commit */
printf("base-commit: %s\n", oid_to_hex(&bases->base_commit));
fprintf(file, "base-commit: %s\n", oid_to_hex(&bases->base_commit));
/* Show the prerequisite patches */
for (i = bases->nr_patch_id - 1; i >= 0; i--)
printf("prerequisite-patch-id: %s\n", oid_to_hex(&bases->patch_id[i]));
fprintf(file, "prerequisite-patch-id: %s\n", oid_to_hex(&bases->patch_id[i]));
free(bases->patch_id);
bases->nr_patch_id = 0;
@ -1575,6 +1585,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
setup_pager();
if (output_directory) {
if (rev.diffopt.use_color != GIT_COLOR_ALWAYS)
rev.diffopt.use_color = GIT_COLOR_NEVER;
if (use_stdout)
die(_("standard output, or directory, which one?"));
if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
@ -1632,9 +1644,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
get_patch_ids(&rev, &ids);
}
if (!use_stdout)
realstdout = xfdopen(xdup(1), "w");
if (prepare_revision_walk(&rev))
die(_("revision walk setup failed"));
rev.boundary = 1;
@ -1699,7 +1708,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
gen_message_id(&rev, "cover");
make_cover_letter(&rev, use_stdout,
origin, nr, list, branch_name, quiet);
print_bases(&bases);
print_bases(&bases, rev.diffopt.file);
total++;
start_number--;
}
@ -1745,7 +1754,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
}
if (!use_stdout &&
reopen_stdout(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
die(_("Failed to create output files"));
shown = log_tree_commit(&rev, commit);
free_commit_buffer(commit);
@ -1760,15 +1769,15 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
rev.shown_one = 0;
if (shown) {
if (rev.mime_boundary)
printf("\n--%s%s--\n\n\n",
fprintf(rev.diffopt.file, "\n--%s%s--\n\n\n",
mime_boundary_leader,
rev.mime_boundary);
else
print_signature();
print_bases(&bases);
print_signature(rev.diffopt.file);
print_bases(&bases, rev.diffopt.file);
}
if (!use_stdout)
fclose(stdout);
fclose(rev.diffopt.file);
}
free(list);
free(branch_name);
@ -1800,15 +1809,15 @@ static const char * const cherry_usage[] = {
};
static void print_commit(char sign, struct commit *commit, int verbose,
int abbrev)
int abbrev, FILE *file)
{
if (!verbose) {
printf("%c %s\n", sign,
fprintf(file, "%c %s\n", sign,
find_unique_abbrev(commit->object.oid.hash, abbrev));
} else {
struct strbuf buf = STRBUF_INIT;
pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
printf("%c %s %s\n", sign,
fprintf(file, "%c %s %s\n", sign,
find_unique_abbrev(commit->object.oid.hash, abbrev),
buf.buf);
strbuf_release(&buf);
@ -1889,7 +1898,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
commit = list->item;
if (has_commit_patch_id(commit, &ids))
sign = '-';
print_commit(sign, commit, verbose, abbrev);
print_commit(sign, commit, verbose, abbrev, revs.diffopt.file);
list = list->next;
}

Просмотреть файл

@ -276,6 +276,7 @@ parse_done:
log.user_format = rev.commit_format == CMIT_FMT_USERFORMAT;
log.abbrev = rev.abbrev;
log.file = rev.diffopt.file;
/* assume HEAD if from a tty */
if (!nongit && !rev.pending.nr && isatty(0))
@ -289,6 +290,8 @@ parse_done:
get_from_rev(&rev, &log);
shortlog_output(&log);
if (log.file != stdout)
fclose(log.file);
return 0;
}
@ -310,22 +313,24 @@ void shortlog_output(struct shortlog *log)
for (i = 0; i < log->list.nr; i++) {
const struct string_list_item *item = &log->list.items[i];
if (log->summary) {
printf("%6d\t%s\n", (int)UTIL_TO_INT(item), item->string);
fprintf(log->file, "%6d\t%s\n",
(int)UTIL_TO_INT(item), item->string);
} else {
struct string_list *onelines = item->util;
printf("%s (%d):\n", item->string, onelines->nr);
fprintf(log->file, "%s (%d):\n",
item->string, onelines->nr);
for (j = onelines->nr - 1; j >= 0; j--) {
const char *msg = onelines->items[j].string;
if (log->wrap_lines) {
strbuf_reset(&sb);
add_wrapped_shortlog_msg(&sb, msg, log);
fwrite(sb.buf, sb.len, 1, stdout);
fwrite(sb.buf, sb.len, 1, log->file);
}
else
printf(" %s\n", msg);
fprintf(log->file, " %s\n", msg);
}
putchar('\n');
putc('\n', log->file);
onelines->strdup_strings = 1;
string_list_clear(onelines, 0);
free(onelines);

2
diff.c
Просмотреть файл

@ -3977,6 +3977,8 @@ int diff_opt_parse(struct diff_options *options,
if (!options->file)
die_errno("Could not open '%s'", path);
options->close_file = 1;
if (options->use_color != GIT_COLOR_ALWAYS)
options->use_color = GIT_COLOR_NEVER;
return argcount;
} else
return 0;

30
graph.c
Просмотреть файл

@ -17,8 +17,8 @@
static void graph_padding_line(struct git_graph *graph, struct strbuf *sb);
/*
* Print a strbuf to stdout. If the graph is non-NULL, all lines but the
* first will be prefixed with the graph output.
* Print a strbuf. If the graph is non-NULL, all lines but the first will be
* prefixed with the graph output.
*
* If the strbuf ends with a newline, the output will end after this
* newline. A new graph line will not be printed after the final newline.
@ -1200,9 +1200,10 @@ void graph_show_commit(struct git_graph *graph)
while (!shown_commit_line && !graph_is_commit_finished(graph)) {
shown_commit_line = graph_next_line(graph, &msgbuf);
fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout);
fwrite(msgbuf.buf, sizeof(char), msgbuf.len,
graph->revs->diffopt.file);
if (!shown_commit_line)
putchar('\n');
putc('\n', graph->revs->diffopt.file);
strbuf_setlen(&msgbuf, 0);
}
@ -1217,7 +1218,7 @@ void graph_show_oneline(struct git_graph *graph)
return;
graph_next_line(graph, &msgbuf);
fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout);
fwrite(msgbuf.buf, sizeof(char), msgbuf.len, graph->revs->diffopt.file);
strbuf_release(&msgbuf);
}
@ -1229,7 +1230,7 @@ void graph_show_padding(struct git_graph *graph)
return;
graph_padding_line(graph, &msgbuf);
fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout);
fwrite(msgbuf.buf, sizeof(char), msgbuf.len, graph->revs->diffopt.file);
strbuf_release(&msgbuf);
}
@ -1246,12 +1247,13 @@ int graph_show_remainder(struct git_graph *graph)
for (;;) {
graph_next_line(graph, &msgbuf);
fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout);
fwrite(msgbuf.buf, sizeof(char), msgbuf.len,
graph->revs->diffopt.file);
strbuf_setlen(&msgbuf, 0);
shown = 1;
if (!graph_is_commit_finished(graph))
putchar('\n');
putc('\n', graph->revs->diffopt.file);
else
break;
}
@ -1266,7 +1268,8 @@ static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb)
char *p;
if (!graph) {
fwrite(sb->buf, sizeof(char), sb->len, stdout);
fwrite(sb->buf, sizeof(char), sb->len,
graph->revs->diffopt.file);
return;
}
@ -1284,7 +1287,7 @@ static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb)
} else {
len = (sb->buf + sb->len) - p;
}
fwrite(p, sizeof(char), len, stdout);
fwrite(p, sizeof(char), len, graph->revs->diffopt.file);
if (next_p && *next_p != '\0')
graph_show_oneline(graph);
p = next_p;
@ -1304,7 +1307,8 @@ void graph_show_commit_msg(struct git_graph *graph,
* CMIT_FMT_USERFORMAT are already missing a terminating
* newline. All of the other formats should have it.
*/
fwrite(sb->buf, sizeof(char), sb->len, stdout);
fwrite(sb->buf, sizeof(char), sb->len,
graph->revs->diffopt.file);
return;
}
@ -1325,7 +1329,7 @@ void graph_show_commit_msg(struct git_graph *graph,
* new line.
*/
if (!newline_terminated)
putchar('\n');
putc('\n', graph->revs->diffopt.file);
graph_show_remainder(graph);
@ -1333,6 +1337,6 @@ void graph_show_commit_msg(struct git_graph *graph,
* If sb ends with a newline, our output should too.
*/
if (newline_terminated)
putchar('\n');
putc('\n', graph->revs->diffopt.file);
}
}

Просмотреть файл

@ -840,7 +840,7 @@ static char *get_nth_line(long line, unsigned long *ends, void *data)
static void print_line(const char *prefix, char first,
long line, unsigned long *ends, void *data,
const char *color, const char *reset)
const char *color, const char *reset, FILE *file)
{
char *begin = get_nth_line(line, ends, data);
char *end = get_nth_line(line+1, ends, data);
@ -851,14 +851,14 @@ static void print_line(const char *prefix, char first,
had_nl = 1;
}
fputs(prefix, stdout);
fputs(color, stdout);
putchar(first);
fwrite(begin, 1, end-begin, stdout);
fputs(reset, stdout);
putchar('\n');
fputs(prefix, file);
fputs(color, file);
putc(first, file);
fwrite(begin, 1, end-begin, file);
fputs(reset, file);
putc('\n', file);
if (!had_nl)
fputs("\\ No newline at end of file\n", stdout);
fputs("\\ No newline at end of file\n", file);
}
static char *output_prefix(struct diff_options *opt)
@ -897,12 +897,12 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang
fill_line_ends(pair->one, &p_lines, &p_ends);
fill_line_ends(pair->two, &t_lines, &t_ends);
printf("%s%sdiff --git a/%s b/%s%s\n", prefix, c_meta, pair->one->path, pair->two->path, c_reset);
printf("%s%s--- %s%s%s\n", prefix, c_meta,
fprintf(opt->file, "%s%sdiff --git a/%s b/%s%s\n", prefix, c_meta, pair->one->path, pair->two->path, c_reset);
fprintf(opt->file, "%s%s--- %s%s%s\n", prefix, c_meta,
pair->one->sha1_valid ? "a/" : "",
pair->one->sha1_valid ? pair->one->path : "/dev/null",
c_reset);
printf("%s%s+++ b/%s%s\n", prefix, c_meta, pair->two->path, c_reset);
fprintf(opt->file, "%s%s+++ b/%s%s\n", prefix, c_meta, pair->two->path, c_reset);
for (i = 0; i < range->ranges.nr; i++) {
long p_start, p_end;
long t_start = range->ranges.ranges[i].start;
@ -944,7 +944,7 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang
}
/* Now output a diff hunk for this range */
printf("%s%s@@ -%ld,%ld +%ld,%ld @@%s\n",
fprintf(opt->file, "%s%s@@ -%ld,%ld +%ld,%ld @@%s\n",
prefix, c_frag,
p_start+1, p_end-p_start, t_start+1, t_end-t_start,
c_reset);
@ -952,18 +952,18 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang
int k;
for (; t_cur < diff->target.ranges[j].start; t_cur++)
print_line(prefix, ' ', t_cur, t_ends, pair->two->data,
c_context, c_reset);
c_context, c_reset, opt->file);
for (k = diff->parent.ranges[j].start; k < diff->parent.ranges[j].end; k++)
print_line(prefix, '-', k, p_ends, pair->one->data,
c_old, c_reset);
c_old, c_reset, opt->file);
for (; t_cur < diff->target.ranges[j].end && t_cur < t_end; t_cur++)
print_line(prefix, '+', t_cur, t_ends, pair->two->data,
c_new, c_reset);
c_new, c_reset, opt->file);
j++;
}
for (; t_cur < t_end; t_cur++)
print_line(prefix, ' ', t_cur, t_ends, pair->two->data,
c_context, c_reset);
c_context, c_reset, opt->file);
}
free(p_ends);
@ -976,7 +976,7 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang
*/
static void dump_diff_hacky(struct rev_info *rev, struct line_log_data *range)
{
puts(output_prefix(&rev->diffopt));
fprintf(rev->diffopt.file, "%s\n", output_prefix(&rev->diffopt));
while (range) {
dump_diff_hacky_one(rev, range);
range = range->next;

Просмотреть файл

@ -159,12 +159,12 @@ void load_ref_decorations(int flags)
}
}
static void show_parents(struct commit *commit, int abbrev)
static void show_parents(struct commit *commit, int abbrev, FILE *file)
{
struct commit_list *p;
for (p = commit->parents; p ; p = p->next) {
struct commit *parent = p->item;
printf(" %s", find_unique_abbrev(parent->object.oid.hash, abbrev));
fprintf(file, " %s", find_unique_abbrev(parent->object.oid.hash, abbrev));
}
}
@ -172,7 +172,7 @@ static void show_children(struct rev_info *opt, struct commit *commit, int abbre
{
struct commit_list *p = lookup_decoration(&opt->children, &commit->object);
for ( ; p; p = p->next) {
printf(" %s", find_unique_abbrev(p->item->object.oid.hash, abbrev));
fprintf(opt->diffopt.file, " %s", find_unique_abbrev(p->item->object.oid.hash, abbrev));
}
}
@ -286,11 +286,11 @@ void show_decorations(struct rev_info *opt, struct commit *commit)
struct strbuf sb = STRBUF_INIT;
if (opt->show_source && commit->util)
printf("\t%s", (char *) commit->util);
fprintf(opt->diffopt.file, "\t%s", (char *) commit->util);
if (!opt->show_decorations)
return;
format_decorations(&sb, commit, opt->diffopt.use_color);
fputs(sb.buf, stdout);
fputs(sb.buf, opt->diffopt.file);
strbuf_release(&sb);
}
@ -364,18 +364,18 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
subject = "Subject: ";
}
printf("From %s Mon Sep 17 00:00:00 2001\n", name);
fprintf(opt->diffopt.file, "From %s Mon Sep 17 00:00:00 2001\n", name);
graph_show_oneline(opt->graph);
if (opt->message_id) {
printf("Message-Id: <%s>\n", opt->message_id);
fprintf(opt->diffopt.file, "Message-Id: <%s>\n", opt->message_id);
graph_show_oneline(opt->graph);
}
if (opt->ref_message_ids && opt->ref_message_ids->nr > 0) {
int i, n;
n = opt->ref_message_ids->nr;
printf("In-Reply-To: <%s>\n", opt->ref_message_ids->items[n-1].string);
fprintf(opt->diffopt.file, "In-Reply-To: <%s>\n", opt->ref_message_ids->items[n-1].string);
for (i = 0; i < n; i++)
printf("%s<%s>\n", (i > 0 ? "\t" : "References: "),
fprintf(opt->diffopt.file, "%s<%s>\n", (i > 0 ? "\t" : "References: "),
opt->ref_message_ids->items[i].string);
graph_show_oneline(opt->graph);
}
@ -432,7 +432,7 @@ static void show_sig_lines(struct rev_info *opt, int status, const char *bol)
reset = diff_get_color_opt(&opt->diffopt, DIFF_RESET);
while (*bol) {
eol = strchrnul(bol, '\n');
printf("%s%.*s%s%s", color, (int)(eol - bol), bol, reset,
fprintf(opt->diffopt.file, "%s%.*s%s%s", color, (int)(eol - bol), bol, reset,
*eol ? "\n" : "");
graph_show_oneline(opt->graph);
bol = (*eol) ? (eol + 1) : eol;
@ -553,17 +553,17 @@ void show_log(struct rev_info *opt)
if (!opt->graph)
put_revision_mark(opt, commit);
fputs(find_unique_abbrev(commit->object.oid.hash, abbrev_commit), stdout);
fputs(find_unique_abbrev(commit->object.oid.hash, abbrev_commit), opt->diffopt.file);
if (opt->print_parents)
show_parents(commit, abbrev_commit);
show_parents(commit, abbrev_commit, opt->diffopt.file);
if (opt->children.name)
show_children(opt, commit, abbrev_commit);
show_decorations(opt, commit);
if (opt->graph && !graph_is_commit_finished(opt->graph)) {
putchar('\n');
putc('\n', opt->diffopt.file);
graph_show_remainder(opt->graph);
}
putchar(opt->diffopt.line_termination);
putc(opt->diffopt.line_termination, opt->diffopt.file);
return;
}
@ -589,7 +589,7 @@ void show_log(struct rev_info *opt)
if (opt->diffopt.line_termination == '\n' &&
!opt->missing_newline)
graph_show_padding(opt->graph);
putchar(opt->diffopt.line_termination);
putc(opt->diffopt.line_termination, opt->diffopt.file);
}
opt->shown_one = 1;
@ -607,28 +607,28 @@ void show_log(struct rev_info *opt)
log_write_email_headers(opt, commit, &ctx.subject, &extra_headers,
&ctx.need_8bit_cte);
} else if (opt->commit_format != CMIT_FMT_USERFORMAT) {
fputs(diff_get_color_opt(&opt->diffopt, DIFF_COMMIT), stdout);
fputs(diff_get_color_opt(&opt->diffopt, DIFF_COMMIT), opt->diffopt.file);
if (opt->commit_format != CMIT_FMT_ONELINE)
fputs("commit ", stdout);
fputs("commit ", opt->diffopt.file);
if (!opt->graph)
put_revision_mark(opt, commit);
fputs(find_unique_abbrev(commit->object.oid.hash, abbrev_commit),
stdout);
opt->diffopt.file);
if (opt->print_parents)
show_parents(commit, abbrev_commit);
show_parents(commit, abbrev_commit, opt->diffopt.file);
if (opt->children.name)
show_children(opt, commit, abbrev_commit);
if (parent)
printf(" (from %s)",
fprintf(opt->diffopt.file, " (from %s)",
find_unique_abbrev(parent->object.oid.hash,
abbrev_commit));
fputs(diff_get_color_opt(&opt->diffopt, DIFF_RESET), stdout);
fputs(diff_get_color_opt(&opt->diffopt, DIFF_RESET), opt->diffopt.file);
show_decorations(opt, commit);
if (opt->commit_format == CMIT_FMT_ONELINE) {
putchar(' ');
putc(' ', opt->diffopt.file);
} else {
putchar('\n');
putc('\n', opt->diffopt.file);
graph_show_oneline(opt->graph);
}
if (opt->reflog_info) {
@ -704,7 +704,7 @@ void show_log(struct rev_info *opt)
}
if (opt->show_log_size) {
printf("log size %i\n", (int)msgbuf.len);
fprintf(opt->diffopt.file, "log size %i\n", (int)msgbuf.len);
graph_show_oneline(opt->graph);
}
@ -720,11 +720,11 @@ void show_log(struct rev_info *opt)
if (opt->graph)
graph_show_commit_msg(opt->graph, &msgbuf);
else
fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout);
fwrite(msgbuf.buf, sizeof(char), msgbuf.len, opt->diffopt.file);
if (opt->use_terminator && !commit_format_is_empty(opt->commit_format)) {
if (!opt->missing_newline)
graph_show_padding(opt->graph);
putchar(opt->diffopt.line_termination);
putc(opt->diffopt.line_termination, opt->diffopt.file);
}
strbuf_release(&msgbuf);
@ -761,7 +761,7 @@ int log_tree_diff_flush(struct rev_info *opt)
struct strbuf *msg = NULL;
msg = opt->diffopt.output_prefix(&opt->diffopt,
opt->diffopt.output_prefix_data);
fwrite(msg->buf, msg->len, 1, stdout);
fwrite(msg->buf, msg->len, 1, opt->diffopt.file);
}
/*
@ -776,8 +776,8 @@ int log_tree_diff_flush(struct rev_info *opt)
*/
if (!opt->shown_dashes &&
(pch & opt->diffopt.output_format) == pch)
printf("---");
putchar('\n');
fprintf(opt->diffopt.file, "---");
putc('\n', opt->diffopt.file);
}
}
diff_flush(&opt->diffopt);
@ -864,17 +864,18 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
int log_tree_commit(struct rev_info *opt, struct commit *commit)
{
struct log_info log;
int shown;
int shown, close_file = opt->diffopt.close_file;
log.commit = commit;
log.parent = NULL;
opt->loginfo = &log;
opt->diffopt.close_file = 0;
if (opt->line_level_traverse)
return line_log_print(opt, commit);
if (opt->track_linear && !opt->linear && !opt->reverse_output_stage)
printf("\n%s\n", opt->break_bar);
fprintf(opt->diffopt.file, "\n%s\n", opt->break_bar);
shown = log_tree_diff(opt, commit, &log);
if (!shown && opt->loginfo && opt->always_show_header) {
log.parent = NULL;
@ -882,8 +883,10 @@ int log_tree_commit(struct rev_info *opt, struct commit *commit)
shown = 1;
}
if (opt->track_linear && !opt->linear && opt->reverse_output_stage)
printf("\n%s\n", opt->break_bar);
fprintf(opt->diffopt.file, "\n%s\n", opt->break_bar);
opt->loginfo = NULL;
maybe_flush_or_die(stdout, "stdout");
maybe_flush_or_die(opt->diffopt.file, "stdout");
if (close_file)
fclose(opt->diffopt.file);
return shown;
}

Просмотреть файл

@ -17,6 +17,7 @@ struct shortlog {
char *common_repo_prefix;
int email;
struct string_list mailmap;
FILE *file;
};
void shortlog_init(struct shortlog *log);

Просмотреть файл

@ -184,4 +184,10 @@ test_expect_success 'shortlog with revision pseudo options' '
git shortlog --exclude=refs/heads/m* --all
'
test_expect_success 'shortlog with --output=<file>' '
git shortlog --output=shortlog -1 master >output &&
test ! -s output &&
test_line_count = 3 shortlog
'
test_done

Просмотреть файл

@ -99,4 +99,11 @@ test_expect_success '-L with --first-parent and a merge' '
git log --first-parent -L 1,1:b.c
'
test_expect_success '-L with --output' '
git checkout parallel-change &&
git log --output=log -L :main:b.c >output &&
test ! -s output &&
test_line_count = 70 log
'
test_done