@@ -457,6 +457,76 @@ static int guess_p_value(const char *nameline)
457
457
return val ;
458
458
}
459
459
460
+ /*
461
+ * Does the ---/+++ line has the POSIX timestamp after the last HT?
462
+ * GNU diff puts epoch there to signal a creation/deletion event. Is
463
+ * this such a timestamp?
464
+ */
465
+ static int has_epoch_timestamp (const char * nameline )
466
+ {
467
+ /*
468
+ * We are only interested in epoch timestamp; any non-zero
469
+ * fraction cannot be one, hence "(\.0+)?" in the regexp below.
470
+ * For the same reason, the date must be either 1969-12-31 or
471
+ * 1970-01-01, and the seconds part must be "00".
472
+ */
473
+ const char stamp_regexp [] =
474
+ "^(1969-12-31|1970-01-01)"
475
+ " "
476
+ "[0-2][0-9]:[0-5][0-9]:00(\\.0+)?"
477
+ " "
478
+ "([-+][0-2][0-9][0-5][0-9])\n" ;
479
+ const char * timestamp = NULL , * cp ;
480
+ static regex_t * stamp ;
481
+ regmatch_t m [10 ];
482
+ int zoneoffset ;
483
+ int hourminute ;
484
+ int status ;
485
+
486
+ for (cp = nameline ; * cp != '\n' ; cp ++ ) {
487
+ if (* cp == '\t' )
488
+ timestamp = cp + 1 ;
489
+ }
490
+ if (!timestamp )
491
+ return 0 ;
492
+ if (!stamp ) {
493
+ stamp = xmalloc (sizeof (* stamp ));
494
+ if (regcomp (stamp , stamp_regexp , REG_EXTENDED )) {
495
+ warning ("Cannot prepare timestamp regexp %s" ,
496
+ stamp_regexp );
497
+ return 0 ;
498
+ }
499
+ }
500
+
501
+ status = regexec (stamp , timestamp , ARRAY_SIZE (m ), m , 0 );
502
+ if (status ) {
503
+ if (status != REG_NOMATCH )
504
+ warning ("regexec returned %d for input: %s" ,
505
+ status , timestamp );
506
+ return 0 ;
507
+ }
508
+
509
+ zoneoffset = strtol (timestamp + m [3 ].rm_so + 1 , NULL , 10 );
510
+ zoneoffset = (zoneoffset / 100 ) * 60 + (zoneoffset % 100 );
511
+ if (timestamp [m [3 ].rm_so ] == '-' )
512
+ zoneoffset = - zoneoffset ;
513
+
514
+ /*
515
+ * YYYY-MM-DD hh:mm:ss must be from either 1969-12-31
516
+ * (west of GMT) or 1970-01-01 (east of GMT)
517
+ */
518
+ if ((zoneoffset < 0 && memcmp (timestamp , "1969-12-31" , 10 )) ||
519
+ (0 <= zoneoffset && memcmp (timestamp , "1970-01-01" , 10 )))
520
+ return 0 ;
521
+
522
+ hourminute = (strtol (timestamp + 11 , NULL , 10 ) * 60 +
523
+ strtol (timestamp + 14 , NULL , 10 ) -
524
+ zoneoffset );
525
+
526
+ return ((zoneoffset < 0 && hourminute == 1440 ) ||
527
+ (0 <= zoneoffset && !hourminute ));
528
+ }
529
+
460
530
/*
461
531
* Get the name etc info from the ---/+++ lines of a traditional patch header
462
532
*
@@ -493,7 +563,17 @@ static void parse_traditional_patch(const char *first, const char *second, struc
493
563
} else {
494
564
name = find_name (first , NULL , p_value , TERM_SPACE | TERM_TAB );
495
565
name = find_name (second , name , p_value , TERM_SPACE | TERM_TAB );
496
- patch -> old_name = patch -> new_name = name ;
566
+ if (has_epoch_timestamp (first )) {
567
+ patch -> is_new = 1 ;
568
+ patch -> is_delete = 0 ;
569
+ patch -> new_name = name ;
570
+ } else if (has_epoch_timestamp (second )) {
571
+ patch -> is_new = 0 ;
572
+ patch -> is_delete = 1 ;
573
+ patch -> old_name = name ;
574
+ } else {
575
+ patch -> old_name = patch -> new_name = name ;
576
+ }
497
577
}
498
578
if (!name )
499
579
die ("unable to find filename in patch at line %d" , linenr );
0 commit comments