Skip to content

Commit 0392513

Browse files
peffgitster
authored andcommitted
add-interactive: refactor mode hunk handling
The original implementation considered the mode separately from the rest of the hunks, asking about it outside the main hunk-selection loop. This patch instead places a mode change as the first hunk in the loop. This has two advantages: 1. less duplicated code (since we use the main selection loop). This also cleans up an inconsistency, which is that the main selection loop separates options with a comma, whereas the mode prompt used slashes. 2. users can now skip the mode change and come back to it, search for it (via "/mode"), etc, as they can with other hunks. To facilitate this, each hunk is now marked with a "type". Mode hunks are not considered for splitting (which would make no sense, and also confuses the split_hunk function), nor are they editable. In theory, one could edit the mode lines and change to a new mode. In practice, there are only two modes that git cares about (0644 and 0755), so either you want to move from one to the other or not (and you can do that by staging or not staging). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 9a7a1e0 commit 0392513

File tree

1 file changed

+21
-43
lines changed

1 file changed

+21
-43
lines changed

git-add--interactive.perl

Lines changed: 21 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -620,11 +620,12 @@ sub parse_diff {
620620
if ($diff_use_color) {
621621
@colored = run_cmd_pipe(qw(git diff-files -p --color --), $path);
622622
}
623-
my (@hunk) = { TEXT => [], DISPLAY => [] };
623+
my (@hunk) = { TEXT => [], DISPLAY => [], TYPE => 'header' };
624624

625625
for (my $i = 0; $i < @diff; $i++) {
626626
if ($diff[$i] =~ /^@@ /) {
627-
push @hunk, { TEXT => [], DISPLAY => [] };
627+
push @hunk, { TEXT => [], DISPLAY => [],
628+
TYPE => 'hunk' };
628629
}
629630
push @{$hunk[-1]{TEXT}}, $diff[$i];
630631
push @{$hunk[-1]{DISPLAY}},
@@ -636,8 +637,8 @@ sub parse_diff {
636637
sub parse_diff_header {
637638
my $src = shift;
638639

639-
my $head = { TEXT => [], DISPLAY => [] };
640-
my $mode = { TEXT => [], DISPLAY => [] };
640+
my $head = { TEXT => [], DISPLAY => [], TYPE => 'header' };
641+
my $mode = { TEXT => [], DISPLAY => [], TYPE => 'mode' };
641642

642643
for (my $i = 0; $i < @{$src->{TEXT}}; $i++) {
643644
my $dest = $src->{TEXT}->[$i] =~ /^(old|new) mode (\d+)$/ ?
@@ -684,6 +685,7 @@ sub split_hunk {
684685
my $this = +{
685686
TEXT => [],
686687
DISPLAY => [],
688+
TYPE => 'hunk',
687689
OLD => $o_ofs,
688690
NEW => $n_ofs,
689691
OCNT => 0,
@@ -873,7 +875,11 @@ sub edit_hunk_loop {
873875
if (!defined $text) {
874876
return undef;
875877
}
876-
my $newhunk = { TEXT => $text, USE => 1 };
878+
my $newhunk = {
879+
TEXT => $text,
880+
TYPE => $hunk->[$ix]->{TYPE},
881+
USE => 1
882+
};
877883
if (diff_applies($head,
878884
@{$hunk}[0..$ix-1],
879885
$newhunk,
@@ -987,37 +993,7 @@ sub patch_update_file {
987993
}
988994

989995
if (@{$mode->{TEXT}}) {
990-
while (1) {
991-
print @{$mode->{DISPLAY}};
992-
print colored $prompt_color,
993-
"Stage mode change [y/n/a/d/?]? ";
994-
my $line = prompt_single_character;
995-
if ($line =~ /^y/i) {
996-
$mode->{USE} = 1;
997-
last;
998-
}
999-
elsif ($line =~ /^n/i) {
1000-
$mode->{USE} = 0;
1001-
last;
1002-
}
1003-
elsif ($line =~ /^a/i) {
1004-
$_->{USE} = 1 foreach ($mode, @hunk);
1005-
last;
1006-
}
1007-
elsif ($line =~ /^d/i) {
1008-
$_->{USE} = 0 foreach ($mode, @hunk);
1009-
last;
1010-
}
1011-
elsif ($line =~ /^q/i) {
1012-
$_->{USE} = 0 foreach ($mode, @hunk);
1013-
$quit = 1;
1014-
last;
1015-
}
1016-
else {
1017-
help_patch_cmd('');
1018-
next;
1019-
}
1020-
}
996+
unshift @hunk, $mode;
1021997
}
1022998

1023999
$num = scalar @hunk;
@@ -1061,14 +1037,19 @@ sub patch_update_file {
10611037
}
10621038
last if (!$undecided);
10631039

1064-
if (hunk_splittable($hunk[$ix]{TEXT})) {
1040+
if ($hunk[$ix]{TYPE} eq 'hunk' &&
1041+
hunk_splittable($hunk[$ix]{TEXT})) {
10651042
$other .= ',s';
10661043
}
1067-
$other .= ',e';
1044+
if ($hunk[$ix]{TYPE} eq 'hunk') {
1045+
$other .= ',e';
1046+
}
10681047
for (@{$hunk[$ix]{DISPLAY}}) {
10691048
print;
10701049
}
1071-
print colored $prompt_color, "Stage this hunk [y,n,a,d,/$other,?]? ";
1050+
print colored $prompt_color, 'Stage ',
1051+
($hunk[$ix]{TYPE} eq 'mode' ? 'mode change' : 'this hunk'),
1052+
" [y,n,a,d,/$other,?]? ";
10721053
my $line = prompt_single_character;
10731054
if ($line) {
10741055
if ($line =~ /^y/i) {
@@ -1210,7 +1191,7 @@ sub patch_update_file {
12101191
$num = scalar @hunk;
12111192
next;
12121193
}
1213-
elsif ($line =~ /^e/) {
1194+
elsif ($other =~ /e/ && $line =~ /^e/) {
12141195
my $newhunk = edit_hunk_loop($head, \@hunk, $ix);
12151196
if (defined $newhunk) {
12161197
splice @hunk, $ix, 1, $newhunk;
@@ -1231,9 +1212,6 @@ sub patch_update_file {
12311212

12321213
my $n_lofs = 0;
12331214
my @result = ();
1234-
if ($mode->{USE}) {
1235-
push @result, @{$mode->{TEXT}};
1236-
}
12371215
for (@hunk) {
12381216
if ($_->{USE}) {
12391217
push @result, @{$_->{TEXT}};

0 commit comments

Comments
 (0)