@@ -465,7 +465,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
465
465
pend = p + plain -> len ;
466
466
while (p != pend ) {
467
467
char * eol = memchr (p , '\n' , pend - p );
468
- const char * deleted = NULL , * added = NULL , * mode_change = NULL ;
468
+ const char * deleted = NULL , * mode_change = NULL ;
469
469
470
470
if (!eol )
471
471
eol = pend ;
@@ -482,12 +482,11 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
482
482
} else if (p == plain -> buf )
483
483
BUG ("diff starts with unexpected line:\n"
484
484
"%.*s\n" , (int )(eol - p ), p );
485
- else if (file_diff -> deleted || file_diff -> added )
485
+ else if (file_diff -> deleted )
486
486
; /* keep the rest of the file in a single "hunk" */
487
487
else if (starts_with (p , "@@ " ) ||
488
488
(hunk == & file_diff -> head &&
489
- (skip_prefix (p , "deleted file" , & deleted ) ||
490
- skip_prefix (p , "new file" , & added )))) {
489
+ (skip_prefix (p , "deleted file" , & deleted )))) {
491
490
if (marker == '-' || marker == '+' )
492
491
/*
493
492
* Should not happen; previous hunk did not end
@@ -505,8 +504,6 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
505
504
506
505
if (deleted )
507
506
file_diff -> deleted = 1 ;
508
- else if (added )
509
- file_diff -> added = 1 ;
510
507
else if (parse_hunk_header (s , hunk ) < 0 )
511
508
return -1 ;
512
509
@@ -515,6 +512,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
515
512
* split
516
513
*/
517
514
marker = * p ;
515
+ } else if (hunk == & file_diff -> head &&
516
+ starts_with (p , "new file" )) {
517
+ file_diff -> added = 1 ;
518
518
} else if (hunk == & file_diff -> head &&
519
519
skip_prefix (p , "old mode " , & mode_change ) &&
520
520
is_octal (mode_change , eol - mode_change )) {
@@ -1376,7 +1376,8 @@ static int patch_update_file(struct add_p_state *s,
1376
1376
ALLOW_EDIT = 1 << 6
1377
1377
} permitted = 0 ;
1378
1378
1379
- if (!file_diff -> hunk_nr )
1379
+ /* Empty added files have no hunks */
1380
+ if (!file_diff -> hunk_nr && !file_diff -> added )
1380
1381
return 0 ;
1381
1382
1382
1383
strbuf_reset (& s -> buf );
@@ -1385,60 +1386,66 @@ static int patch_update_file(struct add_p_state *s,
1385
1386
for (;;) {
1386
1387
if (hunk_index >= file_diff -> hunk_nr )
1387
1388
hunk_index = 0 ;
1388
- hunk = file_diff -> hunk + hunk_index ;
1389
-
1389
+ hunk = file_diff -> hunk_nr
1390
+ ? file_diff -> hunk + hunk_index
1391
+ : & file_diff -> head ;
1390
1392
undecided_previous = -1 ;
1391
- for (i = hunk_index - 1 ; i >= 0 ; i -- )
1392
- if (file_diff -> hunk [i ].use == UNDECIDED_HUNK ) {
1393
- undecided_previous = i ;
1394
- break ;
1395
- }
1396
-
1397
1393
undecided_next = -1 ;
1398
- for (i = hunk_index + 1 ; i < file_diff -> hunk_nr ; i ++ )
1399
- if (file_diff -> hunk [i ].use == UNDECIDED_HUNK ) {
1400
- undecided_next = i ;
1401
- break ;
1402
- }
1394
+
1395
+ if (file_diff -> hunk_nr ) {
1396
+ for (i = hunk_index - 1 ; i >= 0 ; i -- )
1397
+ if (file_diff -> hunk [i ].use == UNDECIDED_HUNK ) {
1398
+ undecided_previous = i ;
1399
+ break ;
1400
+ }
1401
+
1402
+ for (i = hunk_index + 1 ; i < file_diff -> hunk_nr ; i ++ )
1403
+ if (file_diff -> hunk [i ].use == UNDECIDED_HUNK ) {
1404
+ undecided_next = i ;
1405
+ break ;
1406
+ }
1407
+ }
1403
1408
1404
1409
/* Everything decided? */
1405
1410
if (undecided_previous < 0 && undecided_next < 0 &&
1406
1411
hunk -> use != UNDECIDED_HUNK )
1407
1412
break ;
1408
1413
1409
1414
strbuf_reset (& s -> buf );
1410
- render_hunk (s , hunk , 0 , colored , & s -> buf );
1411
- fputs (s -> buf .buf , stdout );
1415
+ if (file_diff -> hunk_nr ) {
1416
+ render_hunk (s , hunk , 0 , colored , & s -> buf );
1417
+ fputs (s -> buf .buf , stdout );
1412
1418
1413
- strbuf_reset (& s -> buf );
1414
- if (undecided_previous >= 0 ) {
1415
- permitted |= ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK ;
1416
- strbuf_addstr (& s -> buf , ",k" );
1417
- }
1418
- if (hunk_index ) {
1419
- permitted |= ALLOW_GOTO_PREVIOUS_HUNK ;
1420
- strbuf_addstr (& s -> buf , ",K" );
1421
- }
1422
- if (undecided_next >= 0 ) {
1423
- permitted |= ALLOW_GOTO_NEXT_UNDECIDED_HUNK ;
1424
- strbuf_addstr (& s -> buf , ",j" );
1425
- }
1426
- if (hunk_index + 1 < file_diff -> hunk_nr ) {
1427
- permitted |= ALLOW_GOTO_NEXT_HUNK ;
1428
- strbuf_addstr (& s -> buf , ",J" );
1429
- }
1430
- if (file_diff -> hunk_nr > 1 ) {
1431
- permitted |= ALLOW_SEARCH_AND_GOTO ;
1432
- strbuf_addstr (& s -> buf , ",g,/" );
1433
- }
1434
- if (hunk -> splittable_into > 1 ) {
1435
- permitted |= ALLOW_SPLIT ;
1436
- strbuf_addstr (& s -> buf , ",s" );
1437
- }
1438
- if (hunk_index + 1 > file_diff -> mode_change &&
1439
- !file_diff -> deleted ) {
1440
- permitted |= ALLOW_EDIT ;
1441
- strbuf_addstr (& s -> buf , ",e" );
1419
+ strbuf_reset (& s -> buf );
1420
+ if (undecided_previous >= 0 ) {
1421
+ permitted |= ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK ;
1422
+ strbuf_addstr (& s -> buf , ",k" );
1423
+ }
1424
+ if (hunk_index ) {
1425
+ permitted |= ALLOW_GOTO_PREVIOUS_HUNK ;
1426
+ strbuf_addstr (& s -> buf , ",K" );
1427
+ }
1428
+ if (undecided_next >= 0 ) {
1429
+ permitted |= ALLOW_GOTO_NEXT_UNDECIDED_HUNK ;
1430
+ strbuf_addstr (& s -> buf , ",j" );
1431
+ }
1432
+ if (hunk_index + 1 < file_diff -> hunk_nr ) {
1433
+ permitted |= ALLOW_GOTO_NEXT_HUNK ;
1434
+ strbuf_addstr (& s -> buf , ",J" );
1435
+ }
1436
+ if (file_diff -> hunk_nr > 1 ) {
1437
+ permitted |= ALLOW_SEARCH_AND_GOTO ;
1438
+ strbuf_addstr (& s -> buf , ",g,/" );
1439
+ }
1440
+ if (hunk -> splittable_into > 1 ) {
1441
+ permitted |= ALLOW_SPLIT ;
1442
+ strbuf_addstr (& s -> buf , ",s" );
1443
+ }
1444
+ if (hunk_index + 1 > file_diff -> mode_change &&
1445
+ !file_diff -> deleted ) {
1446
+ permitted |= ALLOW_EDIT ;
1447
+ strbuf_addstr (& s -> buf , ",e" );
1448
+ }
1442
1449
}
1443
1450
if (file_diff -> deleted )
1444
1451
prompt_mode_type = PROMPT_DELETION ;
@@ -1452,7 +1459,9 @@ static int patch_update_file(struct add_p_state *s,
1452
1459
color_fprintf (stdout , s -> s .prompt_color ,
1453
1460
"(%" PRIuMAX "/%" PRIuMAX ") " ,
1454
1461
(uintmax_t )hunk_index + 1 ,
1455
- (uintmax_t )file_diff -> hunk_nr );
1462
+ (uintmax_t )(file_diff -> hunk_nr
1463
+ ? file_diff -> hunk_nr
1464
+ : 1 ));
1456
1465
color_fprintf (stdout , s -> s .prompt_color ,
1457
1466
_ (s -> mode -> prompt_mode [prompt_mode_type ]),
1458
1467
s -> buf .buf );
@@ -1472,16 +1481,24 @@ static int patch_update_file(struct add_p_state *s,
1472
1481
hunk -> use = SKIP_HUNK ;
1473
1482
goto soft_increment ;
1474
1483
} else if (ch == 'a' ) {
1475
- for (; hunk_index < file_diff -> hunk_nr ; hunk_index ++ ) {
1476
- hunk = file_diff -> hunk + hunk_index ;
1477
- if (hunk -> use == UNDECIDED_HUNK )
1478
- hunk -> use = USE_HUNK ;
1484
+ if (file_diff -> hunk_nr ) {
1485
+ for (; hunk_index < file_diff -> hunk_nr ; hunk_index ++ ) {
1486
+ hunk = file_diff -> hunk + hunk_index ;
1487
+ if (hunk -> use == UNDECIDED_HUNK )
1488
+ hunk -> use = USE_HUNK ;
1489
+ }
1490
+ } else if (hunk -> use == UNDECIDED_HUNK ) {
1491
+ hunk -> use = USE_HUNK ;
1479
1492
}
1480
1493
} else if (ch == 'd' || ch == 'q' ) {
1481
- for (; hunk_index < file_diff -> hunk_nr ; hunk_index ++ ) {
1482
- hunk = file_diff -> hunk + hunk_index ;
1483
- if (hunk -> use == UNDECIDED_HUNK )
1484
- hunk -> use = SKIP_HUNK ;
1494
+ if (file_diff -> hunk_nr ) {
1495
+ for (; hunk_index < file_diff -> hunk_nr ; hunk_index ++ ) {
1496
+ hunk = file_diff -> hunk + hunk_index ;
1497
+ if (hunk -> use == UNDECIDED_HUNK )
1498
+ hunk -> use = SKIP_HUNK ;
1499
+ }
1500
+ } else if (hunk -> use == UNDECIDED_HUNK ) {
1501
+ hunk -> use = SKIP_HUNK ;
1485
1502
}
1486
1503
if (ch == 'q' ) {
1487
1504
quit = 1 ;
@@ -1639,7 +1656,8 @@ static int patch_update_file(struct add_p_state *s,
1639
1656
if (file_diff -> hunk [i ].use == USE_HUNK )
1640
1657
break ;
1641
1658
1642
- if (i < file_diff -> hunk_nr ) {
1659
+ if (i < file_diff -> hunk_nr ||
1660
+ (!file_diff -> hunk_nr && file_diff -> head .use == USE_HUNK )) {
1643
1661
/* At least one hunk selected: apply */
1644
1662
strbuf_reset (& s -> buf );
1645
1663
reassemble_patch (s , file_diff , 0 , & s -> buf );
0 commit comments