Skip to content

Commit 458205f

Browse files
committed
Merge branch 'pw/add-p-edit-ita-path'
"add -p" now allows editing paths that were only added in intent. * pw/add-p-edit-ita-path: add -p: fix editing of intent-to-add paths
2 parents c9a04f0 + 75a009d commit 458205f

File tree

3 files changed

+173
-94
lines changed

3 files changed

+173
-94
lines changed

add-patch.c

Lines changed: 79 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
465465
pend = p + plain->len;
466466
while (p != pend) {
467467
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;
469469

470470
if (!eol)
471471
eol = pend;
@@ -482,12 +482,11 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
482482
} else if (p == plain->buf)
483483
BUG("diff starts with unexpected line:\n"
484484
"%.*s\n", (int)(eol - p), p);
485-
else if (file_diff->deleted || file_diff->added)
485+
else if (file_diff->deleted)
486486
; /* keep the rest of the file in a single "hunk" */
487487
else if (starts_with(p, "@@ ") ||
488488
(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)))) {
491490
if (marker == '-' || marker == '+')
492491
/*
493492
* 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)
505504

506505
if (deleted)
507506
file_diff->deleted = 1;
508-
else if (added)
509-
file_diff->added = 1;
510507
else if (parse_hunk_header(s, hunk) < 0)
511508
return -1;
512509

@@ -515,6 +512,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
515512
* split
516513
*/
517514
marker = *p;
515+
} else if (hunk == &file_diff->head &&
516+
starts_with(p, "new file")) {
517+
file_diff->added = 1;
518518
} else if (hunk == &file_diff->head &&
519519
skip_prefix(p, "old mode ", &mode_change) &&
520520
is_octal(mode_change, eol - mode_change)) {
@@ -1376,7 +1376,8 @@ static int patch_update_file(struct add_p_state *s,
13761376
ALLOW_EDIT = 1 << 6
13771377
} permitted = 0;
13781378

1379-
if (!file_diff->hunk_nr)
1379+
/* Empty added files have no hunks */
1380+
if (!file_diff->hunk_nr && !file_diff->added)
13801381
return 0;
13811382

13821383
strbuf_reset(&s->buf);
@@ -1385,60 +1386,66 @@ static int patch_update_file(struct add_p_state *s,
13851386
for (;;) {
13861387
if (hunk_index >= file_diff->hunk_nr)
13871388
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;
13901392
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-
13971393
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+
}
14031408

14041409
/* Everything decided? */
14051410
if (undecided_previous < 0 && undecided_next < 0 &&
14061411
hunk->use != UNDECIDED_HUNK)
14071412
break;
14081413

14091414
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);
14121418

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+
}
14421449
}
14431450
if (file_diff->deleted)
14441451
prompt_mode_type = PROMPT_DELETION;
@@ -1452,7 +1459,9 @@ static int patch_update_file(struct add_p_state *s,
14521459
color_fprintf(stdout, s->s.prompt_color,
14531460
"(%"PRIuMAX"/%"PRIuMAX") ",
14541461
(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));
14561465
color_fprintf(stdout, s->s.prompt_color,
14571466
_(s->mode->prompt_mode[prompt_mode_type]),
14581467
s->buf.buf);
@@ -1472,16 +1481,24 @@ static int patch_update_file(struct add_p_state *s,
14721481
hunk->use = SKIP_HUNK;
14731482
goto soft_increment;
14741483
} 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;
14791492
}
14801493
} 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;
14851502
}
14861503
if (ch == 'q') {
14871504
quit = 1;
@@ -1639,7 +1656,8 @@ static int patch_update_file(struct add_p_state *s,
16391656
if (file_diff->hunk[i].use == USE_HUNK)
16401657
break;
16411658

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)) {
16431661
/* At least one hunk selected: apply */
16441662
strbuf_reset(&s->buf);
16451663
reassemble_patch(s, file_diff, 0, &s->buf);

git-add--interactive.perl

Lines changed: 56 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -754,13 +754,16 @@ sub parse_diff_header {
754754
my $head = { TEXT => [], DISPLAY => [], TYPE => 'header' };
755755
my $mode = { TEXT => [], DISPLAY => [], TYPE => 'mode' };
756756
my $deletion = { TEXT => [], DISPLAY => [], TYPE => 'deletion' };
757-
my $addition = { TEXT => [], DISPLAY => [], TYPE => 'addition' };
757+
my $addition;
758758

759759
for (my $i = 0; $i < @{$src->{TEXT}}; $i++) {
760+
if ($src->{TEXT}->[$i] =~ /^new file/) {
761+
$addition = 1;
762+
$head->{TYPE} = 'addition';
763+
}
760764
my $dest =
761765
$src->{TEXT}->[$i] =~ /^(old|new) mode (\d+)$/ ? $mode :
762766
$src->{TEXT}->[$i] =~ /^deleted file/ ? $deletion :
763-
$src->{TEXT}->[$i] =~ /^new file/ ? $addition :
764767
$head;
765768
push @{$dest->{TEXT}}, $src->{TEXT}->[$i];
766769
push @{$dest->{DISPLAY}}, $src->{DISPLAY}->[$i];
@@ -1501,12 +1504,6 @@ sub patch_update_file {
15011504
push @{$deletion->{DISPLAY}}, @{$hunk->{DISPLAY}};
15021505
}
15031506
@hunk = ($deletion);
1504-
} elsif (@{$addition->{TEXT}}) {
1505-
foreach my $hunk (@hunk) {
1506-
push @{$addition->{TEXT}}, @{$hunk->{TEXT}};
1507-
push @{$addition->{DISPLAY}}, @{$hunk->{DISPLAY}};
1508-
}
1509-
@hunk = ($addition);
15101507
}
15111508

15121509
$num = scalar @hunk;
@@ -1516,6 +1513,7 @@ sub patch_update_file {
15161513
my ($prev, $next, $other, $undecided, $i);
15171514
$other = '';
15181515

1516+
last if ($ix and !$num);
15191517
if ($num <= $ix) {
15201518
$ix = 0;
15211519
}
@@ -1548,35 +1546,51 @@ sub patch_update_file {
15481546
last;
15491547
}
15501548
}
1551-
last if (!$undecided);
1549+
last if (!$undecided && ($num || !$addition));
15521550

1553-
if ($hunk[$ix]{TYPE} eq 'hunk' &&
1554-
hunk_splittable($hunk[$ix]{TEXT})) {
1555-
$other .= ',s';
1556-
}
1557-
if ($hunk[$ix]{TYPE} eq 'hunk') {
1558-
$other .= ',e';
1559-
}
1560-
for (@{$hunk[$ix]{DISPLAY}}) {
1561-
print;
1551+
if ($num) {
1552+
if ($hunk[$ix]{TYPE} eq 'hunk' &&
1553+
hunk_splittable($hunk[$ix]{TEXT})) {
1554+
$other .= ',s';
1555+
}
1556+
if ($hunk[$ix]{TYPE} eq 'hunk') {
1557+
$other .= ',e';
1558+
}
1559+
for (@{$hunk[$ix]{DISPLAY}}) {
1560+
print;
1561+
}
15621562
}
1563-
print colored $prompt_color, "(", ($ix+1), "/$num) ",
1564-
sprintf(__($patch_update_prompt_modes{$patch_mode}{$hunk[$ix]{TYPE}}), $other);
1563+
my $type = $num ? $hunk[$ix]{TYPE} : $head->{TYPE};
1564+
print colored $prompt_color, "(", ($ix+1), "/", ($num ? $num : 1), ") ",
1565+
sprintf(__($patch_update_prompt_modes{$patch_mode}{$type}), $other);
15651566

15661567
my $line = prompt_single_character;
15671568
last unless defined $line;
15681569
if ($line) {
15691570
if ($line =~ /^y/i) {
1570-
$hunk[$ix]{USE} = 1;
1571+
if ($num) {
1572+
$hunk[$ix]{USE} = 1;
1573+
} else {
1574+
$head->{USE} = 1;
1575+
}
15711576
}
15721577
elsif ($line =~ /^n/i) {
1573-
$hunk[$ix]{USE} = 0;
1578+
if ($num) {
1579+
$hunk[$ix]{USE} = 0;
1580+
} else {
1581+
$head->{USE} = 0;
1582+
}
15741583
}
15751584
elsif ($line =~ /^a/i) {
1576-
while ($ix < $num) {
1577-
if (!defined $hunk[$ix]{USE}) {
1578-
$hunk[$ix]{USE} = 1;
1585+
if ($num) {
1586+
while ($ix < $num) {
1587+
if (!defined $hunk[$ix]{USE}) {
1588+
$hunk[$ix]{USE} = 1;
1589+
}
1590+
$ix++;
15791591
}
1592+
} else {
1593+
$head->{USE} = 1;
15801594
$ix++;
15811595
}
15821596
next;
@@ -1613,19 +1627,28 @@ sub patch_update_file {
16131627
next;
16141628
}
16151629
elsif ($line =~ /^d/i) {
1616-
while ($ix < $num) {
1617-
if (!defined $hunk[$ix]{USE}) {
1618-
$hunk[$ix]{USE} = 0;
1630+
if ($num) {
1631+
while ($ix < $num) {
1632+
if (!defined $hunk[$ix]{USE}) {
1633+
$hunk[$ix]{USE} = 0;
1634+
}
1635+
$ix++;
16191636
}
1637+
} else {
1638+
$head->{USE} = 0;
16201639
$ix++;
16211640
}
16221641
next;
16231642
}
16241643
elsif ($line =~ /^q/i) {
1625-
for ($i = 0; $i < $num; $i++) {
1626-
if (!defined $hunk[$i]{USE}) {
1627-
$hunk[$i]{USE} = 0;
1644+
if ($num) {
1645+
for ($i = 0; $i < $num; $i++) {
1646+
if (!defined $hunk[$i]{USE}) {
1647+
$hunk[$i]{USE} = 0;
1648+
}
16281649
}
1650+
} elsif (!defined $head->{USE}) {
1651+
$head->{USE} = 0;
16291652
}
16301653
$quit = 1;
16311654
last;
@@ -1743,7 +1766,7 @@ sub patch_update_file {
17431766
}
17441767
}
17451768

1746-
@hunk = coalesce_overlapping_hunks(@hunk);
1769+
@hunk = coalesce_overlapping_hunks(@hunk) if ($num);
17471770

17481771
my $n_lofs = 0;
17491772
my @result = ();
@@ -1753,7 +1776,7 @@ sub patch_update_file {
17531776
}
17541777
}
17551778

1756-
if (@result) {
1779+
if (@result or $head->{USE}) {
17571780
my @patch = reassemble_patch($head->{TEXT}, @result);
17581781
my $apply_routine = $patch_mode_flavour{APPLY};
17591782
&$apply_routine(@patch);

0 commit comments

Comments
 (0)