blame: add --aggregate option
PATCH 1/1 blame: add --aggregate option
--- builtin/blame.c | 78 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 27 deletions(-)
builtin/blame.c +51 -27
@@ -1884,6 +1884,7 @@ static const char *format_time(unsigned long time, const char *tz_str,#define OUTPUT_NO_AUTHOR 0200#define OUTPUT_SHOW_EMAIL 0400#define OUTPUT_LINE_PORCELAIN 01000 +#define OUTPUT_AGGREGATE 02000static void emit_porcelain_details (struct origin *suspect,int repeat) {
@@ -1931,43 +1932,36 @@ static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent,putchar ('\n' ); } -static void emit_other (struct scoreboard *sb,struct blame_entry *ent,int opt) +/** +* Print information about the revision. +* This information can be used in either aggregated output +* or prepending each line of the content of the file being blamed +*/ +static void print_revision_info (char * revision_hex,int revision_length,struct blame_entry * ent, +struct commit * commit,struct commit_info ci,int opt,int show_raw_time) { -int cnt; -const char *cp; -struct origin *suspect = ent->suspect; -struct commit_info ci; -char hex[GIT_SHA1_HEXSZ +1 ]; -int show_raw_time = !!(opt &OUTPUT_RAW_TIMESTAMP ); - -get_commit_info (suspect->commit, &ci,1 ); -sha1_to_hex_r (hex, suspect->commit->object.oid.hash); - - cp =nth_line (sb, ent->lno); -for (cnt =0 ; cnt < ent->num_lines; cnt++) { -char ch; -int length = (opt &OUTPUT_LONG_OBJECT_NAME ) ?GIT_SHA1_HEXSZ : abbrev; - -if (suspect->commit->object.flags &UNINTERESTING ) { +if (opt &OUTPUT_AGGREGATE ) +printf ("\t" ); +int length = revision_length; +if (commit->object.flags &UNINTERESTING ) {if (blank_boundary) -memset (hex,' ' , length); +memset (revision_hex,' ' , length);else if (!(opt &OUTPUT_ANNOTATE_COMPAT )) { length--;putchar ('^' ); } } -printf ("%.*s" , length, hex); +printf ("%.*s" , length, revision_hex);if (opt &OUTPUT_ANNOTATE_COMPAT ) {const char *name;if (opt &OUTPUT_SHOW_EMAIL ) name = ci.author_mail.buf;else name = ci.author.buf; -printf ("\t(%10s\t%10s\t%d)" , name, +printf ("\t(%10s\t%10s\t" , name,format_time (ci.author_time, ci.author_tz.buf, - show_raw_time), - ent->lno +1 + cnt); + show_raw_time)); }else {if (opt &OUTPUT_SHOW_SCORE ) printf(" %*d %02d",
@@ -1975,11 +1969,7 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt) ent->suspect->refcnt);if (opt &OUTPUT_SHOW_NAME )printf (" %-*.*s" , longest_file, longest_file, - suspect->path); -if (opt &OUTPUT_SHOW_NUMBER ) -printf (" %*d" , max_orig_digits, - ent->s_lno +1 + cnt); - + ent->suspect->path);if (!(opt &OUTPUT_NO_AUTHOR )) {const char *name;int pad;
@@ -1994,9 +1984,42 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt) ci.author_tz.buf, show_raw_time)); } + } +if (opt &OUTPUT_AGGREGATE ) +printf (")\n" ); +} + +static void emit_other (struct scoreboard *sb,struct blame_entry *ent,int opt) +{ +int cnt; +const char *cp; +struct origin *suspect = ent->suspect; +struct commit_info ci; +char hex[GIT_SHA1_HEXSZ +1 ]; +int show_raw_time = !!(opt &OUTPUT_RAW_TIMESTAMP ); +int revision_length = (opt &OUTPUT_LONG_OBJECT_NAME ) ?GIT_SHA1_HEXSZ : abbrev; + +get_commit_info (suspect->commit, &ci,1 ); +sha1_to_hex_r (hex, suspect->commit->object.oid.hash); + +if (opt &OUTPUT_AGGREGATE ) +print_revision_info (hex, revision_length, ent, suspect->commit, ci, opt, show_raw_time); + + cp =nth_line (sb, ent->lno); +for (cnt =0 ; cnt < ent->num_lines; cnt++) { +if (!(opt &OUTPUT_AGGREGATE )) +print_revision_info (hex, revision_length, ent, suspect->commit, ci, opt, show_raw_time); +if (opt &OUTPUT_ANNOTATE_COMPAT ) { +printf ("%*d) " , + max_digits, ent->lno +1 + cnt); + }else { +if (opt &OUTPUT_SHOW_NUMBER ) +printf (" %*d " , max_orig_digits, + ent->s_lno +1 + cnt);printf (" %*d) " , max_digits, ent->lno +1 + cnt); } +char ch; do { ch = *cp++; putchar(ch);
@@ -2609,6 +2632,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) { OPTION_CALLBACK, 'C', NULL, &opt, N_("score"), N_("Find line copies within and across files"), PARSE_OPT_OPTARG, blame_copy_callback }, { OPTION_CALLBACK, 'M', NULL, &opt, N_("score"), N_("Find line movements within and across files"), PARSE_OPT_OPTARG, blame_move_callback },OPT_STRING_LIST ('L' ,NULL , &range_list,N_ ("n,m" ),N_ ("Process only line range n,m, counting from 1" )), +OPT_BIT (0 ,"aggregate" , &output_option,N_ ("Aggregate output" ),OUTPUT_AGGREGATE ),OPT__ABBREV (&abbrev),OPT_END () };
Signature · 1 line
2.11.0.rc1
Developers of the world, rejoice! :-)
Junio, Pranit (and whoever is paying attention to the conversation that was being held about --tips), here's a draft of what I meant when I was talking about the option of "aggregating" blame output. I'm not considering _all_ cases yet, just would like for people to give it a quick test and tell me if they think it's worth "polishing" it for inclusion into mainline git.
The output would look like this:
$ ./git blame -L 1,19 -t --aggregate builtin/blame.c
Blaming lines: 0% (19/2974), done.
cee7f245dc builtin-pickaxe.c (Junio C Hamano 1161298804 -0700)
1) /*
31653c1abc builtin-blame.c (Eugene Letuchy 1235170271 -0800)
2) * Blame
cee7f245dc builtin-pickaxe.c (Junio C Hamano 1161298804 -0700)
3) *
7e6ac6e439 builtin/blame.c (David Kastrup 1398470209 +0200)
4) * Copyright (c) 2006, 2014 by its authors
5) * See COPYING for licensing conditions
cee7f245dc builtin-pickaxe.c (Junio C Hamano 1161298804 -0700)
6) */
7)
8) #include "cache.h"
fb58c8d507 builtin/blame.c (Michael Haggerty 1434981785 +0200)
9) #include "refs.h"
cee7f245dc builtin-pickaxe.c (Junio C Hamano 1161298804 -0700)
10) #include "builtin.h"
11) #include "blob.h"
12) #include "commit.h"
13) #include "tag.h"
14) #include "tree-walk.h"
15) #include "diff.h"
16) #include "diffcore.h"
17) #include "revision.h"
717d1462ba builtin-blame.c (Linus Torvalds 1169976846 -0800)
18) #include "quote.h"
cee7f245dc builtin-pickaxe.c (Junio C Hamano 1161298804 -0700)
19) #include "xdiff-interface.h"It can be seen that options like -t still work in aggregation.
In relation to the previous conversation about "tips", I think a better name could be "hints" and it could be added on top of the aggregation.
Quoted 142 lines · Edmundo Carmona Antoranz
--- builtin/blame.c | 78 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 27 deletions(-)builtin/blame.c +51
-28@@ -1884,6 +1884,7 @@ static const char *format_time(unsigned long time, const char *tz_str,#define OUTPUT_NO_AUTHOR 0200#define OUTPUT_SHOW_EMAIL 0400#define OUTPUT_LINE_PORCELAIN 01000 +#define OUTPUT_AGGREGATE 02000static void emit_porcelain_details (struct origin *suspect,int repeat) {@@ -1931,43 +1932,36 @@ static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent,putchar ('\n' ); } -static void emit_other (struct scoreboard *sb,struct blame_entry *ent,int opt) +/** +* Print information about the revision. +* This information can be used in either aggregated output +* or prepending each line of the content of the file being blamed +*/ +static void print_revision_info (char * revision_hex,int revision_length,struct blame_entry * ent, +struct commit * commit,struct commit_info ci,int opt,int show_raw_time) { -int cnt; -const char *cp; -struct origin *suspect = ent->suspect; -struct commit_info ci; -char hex[GIT_SHA1_HEXSZ +1 ]; -int show_raw_time = !!(opt &OUTPUT_RAW_TIMESTAMP ); - -get_commit_info (suspect->commit, &ci,1 ); -sha1_to_hex_r (hex, suspect->commit->object.oid.hash); - - cp =nth_line (sb, ent->lno); -for (cnt =0 ; cnt < ent->num_lines; cnt++) { -char ch; -int length = (opt &OUTPUT_LONG_OBJECT_NAME ) ?GIT_SHA1_HEXSZ : abbrev; - -if (suspect->commit->object.flags &UNINTERESTING ) { +if (opt &OUTPUT_AGGREGATE ) +printf ("\t" ); +int length = revision_length; +if (commit->object.flags &UNINTERESTING ) {if (blank_boundary) -memset (hex,' ' , length); +memset (revision_hex,' ' , length);else if (!(opt &OUTPUT_ANNOTATE_COMPAT )) { length--;putchar ('^' ); } } -printf ("%.*s" , length, hex); +printf ("%.*s" , length, revision_hex);if (opt &OUTPUT_ANNOTATE_COMPAT ) {const char *name;if (opt &OUTPUT_SHOW_EMAIL ) name = ci.author_mail.buf;else name = ci.author.buf; -printf ("\t(%10s\t%10s\t%d)" , name, +printf ("\t(%10s\t%10s\t" , name,format_time (ci.author_time, ci.author_tz.buf, - show_raw_time), - ent->lno +1 + cnt); + show_raw_time)); }else {if (opt &OUTPUT_SHOW_SCORE ) printf(" %*d %02d",@@ -1975,11 +1969,7 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt) ent->suspect->refcnt);if (opt &OUTPUT_SHOW_NAME )printf (" %-*.*s" , longest_file, longest_file, - suspect->path); -if (opt &OUTPUT_SHOW_NUMBER ) -printf (" %*d" , max_orig_digits, - ent->s_lno +1 + cnt); - + ent->suspect->path);if (!(opt &OUTPUT_NO_AUTHOR )) {const char *name;int pad;@@ -1994,9 +1984,42 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt) ci.author_tz.buf, show_raw_time)); } + } +if (opt &OUTPUT_AGGREGATE ) +printf (")\n" ); +} + +static void emit_other (struct scoreboard *sb,struct blame_entry *ent,int opt) +{ +int cnt; +const char *cp; +struct origin *suspect = ent->suspect; +struct commit_info ci; +char hex[GIT_SHA1_HEXSZ +1 ]; +int show_raw_time = !!(opt &OUTPUT_RAW_TIMESTAMP ); +int revision_length = (opt &OUTPUT_LONG_OBJECT_NAME ) ?GIT_SHA1_HEXSZ : abbrev; + +get_commit_info (suspect->commit, &ci,1 ); +sha1_to_hex_r (hex, suspect->commit->object.oid.hash); + +if (opt &OUTPUT_AGGREGATE ) +print_revision_info (hex, revision_length, ent, suspect->commit, ci, opt, show_raw_time); + + cp =nth_line (sb, ent->lno); +for (cnt =0 ; cnt < ent->num_lines; cnt++) { +if (!(opt &OUTPUT_AGGREGATE )) +print_revision_info (hex, revision_length, ent, suspect->commit, ci, opt, show_raw_time); +if (opt &OUTPUT_ANNOTATE_COMPAT ) { +printf ("%*d) " , + max_digits, ent->lno +1 + cnt); + }else { +if (opt &OUTPUT_SHOW_NUMBER ) +printf (" %*d " , max_orig_digits, + ent->s_lno +1 + cnt);printf (" %*d) " , max_digits, ent->lno +1 + cnt); } +char ch; do { ch = *cp++; putchar(ch);@@ -2609,6 +2632,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) { OPTION_CALLBACK, 'C', NULL, &opt, N_("score"), N_("Find line copies within and across files"), PARSE_OPT_OPTARG, blame_copy_callback }, { OPTION_CALLBACK, 'M', NULL, &opt, N_("score"), N_("Find line movements within and across files"), PARSE_OPT_OPTARG, blame_move_callback },OPT_STRING_LIST ('L' ,NULL , &range_list,N_ ("n,m" ),N_ ("Process only line range n,m, counting from 1" )), +OPT_BIT (0 ,"aggregate" , &output_option,N_ ("Aggregate output" ),OUTPUT_AGGREGATE ),OPT__ABBREV (&abbrev),OPT_END () }; --2.11.0.rc1