Browse Source

blame: add --line-porcelain output format

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>
maint
Jeff King 14 years ago committed by Junio C Hamano
parent
commit
ed747dd521
  1. 5
      Documentation/blame-options.txt
  2. 13
      Documentation/git-blame.txt
  3. 10
      builtin/blame.c
  4. 19
      t/t8008-blame-formats.sh

5
Documentation/blame-options.txt

@ -52,6 +52,11 @@ of lines before or after the line given by <start>. @@ -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.

13
Documentation/git-blame.txt

@ -105,6 +105,19 @@ The contents of the actual line is output after the above @@ -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
-----------------

10
builtin/blame.c

@ -1619,6 +1619,7 @@ static const char *format_time(unsigned long time, const char *tz_str, @@ -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)
{
@ -1630,6 +1631,7 @@ static void emit_porcelain_details(struct origin *suspect, int repeat) @@ -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;
@ -1642,15 +1644,18 @@ static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent, @@ -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++;
@ -2307,6 +2312,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) @@ -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),

19
t/t8008-blame-formats.sh

@ -68,4 +68,23 @@ test_expect_success 'blame --porcelain output' ' @@ -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

Loading…
Cancel
Save