1717#include "diffcore.h"
1818#include "revision.h"
1919#include "xdiff-interface.h"
20+ #include "quote.h"
2021
2122#define DEBUG 0
2223
@@ -40,6 +41,7 @@ struct util_info {
4041 unsigned long size ;
4142 int num_lines ;
4243 const char * pathname ;
44+ unsigned meta_given :1 ;
4345
4446 void * topo_data ;
4547};
@@ -332,12 +334,8 @@ static struct util_info *get_util(struct commit *commit)
332334 if (util )
333335 return util ;
334336
335- util = xmalloc (sizeof (struct util_info ));
336- util -> buf = NULL ;
337- util -> size = 0 ;
338- util -> line_map = NULL ;
337+ util = xcalloc (1 , sizeof (struct util_info ));
339338 util -> num_lines = -1 ;
340- util -> pathname = NULL ;
341339 commit -> util = util ;
342340 return util ;
343341}
@@ -642,39 +640,99 @@ struct commit_info
642640 char * author_mail ;
643641 unsigned long author_time ;
644642 char * author_tz ;
643+
644+ /* filled only when asked for details */
645+ char * committer ;
646+ char * committer_mail ;
647+ unsigned long committer_time ;
648+ char * committer_tz ;
649+
650+ char * summary ;
645651};
646652
647- static void get_commit_info (struct commit * commit , struct commit_info * ret )
653+ static void get_ac_line (const char * inbuf , const char * what ,
654+ int bufsz , char * person , char * * mail ,
655+ unsigned long * time , char * * tz )
648656{
649657 int len ;
650- char * tmp ;
651- static char author_buf [1024 ];
652-
653- tmp = strstr (commit -> buffer , "\nauthor " ) + 8 ;
654- len = strchr (tmp , '\n' ) - tmp ;
655- ret -> author = author_buf ;
656- memcpy (ret -> author , tmp , len );
658+ char * tmp , * endp ;
659+
660+ tmp = strstr (inbuf , what );
661+ if (!tmp )
662+ goto error_out ;
663+ tmp += strlen (what );
664+ endp = strchr (tmp , '\n' );
665+ if (!endp )
666+ len = strlen (tmp );
667+ else
668+ len = endp - tmp ;
669+ if (bufsz <= len ) {
670+ error_out :
671+ /* Ugh */
672+ person = * mail = * tz = "(unknown)" ;
673+ * time = 0 ;
674+ return ;
675+ }
676+ memcpy (person , tmp , len );
657677
658- tmp = ret -> author ;
678+ tmp = person ;
659679 tmp += len ;
660680 * tmp = 0 ;
661681 while (* tmp != ' ' )
662682 tmp -- ;
663- ret -> author_tz = tmp + 1 ;
683+ * tz = tmp + 1 ;
664684
665685 * tmp = 0 ;
666686 while (* tmp != ' ' )
667687 tmp -- ;
668- ret -> author_time = strtoul (tmp , NULL , 10 );
688+ * time = strtoul (tmp , NULL , 10 );
669689
670690 * tmp = 0 ;
671691 while (* tmp != ' ' )
672692 tmp -- ;
673- ret -> author_mail = tmp + 1 ;
674-
693+ * mail = tmp + 1 ;
675694 * tmp = 0 ;
676695}
677696
697+ static void get_commit_info (struct commit * commit , struct commit_info * ret , int detailed )
698+ {
699+ int len ;
700+ char * tmp , * endp ;
701+ static char author_buf [1024 ];
702+ static char committer_buf [1024 ];
703+ static char summary_buf [1024 ];
704+
705+ ret -> author = author_buf ;
706+ get_ac_line (commit -> buffer , "\nauthor " ,
707+ sizeof (author_buf ), author_buf , & ret -> author_mail ,
708+ & ret -> author_time , & ret -> author_tz );
709+
710+ if (!detailed )
711+ return ;
712+
713+ ret -> committer = committer_buf ;
714+ get_ac_line (commit -> buffer , "\ncommitter " ,
715+ sizeof (committer_buf ), committer_buf , & ret -> committer_mail ,
716+ & ret -> committer_time , & ret -> committer_tz );
717+
718+ ret -> summary = summary_buf ;
719+ tmp = strstr (commit -> buffer , "\n\n" );
720+ if (!tmp ) {
721+ error_out :
722+ sprintf (summary_buf , "(%s)" , sha1_to_hex (commit -> object .sha1 ));
723+ return ;
724+ }
725+ tmp += 2 ;
726+ endp = strchr (tmp , '\n' );
727+ if (!endp )
728+ goto error_out ;
729+ len = endp - tmp ;
730+ if (len >= sizeof (summary_buf ))
731+ goto error_out ;
732+ memcpy (summary_buf , tmp , len );
733+ summary_buf [len ] = 0 ;
734+ }
735+
678736static const char * format_time (unsigned long time , const char * tz_str ,
679737 int show_raw_time )
680738{
@@ -751,7 +809,7 @@ static int find_orig_linenum(struct util_info *u, int lineno)
751809}
752810
753811static void emit_meta (struct commit * c , int lno ,
754- int sha1_len , int compatibility ,
812+ int sha1_len , int compatibility , int porcelain ,
755813 int show_name , int show_number , int show_raw_time ,
756814 int longest_file , int longest_author ,
757815 int max_digits , int max_orig_digits )
@@ -763,7 +821,47 @@ static void emit_meta(struct commit *c, int lno,
763821 u = c -> util ;
764822 lineno = find_orig_linenum (u , lno );
765823
766- get_commit_info (c , & ci );
824+ if (porcelain ) {
825+ int group_size = -1 ;
826+ struct commit * cc = (lno == 0 ) ? NULL : blame_lines [lno - 1 ];
827+ if (cc != c ) {
828+ /* This is the beginning of this group */
829+ int i ;
830+ for (i = lno + 1 ; i < num_blame_lines ; i ++ )
831+ if (blame_lines [i ] != c )
832+ break ;
833+ group_size = i - lno ;
834+ }
835+ if (0 < group_size )
836+ printf ("%s %d %d %d\n" , sha1_to_hex (c -> object .sha1 ),
837+ lineno , lno + 1 , group_size );
838+ else
839+ printf ("%s %d %d\n" , sha1_to_hex (c -> object .sha1 ),
840+ lineno , lno + 1 );
841+ if (!u -> meta_given ) {
842+ get_commit_info (c , & ci , 1 );
843+ printf ("author %s\n" , ci .author );
844+ printf ("author-mail %s\n" , ci .author_mail );
845+ printf ("author-time %lu\n" , ci .author_time );
846+ printf ("author-tz %s\n" , ci .author_tz );
847+ printf ("committer %s\n" , ci .committer );
848+ printf ("committer-mail %s\n" , ci .committer_mail );
849+ printf ("committer-time %lu\n" , ci .committer_time );
850+ printf ("committer-tz %s\n" , ci .committer_tz );
851+ printf ("filename " );
852+ if (quote_c_style (u -> pathname , NULL , NULL , 0 ))
853+ quote_c_style (u -> pathname , NULL , stdout , 0 );
854+ else
855+ fputs (u -> pathname , stdout );
856+ printf ("\nsummary %s\n" , ci .summary );
857+
858+ u -> meta_given = 1 ;
859+ }
860+ putchar ('\t' );
861+ return ;
862+ }
863+
864+ get_commit_info (c , & ci , 0 );
767865 fwrite (sha1_to_hex (c -> object .sha1 ), sha1_len , 1 , stdout );
768866 if (compatibility ) {
769867 printf ("\t(%10s\t%10s\t%d)" , ci .author ,
@@ -809,6 +907,7 @@ int main(int argc, const char **argv)
809907 int longest_file , longest_author , longest_file_lines ;
810908 int show_name = 0 ;
811909 int show_number = 0 ;
910+ int porcelain = 0 ;
812911
813912 const char * prefix = setup_git_directory ();
814913 git_config (git_default_config );
@@ -852,6 +951,12 @@ int main(int argc, const char **argv)
852951 show_number = 1 ;
853952 continue ;
854953 }
954+ if (!strcmp (argv [i ], "--porcelain" )) {
955+ porcelain = 1 ;
956+ sha1_len = 40 ;
957+ show_raw_time = 1 ;
958+ continue ;
959+ }
855960 if (!strcmp (argv [i ], "--" )) {
856961 options = 0 ;
857962 continue ;
@@ -934,7 +1039,7 @@ int main(int argc, const char **argv)
9341039 longest_file = strlen (u -> pathname );
9351040 if (longest_file_lines < u -> num_lines )
9361041 longest_file_lines = u -> num_lines ;
937- get_commit_info (c , & ci );
1042+ get_commit_info (c , & ci , 0 );
9381043 if (longest_author < strlen (ci .author ))
9391044 longest_author = strlen (ci .author );
9401045 }
@@ -943,7 +1048,7 @@ int main(int argc, const char **argv)
9431048
9441049 for (i = 0 ; i < num_blame_lines ; i ++ ) {
9451050 emit_meta (blame_lines [i ], i ,
946- sha1_len , compatibility ,
1051+ sha1_len , compatibility , porcelain ,
9471052 show_name , show_number , show_raw_time ,
9481053 longest_file , longest_author ,
9491054 max_digits , max_orig_digits );
0 commit comments