зеркало из https://github.com/microsoft/git.git
log and rev-list: add --graph option
This new option causes a text-based representation of the history to be printed to the left of the normal output. Signed-off-by: Adam Simpkins <adam@adamsimpkins.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
c12172d2ea
Коммит
7fefda5cc7
|
@ -75,6 +75,16 @@ you would get an output line this:
|
|||
-xxxxxxx... 1st on a
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
--graph::
|
||||
|
||||
Draw a text-based graphical representation of the commit history
|
||||
on the left hand side of the output. This may cause extra lines
|
||||
to be printed in between commits, in order for the graph history
|
||||
to be drawn properly.
|
||||
+
|
||||
This implies the '--topo-order' option by default, but the
|
||||
'--date-order' option may also be specified.
|
||||
|
||||
Diff Formatting
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -74,14 +74,17 @@ state.
|
|||
Calling sequence
|
||||
----------------
|
||||
|
||||
* Create a `struct git_graph` by calling `graph_init()`.
|
||||
* Create a `struct git_graph` by calling `graph_init()`. When using the
|
||||
revision walking API, this is done automatically by `setup_revisions()` if
|
||||
the '--graph' option is supplied.
|
||||
|
||||
* Use the revision walking API to walk through a group of contiguous commits.
|
||||
The `get_revision()` function automatically calls `graph_update()` each time
|
||||
it is invoked.
|
||||
|
||||
* For each commit traversed, call `graph_update()` to move the graph to the
|
||||
next commit. Once `graph_update()` has been called, call `graph_next_line()`
|
||||
repeatedly, until `graph_is_commit_finished()` returns non-zero. Each call
|
||||
to `graph_next_line()` will output a single line of the graph. The resulting
|
||||
* For each commit, call `graph_next_line()` repeatedly, until
|
||||
`graph_is_commit_finished()` returns non-zero. Each call go
|
||||
`graph_next_line()` will output a single line of the graph. The resulting
|
||||
lines will not contain any newlines. `graph_next_line()` returns 1 if the
|
||||
resulting line contains the current commit, or 0 if this is merely a line
|
||||
needed to adjust the graph before or after the current commit. This return
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "list-objects.h"
|
||||
#include "builtin.h"
|
||||
#include "log-tree.h"
|
||||
#include "graph.h"
|
||||
|
||||
/* bits #0-15 in revision.h */
|
||||
|
||||
|
@ -58,6 +59,8 @@ static const char *header_prefix;
|
|||
static void finish_commit(struct commit *commit);
|
||||
static void show_commit(struct commit *commit)
|
||||
{
|
||||
graph_show_commit(revs.graph);
|
||||
|
||||
if (show_timestamp)
|
||||
printf("%lu ", commit->date);
|
||||
if (header_prefix)
|
||||
|
@ -96,9 +99,48 @@ static void show_commit(struct commit *commit)
|
|||
pretty_print_commit(revs.commit_format, commit,
|
||||
&buf, revs.abbrev, NULL, NULL,
|
||||
revs.date_mode, 0);
|
||||
if (buf.len)
|
||||
printf("%s%c", buf.buf, hdr_termination);
|
||||
if (revs.graph) {
|
||||
if (buf.len) {
|
||||
if (revs.commit_format != CMIT_FMT_ONELINE)
|
||||
graph_show_oneline(revs.graph);
|
||||
|
||||
graph_show_commit_msg(revs.graph, &buf);
|
||||
|
||||
/*
|
||||
* Add a newline after the commit message.
|
||||
*
|
||||
* Usually, this newline produces a blank
|
||||
* padding line between entries, in which case
|
||||
* we need to add graph padding on this line.
|
||||
*
|
||||
* However, the commit message may not end in a
|
||||
* newline. In this case the newline simply
|
||||
* ends the last line of the commit message,
|
||||
* and we don't need any graph output. (This
|
||||
* always happens with CMIT_FMT_ONELINE, and it
|
||||
* happens with CMIT_FMT_USERFORMAT when the
|
||||
* format doesn't explicitly end in a newline.)
|
||||
*/
|
||||
if (buf.len && buf.buf[buf.len - 1] == '\n')
|
||||
graph_show_padding(revs.graph);
|
||||
putchar('\n');
|
||||
} else {
|
||||
/*
|
||||
* If the message buffer is empty, just show
|
||||
* the rest of the graph output for this
|
||||
* commit.
|
||||
*/
|
||||
if (graph_show_remainder(revs.graph))
|
||||
putchar('\n');
|
||||
}
|
||||
} else {
|
||||
if (buf.len)
|
||||
printf("%s%c", buf.buf, hdr_termination);
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
} else {
|
||||
if (graph_show_remainder(revs.graph))
|
||||
putchar('\n');
|
||||
}
|
||||
maybe_flush_or_die(stdout, "stdout");
|
||||
finish_commit(commit);
|
||||
|
|
76
log-tree.c
76
log-tree.c
|
@ -1,6 +1,7 @@
|
|||
#include "cache.h"
|
||||
#include "diff.h"
|
||||
#include "commit.h"
|
||||
#include "graph.h"
|
||||
#include "log-tree.h"
|
||||
#include "reflog-walk.h"
|
||||
|
||||
|
@ -165,11 +166,16 @@ void log_write_email_headers(struct rev_info *opt, const char *name,
|
|||
}
|
||||
|
||||
printf("From %s Mon Sep 17 00:00:00 2001\n", name);
|
||||
if (opt->message_id)
|
||||
graph_show_oneline(opt->graph);
|
||||
if (opt->message_id) {
|
||||
printf("Message-Id: <%s>\n", opt->message_id);
|
||||
if (opt->ref_message_id)
|
||||
graph_show_oneline(opt->graph);
|
||||
}
|
||||
if (opt->ref_message_id) {
|
||||
printf("In-Reply-To: <%s>\nReferences: <%s>\n",
|
||||
opt->ref_message_id, opt->ref_message_id);
|
||||
graph_show_oneline(opt->graph);
|
||||
}
|
||||
if (opt->mime_boundary) {
|
||||
static char subject_buffer[1024];
|
||||
static char buffer[1024];
|
||||
|
@ -220,6 +226,8 @@ void show_log(struct rev_info *opt)
|
|||
|
||||
opt->loginfo = NULL;
|
||||
if (!opt->verbose_header) {
|
||||
graph_show_commit(opt->graph);
|
||||
|
||||
if (commit->object.flags & BOUNDARY)
|
||||
putchar('-');
|
||||
else if (commit->object.flags & UNINTERESTING)
|
||||
|
@ -234,6 +242,10 @@ void show_log(struct rev_info *opt)
|
|||
if (opt->print_parents)
|
||||
show_parents(commit, abbrev_commit);
|
||||
show_decorations(commit);
|
||||
if (opt->graph && !graph_is_commit_finished(opt->graph)) {
|
||||
putchar('\n');
|
||||
graph_show_remainder(opt->graph);
|
||||
}
|
||||
putchar(opt->diffopt.line_termination);
|
||||
return;
|
||||
}
|
||||
|
@ -243,10 +255,32 @@ void show_log(struct rev_info *opt)
|
|||
* Otherwise, add a diffopt.line_termination character before all
|
||||
* entries but the first. (IOW, as a separator between entries)
|
||||
*/
|
||||
if (opt->shown_one && !opt->use_terminator)
|
||||
if (opt->shown_one && !opt->use_terminator) {
|
||||
/*
|
||||
* If entries are separated by a newline, the output
|
||||
* should look human-readable. If the last entry ended
|
||||
* with a newline, print the graph output before this
|
||||
* newline. Otherwise it will end up as a completely blank
|
||||
* line and will look like a gap in the graph.
|
||||
*
|
||||
* If the entry separator is not a newline, the output is
|
||||
* primarily intended for programmatic consumption, and we
|
||||
* never want the extra graph output before the entry
|
||||
* separator.
|
||||
*/
|
||||
if (opt->diffopt.line_termination == '\n' &&
|
||||
!opt->missing_newline)
|
||||
graph_show_padding(opt->graph);
|
||||
putchar(opt->diffopt.line_termination);
|
||||
}
|
||||
opt->shown_one = 1;
|
||||
|
||||
/*
|
||||
* If the history graph was requested,
|
||||
* print the graph, up to this commit's line
|
||||
*/
|
||||
graph_show_commit(opt->graph);
|
||||
|
||||
/*
|
||||
* Print header line of header..
|
||||
*/
|
||||
|
@ -279,8 +313,19 @@ void show_log(struct rev_info *opt)
|
|||
abbrev_commit));
|
||||
show_decorations(commit);
|
||||
printf("%s", diff_get_color_opt(&opt->diffopt, DIFF_RESET));
|
||||
putchar(opt->commit_format == CMIT_FMT_ONELINE ? ' ' : '\n');
|
||||
if (opt->commit_format == CMIT_FMT_ONELINE) {
|
||||
putchar(' ');
|
||||
} else {
|
||||
putchar('\n');
|
||||
graph_show_oneline(opt->graph);
|
||||
}
|
||||
if (opt->reflog_info) {
|
||||
/*
|
||||
* setup_revisions() ensures that opt->reflog_info
|
||||
* and opt->graph cannot both be set,
|
||||
* so we don't need to worry about printing the
|
||||
* graph info here.
|
||||
*/
|
||||
show_reflog_message(opt->reflog_info,
|
||||
opt->commit_format == CMIT_FMT_ONELINE,
|
||||
opt->date_mode);
|
||||
|
@ -304,13 +349,30 @@ void show_log(struct rev_info *opt)
|
|||
|
||||
if (opt->add_signoff)
|
||||
append_signoff(&msgbuf, opt->add_signoff);
|
||||
if (opt->show_log_size)
|
||||
if (opt->show_log_size) {
|
||||
printf("log size %i\n", (int)msgbuf.len);
|
||||
graph_show_oneline(opt->graph);
|
||||
}
|
||||
|
||||
if (msgbuf.len)
|
||||
/*
|
||||
* Set opt->missing_newline if msgbuf doesn't
|
||||
* end in a newline (including if it is empty)
|
||||
*/
|
||||
if (!msgbuf.len || msgbuf.buf[msgbuf.len - 1] != '\n')
|
||||
opt->missing_newline = 1;
|
||||
else
|
||||
opt->missing_newline = 0;
|
||||
|
||||
if (opt->graph)
|
||||
graph_show_commit_msg(opt->graph, &msgbuf);
|
||||
else
|
||||
fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout);
|
||||
if (opt->use_terminator)
|
||||
if (opt->use_terminator) {
|
||||
if (!opt->missing_newline)
|
||||
graph_show_padding(opt->graph);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
strbuf_release(&msgbuf);
|
||||
}
|
||||
|
||||
|
|
26
revision.c
26
revision.c
|
@ -6,6 +6,7 @@
|
|||
#include "diff.h"
|
||||
#include "refs.h"
|
||||
#include "revision.h"
|
||||
#include "graph.h"
|
||||
#include "grep.h"
|
||||
#include "reflog-walk.h"
|
||||
#include "patch-ids.h"
|
||||
|
@ -1203,6 +1204,12 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
|
|||
get_commit_format(arg+8, revs);
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--graph")) {
|
||||
revs->topo_order = 1;
|
||||
revs->rewrite_parents = 1;
|
||||
revs->graph = graph_init();
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--root")) {
|
||||
revs->show_root_diff = 1;
|
||||
continue;
|
||||
|
@ -1397,6 +1404,15 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
|
|||
if (revs->reverse && revs->reflog_info)
|
||||
die("cannot combine --reverse with --walk-reflogs");
|
||||
|
||||
/*
|
||||
* Limitations on the graph functionality
|
||||
*/
|
||||
if (revs->reverse && revs->graph)
|
||||
die("cannot combine --reverse with --graph");
|
||||
|
||||
if (revs->reflog_info && revs->graph)
|
||||
die("cannot combine --walk-reflogs with --graph");
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
|
@ -1598,7 +1614,7 @@ static void gc_boundary(struct object_array *array)
|
|||
}
|
||||
}
|
||||
|
||||
struct commit *get_revision(struct rev_info *revs)
|
||||
static struct commit *get_revision_internal(struct rev_info *revs)
|
||||
{
|
||||
struct commit *c = NULL;
|
||||
struct commit_list *l;
|
||||
|
@ -1705,3 +1721,11 @@ struct commit *get_revision(struct rev_info *revs)
|
|||
|
||||
return c;
|
||||
}
|
||||
|
||||
struct commit *get_revision(struct rev_info *revs)
|
||||
{
|
||||
struct commit *c = get_revision_internal(revs);
|
||||
if (c && revs->graph)
|
||||
graph_update(revs->graph, c);
|
||||
return c;
|
||||
}
|
||||
|
|
|
@ -66,7 +66,8 @@ struct rev_info {
|
|||
/* Format info */
|
||||
unsigned int shown_one:1,
|
||||
abbrev_commit:1,
|
||||
use_terminator:1;
|
||||
use_terminator:1,
|
||||
missing_newline:1;
|
||||
enum date_mode date_mode;
|
||||
|
||||
const char **ignore_packed; /* pretend objects in these are unpacked */
|
||||
|
@ -89,6 +90,9 @@ struct rev_info {
|
|||
/* Filter by commit log message */
|
||||
struct grep_opt *grep_filter;
|
||||
|
||||
/* Display history graph */
|
||||
struct git_graph *graph;
|
||||
|
||||
/* special limits */
|
||||
int skip_count;
|
||||
int max_count;
|
||||
|
|
Загрузка…
Ссылка в новой задаче