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>
Jeff King committed
May 9, 2011 at 09:34 UTC
ed747dd5216ba1fe6fa59da9585dcd6cced202bb
4 files changed
+45
-2
Documentation/blame-options.txt
+5
@@ -52,6 +52,11 @@ of lines before or after the line given by <start>.
52
--porcelain::
53
Show in a format designed for machine consumption.
54
55
+--line-porcelain::
56
+ Show the porcelain format, but output commit information for
57
+ each line, not just the first time a commit is referenced.
58
+ Implies --porcelain.
59
+
60
--incremental::
61
Show the result incrementally in a format designed for
62
machine consumption.
Documentation/git-blame.txt
+13
@@ -105,6 +105,19 @@ The contents of the actual line is output after the above
105
header, prefixed by a TAB. This is to allow adding more
106
header elements later.
107
108
+The porcelain format generally suppresses commit information that has
109
+already been seen. For example, two lines that are blamed to the same
110
+commit will both be shown, but the details for that commit will be shown
111
+only once. This is more efficient, but may require more state be kept by
112
+the reader. The `--line-porcelain` option can be used to output full
113
+commit information for each line, allowing simpler (but less efficient)
114
+usage like:
115
+
116
+ # count the number of lines attributed to each author
117
+ git blame --line-porcelain file |
118
+ sed -n 's/^author //p' |
119
+ sort | uniq -c | sort -rn
120
+
121
122
SPECIFYING RANGES
123
-----------------
builtin/blame.c
+8
-2
@@ -1619,6 +1619,7 @@ static const char *format_time(unsigned long time, const char *tz_str,
1619
#define OUTPUT_SHOW_SCORE 0100
1620
#define OUTPUT_NO_AUTHOR 0200
1621
#define OUTPUT_SHOW_EMAIL 0400
1622
+#define OUTPUT_LINE_PORCELAIN 01000
1623
1624
static void emit_porcelain_details(struct origin *suspect, int repeat)
1625
{
@@ -1630,6 +1631,7 @@ static void emit_porcelain_details(struct origin *suspect, int repeat)
1631
static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent,
1632
int opt)
1633
{
1634
+ int repeat = opt & OUTPUT_LINE_PORCELAIN;
1635
int cnt;
1636
const char *cp;
1637
struct origin *suspect = ent->suspect;
@@ -1642,15 +1644,18 @@ static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent,
1644
ent->s_lno + 1,
1645
ent->lno + 1,
1646
ent->num_lines);
1645
- emit_porcelain_details(suspect, 0);
1647
+ emit_porcelain_details(suspect, repeat);
1648
1649
cp = nth_line(sb, ent->lno);
1650
for (cnt = 0; cnt < ent->num_lines; cnt++) {
1651
char ch;
1650
- if (cnt)
1652
+ if (cnt) {
1653
printf("%s %d %d\n", hex,
1654
ent->s_lno + 1 + cnt,
1655
ent->lno + 1 + cnt);
1656
+ if (repeat)
1657
+ emit_porcelain_details(suspect, 1);
1658
+ }
1659
putchar('\t');
1660
do {
1661
ch = *cp++;
@@ -2307,6 +2312,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
2312
OPT_BIT('f', "show-name", &output_option, "Show original filename (Default: auto)", OUTPUT_SHOW_NAME),
2313
OPT_BIT('n', "show-number", &output_option, "Show original linenumber (Default: off)", OUTPUT_SHOW_NUMBER),
2314
OPT_BIT('p', "porcelain", &output_option, "Show in a format designed for machine consumption", OUTPUT_PORCELAIN),
2315
+ OPT_BIT(0, "line-porcelain", &output_option, "Show porcelain format with per-line commit information", OUTPUT_PORCELAIN|OUTPUT_LINE_PORCELAIN),
2316
OPT_BIT('c', NULL, &output_option, "Use the same output mode as git-annotate (Default: off)", OUTPUT_ANNOTATE_COMPAT),
2317
OPT_BIT('t', NULL, &output_option, "Show raw timestamp (Default: off)", OUTPUT_RAW_TIMESTAMP),
2318
OPT_BIT('l', NULL, &output_option, "Show long commit SHA1 (Default: off)", OUTPUT_LONG_OBJECT_NAME),
t/t8008-blame-formats.sh
+19
@@ -68,4 +68,23 @@ test_expect_success 'blame --porcelain output' '
68
test_cmp expect actual
69
'
70
71
+cat >expect <<EOF
72
+$ID1 1 1 1
73
+$COMMIT1
74
+ a
75
+$ID2 2 2 3
76
+$COMMIT2
77
+ b
78
+$ID2 3 3
79
+$COMMIT2
80
+ c
81
+$ID2 4 4
82
+$COMMIT2
83
+ d
84
+EOF
85
+test_expect_success 'blame --line-porcelain output' '
86
+ git blame --line-porcelain file >actual &&
87
+ test_cmp expect actual
88
+'
89
+
90
test_done