Skip to content

Commit

Permalink
blame: add --line-porcelain output format
Browse files Browse the repository at this point in the history
This is just like --porcelain, except that we always output
the commit information for each line, not just the first
time it is referenced. This can make quick and dirty scripts
much easier to write; see the example added to the blame
documentation.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jeff King authored and Junio C Hamano committed May 9, 2011
1 parent e86226e commit ed747dd
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 2 deletions.
5 changes: 5 additions & 0 deletions Documentation/blame-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ of lines before or after the line given by <start>.
--porcelain::
Show in a format designed for machine consumption.

--line-porcelain::
Show the porcelain format, but output commit information for
each line, not just the first time a commit is referenced.
Implies --porcelain.

--incremental::
Show the result incrementally in a format designed for
machine consumption.
Expand Down
13 changes: 13 additions & 0 deletions Documentation/git-blame.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,19 @@ The contents of the actual line is output after the above
header, prefixed by a TAB. This is to allow adding more
header elements later.

The porcelain format generally suppresses commit information that has
already been seen. For example, two lines that are blamed to the same
commit will both be shown, but the details for that commit will be shown
only once. This is more efficient, but may require more state be kept by
the reader. The `--line-porcelain` option can be used to output full
commit information for each line, allowing simpler (but less efficient)
usage like:

# count the number of lines attributed to each author
git blame --line-porcelain file |
sed -n 's/^author //p' |
sort | uniq -c | sort -rn


SPECIFYING RANGES
-----------------
Expand Down
10 changes: 8 additions & 2 deletions builtin/blame.c
Original file line number Diff line number Diff line change
Expand Up @@ -1619,6 +1619,7 @@ static const char *format_time(unsigned long time, const char *tz_str,
#define OUTPUT_SHOW_SCORE 0100
#define OUTPUT_NO_AUTHOR 0200
#define OUTPUT_SHOW_EMAIL 0400
#define OUTPUT_LINE_PORCELAIN 01000

static void emit_porcelain_details(struct origin *suspect, int repeat)
{
Expand All @@ -1630,6 +1631,7 @@ static void emit_porcelain_details(struct origin *suspect, int repeat)
static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent,
int opt)
{
int repeat = opt & OUTPUT_LINE_PORCELAIN;
int cnt;
const char *cp;
struct origin *suspect = ent->suspect;
Expand All @@ -1642,15 +1644,18 @@ static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent,
ent->s_lno + 1,
ent->lno + 1,
ent->num_lines);
emit_porcelain_details(suspect, 0);
emit_porcelain_details(suspect, repeat);

cp = nth_line(sb, ent->lno);
for (cnt = 0; cnt < ent->num_lines; cnt++) {
char ch;
if (cnt)
if (cnt) {
printf("%s %d %d\n", hex,
ent->s_lno + 1 + cnt,
ent->lno + 1 + cnt);
if (repeat)
emit_porcelain_details(suspect, 1);
}
putchar('\t');
do {
ch = *cp++;
Expand Down Expand Up @@ -2307,6 +2312,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
OPT_BIT('f', "show-name", &output_option, "Show original filename (Default: auto)", OUTPUT_SHOW_NAME),
OPT_BIT('n', "show-number", &output_option, "Show original linenumber (Default: off)", OUTPUT_SHOW_NUMBER),
OPT_BIT('p', "porcelain", &output_option, "Show in a format designed for machine consumption", OUTPUT_PORCELAIN),
OPT_BIT(0, "line-porcelain", &output_option, "Show porcelain format with per-line commit information", OUTPUT_PORCELAIN|OUTPUT_LINE_PORCELAIN),
OPT_BIT('c', NULL, &output_option, "Use the same output mode as git-annotate (Default: off)", OUTPUT_ANNOTATE_COMPAT),
OPT_BIT('t', NULL, &output_option, "Show raw timestamp (Default: off)", OUTPUT_RAW_TIMESTAMP),
OPT_BIT('l', NULL, &output_option, "Show long commit SHA1 (Default: off)", OUTPUT_LONG_OBJECT_NAME),
Expand Down
19 changes: 19 additions & 0 deletions t/t8008-blame-formats.sh
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,23 @@ test_expect_success 'blame --porcelain output' '
test_cmp expect actual
'

cat >expect <<EOF
$ID1 1 1 1
$COMMIT1
a
$ID2 2 2 3
$COMMIT2
b
$ID2 3 3
$COMMIT2
c
$ID2 4 4
$COMMIT2
d
EOF
test_expect_success 'blame --line-porcelain output' '
git blame --line-porcelain file >actual &&
test_cmp expect actual
'

test_done

0 comments on commit ed747dd

Please sign in to comment.