@@ -397,6 +397,46 @@ static void show_stats(struct diffstat_t* data)
397397 total_files , adds , dels );
398398}
399399
400+ struct checkdiff_t {
401+ struct xdiff_emit_state xm ;
402+ const char * filename ;
403+ int lineno ;
404+ };
405+
406+ static void checkdiff_consume (void * priv , char * line , unsigned long len )
407+ {
408+ struct checkdiff_t * data = priv ;
409+
410+ if (line [0 ] == '+' ) {
411+ int i , spaces = 0 ;
412+
413+ data -> lineno ++ ;
414+
415+ /* check space before tab */
416+ for (i = 1 ; i < len && (line [i ] == ' ' || line [i ] == '\t' ); i ++ )
417+ if (line [i ] == ' ' )
418+ spaces ++ ;
419+ if (line [i - 1 ] == '\t' && spaces )
420+ printf ("%s:%d: space before tab:%.*s\n" ,
421+ data -> filename , data -> lineno , (int )len , line );
422+
423+ /* check white space at line end */
424+ if (line [len - 1 ] == '\n' )
425+ len -- ;
426+ if (isspace (line [len - 1 ]))
427+ printf ("%s:%d: white space at end: %.*s\n" ,
428+ data -> filename , data -> lineno , (int )len , line );
429+ } else if (line [0 ] == ' ' )
430+ data -> lineno ++ ;
431+ else if (line [0 ] == '@' ) {
432+ char * plus = strchr (line , '+' );
433+ if (plus )
434+ data -> lineno = strtol (plus , line + len , 10 );
435+ else
436+ die ("invalid diff" );
437+ }
438+ }
439+
400440static unsigned char * deflate_it (char * data ,
401441 unsigned long size ,
402442 unsigned long * result_size )
@@ -624,6 +664,41 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
624664 }
625665}
626666
667+ static void builtin_checkdiff (const char * name_a , const char * name_b ,
668+ struct diff_filespec * one ,
669+ struct diff_filespec * two )
670+ {
671+ mmfile_t mf1 , mf2 ;
672+ struct checkdiff_t data ;
673+
674+ if (!two )
675+ return ;
676+
677+ memset (& data , 0 , sizeof (data ));
678+ data .xm .consume = checkdiff_consume ;
679+ data .filename = name_b ? name_b : name_a ;
680+ data .lineno = 0 ;
681+
682+ if (fill_mmfile (& mf1 , one ) < 0 || fill_mmfile (& mf2 , two ) < 0 )
683+ die ("unable to read files to diff" );
684+
685+ if (mmfile_is_binary (& mf2 ))
686+ return ;
687+ else {
688+ /* Crazy xdl interfaces.. */
689+ xpparam_t xpp ;
690+ xdemitconf_t xecfg ;
691+ xdemitcb_t ecb ;
692+
693+ xpp .flags = XDF_NEED_MINIMAL ;
694+ xecfg .ctxlen = 0 ;
695+ xecfg .flags = 0 ;
696+ ecb .outf = xdiff_outf ;
697+ ecb .priv = & data ;
698+ xdl_diff (& mf1 , & mf2 , & xpp , & xecfg , & ecb );
699+ }
700+ }
701+
627702struct diff_filespec * alloc_filespec (const char * path )
628703{
629704 int namelen = strlen (path );
@@ -1180,6 +1255,25 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
11801255 builtin_diffstat (name , other , p -> one , p -> two , diffstat , complete_rewrite );
11811256}
11821257
1258+ static void run_checkdiff (struct diff_filepair * p , struct diff_options * o )
1259+ {
1260+ const char * name ;
1261+ const char * other ;
1262+
1263+ if (DIFF_PAIR_UNMERGED (p )) {
1264+ /* unmerged */
1265+ return ;
1266+ }
1267+
1268+ name = p -> one -> path ;
1269+ other = (strcmp (name , p -> two -> path ) ? p -> two -> path : NULL );
1270+
1271+ diff_fill_sha1_info (p -> one );
1272+ diff_fill_sha1_info (p -> two );
1273+
1274+ builtin_checkdiff (name , other , p -> one , p -> two );
1275+ }
1276+
11831277void diff_setup (struct diff_options * options )
11841278{
11851279 memset (options , 0 , sizeof (* options ));
@@ -1205,7 +1299,8 @@ int diff_setup_done(struct diff_options *options)
12051299 * recursive bits for other formats here.
12061300 */
12071301 if ((options -> output_format == DIFF_FORMAT_PATCH ) ||
1208- (options -> output_format == DIFF_FORMAT_DIFFSTAT ))
1302+ (options -> output_format == DIFF_FORMAT_DIFFSTAT ) ||
1303+ (options -> output_format == DIFF_FORMAT_CHECKDIFF ))
12091304 options -> recursive = 1 ;
12101305
12111306 if (options -> detect_rename && options -> rename_limit < 0 )
@@ -1288,6 +1383,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
12881383 }
12891384 else if (!strcmp (arg , "--stat" ))
12901385 options -> output_format = DIFF_FORMAT_DIFFSTAT ;
1386+ else if (!strcmp (arg , "--check" ))
1387+ options -> output_format = DIFF_FORMAT_CHECKDIFF ;
12911388 else if (!strcmp (arg , "--summary" ))
12921389 options -> summary = 1 ;
12931390 else if (!strcmp (arg , "--patch-with-stat" )) {
@@ -1610,6 +1707,19 @@ static void diff_flush_stat(struct diff_filepair *p, struct diff_options *o,
16101707 run_diffstat (p , o , diffstat );
16111708}
16121709
1710+ static void diff_flush_checkdiff (struct diff_filepair * p ,
1711+ struct diff_options * o )
1712+ {
1713+ if (diff_unmodified_pair (p ))
1714+ return ;
1715+
1716+ if ((DIFF_FILE_VALID (p -> one ) && S_ISDIR (p -> one -> mode )) ||
1717+ (DIFF_FILE_VALID (p -> two ) && S_ISDIR (p -> two -> mode )))
1718+ return ; /* no tree diffs in patch format */
1719+
1720+ run_checkdiff (p , o );
1721+ }
1722+
16131723int diff_queue_is_empty (void )
16141724{
16151725 struct diff_queue_struct * q = & diff_queued_diff ;
@@ -1740,6 +1850,9 @@ static void flush_one_pair(struct diff_filepair *p,
17401850 case DIFF_FORMAT_DIFFSTAT :
17411851 diff_flush_stat (p , options , diffstat );
17421852 break ;
1853+ case DIFF_FORMAT_CHECKDIFF :
1854+ diff_flush_checkdiff (p , options );
1855+ break ;
17431856 case DIFF_FORMAT_PATCH :
17441857 diff_flush_patch (p , options );
17451858 break ;
0 commit comments