@matheusbsbs / matheus-bagliano / commits / 7535e5a16a
Fork 0

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>

Jeff King committed Apr 16, 2009 at 03:14 UTC 7535e5a16aa7167074ac74ee1342814767a83a82
1 file changed +21 -43
git-add--interactive.perl
+21 -43
@@ -620,11 +620,12 @@ sub parse_diff {
620 if ($diff_use_color) {
621 @colored = run_cmd_pipe(qw(git diff-files -p --color --), $path);
622 }
623 - my (@hunk) = { TEXT => [], DISPLAY => [] };
623 + my (@hunk) = { TEXT => [], DISPLAY => [], TYPE => 'header' };
624
625 for (my $i = 0; $i < @diff; $i++) {
626 if ($diff[$i] =~ /^@@ /) {
627 - push @hunk, { TEXT => [], DISPLAY => [] };
627 + push @hunk, { TEXT => [], DISPLAY => [],
628 + TYPE => 'hunk' };
629 }
630 push @{$hunk[-1]{TEXT}}, $diff[$i];
631 push @{$hunk[-1]{DISPLAY}},
@@ -636,8 +637,8 @@ sub parse_diff {
637 sub parse_diff_header {
638 my $src = shift;
639
639 - my $head = { TEXT => [], DISPLAY => [] };
640 - my $mode = { TEXT => [], DISPLAY => [] };
640 + my $head = { TEXT => [], DISPLAY => [], TYPE => 'header' };
641 + my $mode = { TEXT => [], DISPLAY => [], TYPE => 'mode' };
642
643 for (my $i = 0; $i < @{$src->{TEXT}}; $i++) {
644 my $dest = $src->{TEXT}->[$i] =~ /^(old|new) mode (\d+)$/ ?
@@ -684,6 +685,7 @@ sub split_hunk {
685 my $this = +{
686 TEXT => [],
687 DISPLAY => [],
688 + TYPE => 'hunk',
689 OLD => $o_ofs,
690 NEW => $n_ofs,
691 OCNT => 0,
@@ -869,7 +871,11 @@ sub edit_hunk_loop {
871 if (!defined $text) {
872 return undef;
873 }
872 - my $newhunk = { TEXT => $text, USE => 1 };
874 + my $newhunk = {
875 + TEXT => $text,
876 + TYPE => $hunk->[$ix]->{TYPE},
877 + USE => 1
878 + };
879 if (diff_applies($head,
880 @{$hunk}[0..$ix-1],
881 $newhunk,
@@ -983,37 +989,7 @@ sub patch_update_file {
989 }
990
991 if (@{$mode->{TEXT}}) {
986 - while (1) {
987 - print @{$mode->{DISPLAY}};
988 - print colored $prompt_color,
989 - "Stage mode change [y/n/a/d/?]? ";
990 - my $line = prompt_single_character;
991 - if ($line =~ /^y/i) {
992 - $mode->{USE} = 1;
993 - last;
994 - }
995 - elsif ($line =~ /^n/i) {
996 - $mode->{USE} = 0;
997 - last;
998 - }
999 - elsif ($line =~ /^a/i) {
1000 - $_->{USE} = 1 foreach ($mode, @hunk);
1001 - last;
1002 - }
1003 - elsif ($line =~ /^d/i) {
1004 - $_->{USE} = 0 foreach ($mode, @hunk);
1005 - last;
1006 - }
1007 - elsif ($line =~ /^q/i) {
1008 - $_->{USE} = 0 foreach ($mode, @hunk);
1009 - $quit = 1;
1010 - last;
1011 - }
1012 - else {
1013 - help_patch_cmd('');
1014 - next;
1015 - }
1016 - }
992 + unshift @hunk, $mode;
993 }
994
995 $num = scalar @hunk;
@@ -1057,14 +1033,19 @@ sub patch_update_file {
1033 }
1034 last if (!$undecided);
1035
1060 - if (hunk_splittable($hunk[$ix]{TEXT})) {
1036 + if ($hunk[$ix]{TYPE} eq 'hunk' &&
1037 + hunk_splittable($hunk[$ix]{TEXT})) {
1038 $other .= ',s';
1039 }
1063 - $other .= ',e';
1040 + if ($hunk[$ix]{TYPE} eq 'hunk') {
1041 + $other .= ',e';
1042 + }
1043 for (@{$hunk[$ix]{DISPLAY}}) {
1044 print;
1045 }
1067 - print colored $prompt_color, "Stage this hunk [y,n,a,d,/$other,?]? ";
1046 + print colored $prompt_color, 'Stage ',
1047 + ($hunk[$ix]{TYPE} eq 'mode' ? 'mode change' : 'this hunk'),
1048 + " [y,n,a,d,/$other,?]? ";
1049 my $line = prompt_single_character;
1050 if ($line) {
1051 if ($line =~ /^y/i) {
@@ -1206,7 +1187,7 @@ sub patch_update_file {
1187 $num = scalar @hunk;
1188 next;
1189 }
1209 - elsif ($line =~ /^e/) {
1190 + elsif ($other =~ /e/ && $line =~ /^e/) {
1191 my $newhunk = edit_hunk_loop($head, \@hunk, $ix);
1192 if (defined $newhunk) {
1193 splice @hunk, $ix, 1, $newhunk;
@@ -1227,9 +1208,6 @@ sub patch_update_file {
1208
1209 my $n_lofs = 0;
1210 my @result = ();
1230 - if ($mode->{USE}) {
1231 - push @result, @{$mode->{TEXT}};
1232 - }
1211 for (@hunk) {
1212 if ($_->{USE}) {
1213 push @result, @{$_->{TEXT}};