@matheusbsbs / matheus-bagliano / commits / 0392513fdc
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 0392513fdc7e98f5ca5dff1ad80962c28029267b
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,
@@ -873,7 +875,11 @@ sub edit_hunk_loop {
875 if (!defined $text) {
876 return undef;
877 }
876 - my $newhunk = { TEXT => $text, USE => 1 };
878 + my $newhunk = {
879 + TEXT => $text,
880 + TYPE => $hunk->[$ix]->{TYPE},
881 + USE => 1
882 + };
883 if (diff_applies($head,
884 @{$hunk}[0..$ix-1],
885 $newhunk,
@@ -987,37 +993,7 @@ sub patch_update_file {
993 }
994
995 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;
997 }
998
999 $num = scalar @hunk;
@@ -1061,14 +1037,19 @@ sub patch_update_file {
1037 }
1038 last if (!$undecided);
1039
1064 - if (hunk_splittable($hunk[$ix]{TEXT})) {
1040 + if ($hunk[$ix]{TYPE} eq 'hunk' &&
1041 + hunk_splittable($hunk[$ix]{TEXT})) {
1042 $other .= ',s';
1043 }
1067 - $other .= ',e';
1044 + if ($hunk[$ix]{TYPE} eq 'hunk') {
1045 + $other .= ',e';
1046 + }
1047 for (@{$hunk[$ix]{DISPLAY}}) {
1048 print;
1049 }
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,?]? ";
1053 my $line = prompt_single_character;
1054 if ($line) {
1055 if ($line =~ /^y/i) {
@@ -1210,7 +1191,7 @@ sub patch_update_file {
1191 $num = scalar @hunk;
1192 next;
1193 }
1213 - elsif ($line =~ /^e/) {
1194 + elsif ($other =~ /e/ && $line =~ /^e/) {
1195 my $newhunk = edit_hunk_loop($head, \@hunk, $ix);
1196 if (defined $newhunk) {
1197 splice @hunk, $ix, 1, $newhunk;
@@ -1231,9 +1212,6 @@ sub patch_update_file {
1212
1213 my $n_lofs = 0;
1214 my @result = ();
1234 - if ($mode->{USE}) {
1235 - push @result, @{$mode->{TEXT}};
1236 - }
1215 for (@hunk) {
1216 if ($_->{USE}) {
1217 push @result, @{$_->{TEXT}};