@@ -154,6 +154,7 @@ struct patch {
154154 unsigned int is_binary :1 ;
155155 unsigned int is_copy :1 ;
156156 unsigned int is_rename :1 ;
157+ unsigned int recount :1 ;
157158 struct fragment * fragments ;
158159 char * result ;
159160 size_t resultsize ;
@@ -890,6 +891,56 @@ static int parse_range(const char *line, int len, int offset, const char *expect
890891 return offset + ex ;
891892}
892893
894+ static void recount_diff (char * line , int size , struct fragment * fragment )
895+ {
896+ int oldlines = 0 , newlines = 0 , ret = 0 ;
897+
898+ if (size < 1 ) {
899+ warning ("recount: ignore empty hunk" );
900+ return ;
901+ }
902+
903+ for (;;) {
904+ int len = linelen (line , size );
905+ size -= len ;
906+ line += len ;
907+
908+ if (size < 1 )
909+ break ;
910+
911+ switch (* line ) {
912+ case ' ' : case '\n' :
913+ newlines ++ ;
914+ /* fall through */
915+ case '-' :
916+ oldlines ++ ;
917+ continue ;
918+ case '+' :
919+ newlines ++ ;
920+ continue ;
921+ case '\\' :
922+ break ;
923+ case '@' :
924+ ret = size < 3 || prefixcmp (line , "@@ " );
925+ break ;
926+ case 'd' :
927+ ret = size < 5 || prefixcmp (line , "diff " );
928+ break ;
929+ default :
930+ ret = -1 ;
931+ break ;
932+ }
933+ if (ret ) {
934+ warning ("recount: unexpected line: %.*s" ,
935+ (int )linelen (line , size ), line );
936+ return ;
937+ }
938+ break ;
939+ }
940+ fragment -> oldlines = oldlines ;
941+ fragment -> newlines = newlines ;
942+ }
943+
893944/*
894945 * Parse a unified diff fragment header of the
895946 * form "@@ -a,b +c,d @@"
@@ -1020,6 +1071,8 @@ static int parse_fragment(char *line, unsigned long size,
10201071 offset = parse_fragment_header (line , len , fragment );
10211072 if (offset < 0 )
10221073 return -1 ;
1074+ if (offset > 0 && patch -> recount )
1075+ recount_diff (line + offset , size - offset , fragment );
10231076 oldlines = fragment -> oldlines ;
10241077 newlines = fragment -> newlines ;
10251078 leading = 0 ;
@@ -2971,7 +3024,10 @@ static void prefix_patches(struct patch *p)
29713024 }
29723025}
29733026
2974- static int apply_patch (int fd , const char * filename , int inaccurate_eof )
3027+ #define INACCURATE_EOF (1<<0)
3028+ #define RECOUNT (1<<1)
3029+
3030+ static int apply_patch (int fd , const char * filename , int options )
29753031{
29763032 size_t offset ;
29773033 struct strbuf buf ;
@@ -2989,7 +3045,8 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
29893045 int nr ;
29903046
29913047 patch = xcalloc (1 , sizeof (* patch ));
2992- patch -> inaccurate_eof = inaccurate_eof ;
3048+ patch -> inaccurate_eof = !!(options & INACCURATE_EOF );
3049+ patch -> recount = !!(options & RECOUNT );
29933050 nr = parse_chunk (buf .buf + offset , buf .len - offset , patch );
29943051 if (nr < 0 )
29953052 break ;
@@ -3058,7 +3115,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
30583115{
30593116 int i ;
30603117 int read_stdin = 1 ;
3061- int inaccurate_eof = 0 ;
3118+ int options = 0 ;
30623119 int errs = 0 ;
30633120 int is_not_gitdir ;
30643121
@@ -3076,7 +3133,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
30763133 int fd ;
30773134
30783135 if (!strcmp (arg , "-" )) {
3079- errs |= apply_patch (0 , "<stdin>" , inaccurate_eof );
3136+ errs |= apply_patch (0 , "<stdin>" , options );
30803137 read_stdin = 0 ;
30813138 continue ;
30823139 }
@@ -3176,7 +3233,11 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
31763233 continue ;
31773234 }
31783235 if (!strcmp (arg , "--inaccurate-eof" )) {
3179- inaccurate_eof = 1 ;
3236+ options |= INACCURATE_EOF ;
3237+ continue ;
3238+ }
3239+ if (!strcmp (arg , "--recount" )) {
3240+ options |= RECOUNT ;
31803241 continue ;
31813242 }
31823243 if (0 < prefix_length )
@@ -3187,12 +3248,12 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
31873248 die ("can't open patch '%s': %s" , arg , strerror (errno ));
31883249 read_stdin = 0 ;
31893250 set_default_whitespace_mode (whitespace_option );
3190- errs |= apply_patch (fd , arg , inaccurate_eof );
3251+ errs |= apply_patch (fd , arg , options );
31913252 close (fd );
31923253 }
31933254 set_default_whitespace_mode (whitespace_option );
31943255 if (read_stdin )
3195- errs |= apply_patch (0 , "<stdin>" , inaccurate_eof );
3256+ errs |= apply_patch (0 , "<stdin>" , options );
31963257 if (whitespace_error ) {
31973258 if (squelch_whitespace_errors &&
31983259 squelch_whitespace_errors < whitespace_error ) {
0 commit comments