451
pend = p + plain->len;
452
while (p != pend) {
453
char *eol = memchr(p, '\n', pend - p);
454
- const char *deleted = NULL, *added = NULL, *mode_change = NULL;
454
+ const char *deleted = NULL, *mode_change = NULL;
455
456
if (!eol)
457
eol = pend;
468
} else if (p == plain->buf)
469
BUG("diff starts with unexpected line:\n"
470
"%.*s\n", (int)(eol - p), p);
471
- else if (file_diff->deleted || file_diff->added)
471
+ else if (file_diff->deleted)
472
; /* keep the rest of the file in a single "hunk" */
473
else if (starts_with(p, "@@ ") ||
474
(hunk == &file_diff->head &&
475
- (skip_prefix(p, "deleted file", &deleted) ||
476
- skip_prefix(p, "new file", &added)))) {
475
+ (skip_prefix(p, "deleted file", &deleted)))) {
476
if (marker == '-' || marker == '+')
477
/*
478
* Should not happen; previous hunk did not end
490
491
if (deleted)
492
file_diff->deleted = 1;
494
- else if (added)
495
- file_diff->added = 1;
493
else if (parse_hunk_header(s, hunk) < 0)
494
return -1;
495
498
* split
499
*/
500
marker = *p;
501
+ } else if (hunk == &file_diff->head &&
502
+ starts_with(p, "new file")) {
503
+ file_diff->added = 1;
504
} else if (hunk == &file_diff->head &&
505
skip_prefix(p, "old mode ", &mode_change) &&
506
is_octal(mode_change, eol - mode_change)) {
1362
ALLOW_EDIT = 1 << 6
1363
} permitted = 0;
1364
1365
- if (!file_diff->hunk_nr)
1365
+ /* Empty added files have no hunks */
1366
+ if (!file_diff->hunk_nr && !file_diff->added)
1367
return 0;
1368
1369
strbuf_reset(&s->buf);
1372
for (;;) {
1373
if (hunk_index >= file_diff->hunk_nr)
1374
hunk_index = 0;
1374
- hunk = file_diff->hunk + hunk_index;
1375
-
1375
+ hunk = file_diff->hunk_nr
1376
+ ? file_diff->hunk + hunk_index
1377
+ : &file_diff->head;
1378
undecided_previous = -1;
1377
- for (i = hunk_index - 1; i >= 0; i--)
1378
- if (file_diff->hunk[i].use == UNDECIDED_HUNK) {
1379
- undecided_previous = i;
1380
- break;
1381
- }
1382
-
1379
undecided_next = -1;
1384
- for (i = hunk_index + 1; i < file_diff->hunk_nr; i++)
1385
- if (file_diff->hunk[i].use == UNDECIDED_HUNK) {
1386
- undecided_next = i;
1387
- break;
1388
- }
1380
+
1381
+ if (file_diff->hunk_nr) {
1382
+ for (i = hunk_index - 1; i >= 0; i--)
1383
+ if (file_diff->hunk[i].use == UNDECIDED_HUNK) {
1384
+ undecided_previous = i;
1385
+ break;
1386
+ }
1387
+
1388
+ for (i = hunk_index + 1; i < file_diff->hunk_nr; i++)
1389
+ if (file_diff->hunk[i].use == UNDECIDED_HUNK) {
1390
+ undecided_next = i;
1391
+ break;
1392
+ }
1393
+ }
1394
1395
/* Everything decided? */
1396
if (undecided_previous < 0 && undecided_next < 0 &&
1398
break;
1399
1400
strbuf_reset(&s->buf);
1396
- render_hunk(s, hunk, 0, colored, &s->buf);
1397
- fputs(s->buf.buf, stdout);
1401
+ if (file_diff->hunk_nr) {
1402
+ render_hunk(s, hunk, 0, colored, &s->buf);
1403
+ fputs(s->buf.buf, stdout);
1404
1399
- strbuf_reset(&s->buf);
1400
- if (undecided_previous >= 0) {
1401
- permitted |= ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK;
1402
- strbuf_addstr(&s->buf, ",k");
1403
- }
1404
- if (hunk_index) {
1405
- permitted |= ALLOW_GOTO_PREVIOUS_HUNK;
1406
- strbuf_addstr(&s->buf, ",K");
1407
- }
1408
- if (undecided_next >= 0) {
1409
- permitted |= ALLOW_GOTO_NEXT_UNDECIDED_HUNK;
1410
- strbuf_addstr(&s->buf, ",j");
1411
- }
1412
- if (hunk_index + 1 < file_diff->hunk_nr) {
1413
- permitted |= ALLOW_GOTO_NEXT_HUNK;
1414
- strbuf_addstr(&s->buf, ",J");
1415
- }
1416
- if (file_diff->hunk_nr > 1) {
1417
- permitted |= ALLOW_SEARCH_AND_GOTO;
1418
- strbuf_addstr(&s->buf, ",g,/");
1419
- }
1420
- if (hunk->splittable_into > 1) {
1421
- permitted |= ALLOW_SPLIT;
1422
- strbuf_addstr(&s->buf, ",s");
1423
- }
1424
- if (hunk_index + 1 > file_diff->mode_change &&
1425
- !file_diff->deleted) {
1426
- permitted |= ALLOW_EDIT;
1427
- strbuf_addstr(&s->buf, ",e");
1405
+ strbuf_reset(&s->buf);
1406
+ if (undecided_previous >= 0) {
1407
+ permitted |= ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK;
1408
+ strbuf_addstr(&s->buf, ",k");
1409
+ }
1410
+ if (hunk_index) {
1411
+ permitted |= ALLOW_GOTO_PREVIOUS_HUNK;
1412
+ strbuf_addstr(&s->buf, ",K");
1413
+ }
1414
+ if (undecided_next >= 0) {
1415
+ permitted |= ALLOW_GOTO_NEXT_UNDECIDED_HUNK;
1416
+ strbuf_addstr(&s->buf, ",j");
1417
+ }
1418
+ if (hunk_index + 1 < file_diff->hunk_nr) {
1419
+ permitted |= ALLOW_GOTO_NEXT_HUNK;
1420
+ strbuf_addstr(&s->buf, ",J");
1421
+ }
1422
+ if (file_diff->hunk_nr > 1) {
1423
+ permitted |= ALLOW_SEARCH_AND_GOTO;
1424
+ strbuf_addstr(&s->buf, ",g,/");
1425
+ }
1426
+ if (hunk->splittable_into > 1) {
1427
+ permitted |= ALLOW_SPLIT;
1428
+ strbuf_addstr(&s->buf, ",s");
1429
+ }
1430
+ if (hunk_index + 1 > file_diff->mode_change &&
1431
+ !file_diff->deleted) {
1432
+ permitted |= ALLOW_EDIT;
1433
+ strbuf_addstr(&s->buf, ",e");
1434
+ }
1435
}
1436
if (file_diff->deleted)
1437
prompt_mode_type = PROMPT_DELETION;
1445
color_fprintf(stdout, s->s.prompt_color,
1446
"(%"PRIuMAX"/%"PRIuMAX") ",
1447
(uintmax_t)hunk_index + 1,
1441
- (uintmax_t)file_diff->hunk_nr);
1448
+ (uintmax_t)(file_diff->hunk_nr
1449
+ ? file_diff->hunk_nr
1450
+ : 1));
1451
color_fprintf(stdout, s->s.prompt_color,
1452
_(s->mode->prompt_mode[prompt_mode_type]),
1453
s->buf.buf);
1467
hunk->use = SKIP_HUNK;
1468
goto soft_increment;
1469
} else if (ch == 'a') {
1461
- for (; hunk_index < file_diff->hunk_nr; hunk_index++) {
1462
- hunk = file_diff->hunk + hunk_index;
1463
- if (hunk->use == UNDECIDED_HUNK)
1464
- hunk->use = USE_HUNK;
1470
+ if (file_diff->hunk_nr) {
1471
+ for (; hunk_index < file_diff->hunk_nr; hunk_index++) {
1472
+ hunk = file_diff->hunk + hunk_index;
1473
+ if (hunk->use == UNDECIDED_HUNK)
1474
+ hunk->use = USE_HUNK;
1475
+ }
1476
+ } else if (hunk->use == UNDECIDED_HUNK) {
1477
+ hunk->use = USE_HUNK;
1478
}
1479
} else if (ch == 'd' || ch == 'q') {
1467
- for (; hunk_index < file_diff->hunk_nr; hunk_index++) {
1468
- hunk = file_diff->hunk + hunk_index;
1469
- if (hunk->use == UNDECIDED_HUNK)
1470
- hunk->use = SKIP_HUNK;
1480
+ if (file_diff->hunk_nr) {
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;
1485
+ }
1486
+ } else if (hunk->use == UNDECIDED_HUNK) {
1487
+ hunk->use = SKIP_HUNK;
1488
}
1489
if (ch == 'q') {
1490
quit = 1;
1642
if (file_diff->hunk[i].use == USE_HUNK)
1643
break;
1644
1628
- if (i < file_diff->hunk_nr) {
1645
+ if (i < file_diff->hunk_nr ||
1646
+ (!file_diff->hunk_nr && file_diff->head.use == USE_HUNK)) {
1647
/* At least one hunk selected: apply */
1648
strbuf_reset(&s->buf);
1649
reassemble_patch(s, file_diff, 0, &s->buf);