From b717a627629e6886956af54274d507b9711d49e6 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 27 Mar 2008 03:30:43 -0400 Subject: add--interactive: ignore mode change in 'p'atch command When a path is examined in the patch subcommand, any mode changes in the file are given to use in the diff header by git-diff. If no hunks are staged, then we throw out that header and do not touch the path. But if _any_ hunks are staged, we use the header, and the mode is changed together with the contents. Since the 'p'atch command should just be dealing with hunks that are shown to the user, it makes sense to just ignore mode changes entirely. We do squirrel away the mode, though, since the next patch will allow users to select the mode update separately. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- git-add--interactive.perl | 16 ++++++++++++++++ t/t3701-add-interactive.sh | 9 +++++++++ 2 files changed, 25 insertions(+) diff --git a/git-add--interactive.perl b/git-add--interactive.perl index a0a81f134..5cdda29c5 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -550,6 +550,21 @@ sub parse_diff { return @hunk; } +sub parse_diff_header { + my $src = shift; + + my $head = { TEXT => [], DISPLAY => [] }; + my $mode = { TEXT => [], DISPLAY => [] }; + + for (my $i = 0; $i < @{$src->{TEXT}}; $i++) { + my $dest = $src->{TEXT}->[$i] =~ /^(old|new) mode (\d+)$/ ? + $mode : $head; + push @{$dest->{TEXT}}, $src->{TEXT}->[$i]; + push @{$dest->{DISPLAY}}, $src->{DISPLAY}->[$i]; + } + return ($head, $mode); +} + sub hunk_splittable { my ($text) = @_; @@ -795,6 +810,7 @@ sub patch_update_file { my ($ix, $num); my $path = shift; my ($head, @hunk) = parse_diff($path); + ($head, my $mode) = parse_diff_header($head); for (@{$head->{DISPLAY}}) { print; } diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 77c90f6fa..d920d06d5 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -66,4 +66,13 @@ test_expect_success 'revert works (commit)' ' grep "unchanged *+3/-0 file" output ' +test_expect_success 'patch does not affect mode' ' + git reset --hard && + echo content >>file && + chmod +x file && + printf "y\\n" | git add -p && + git show :file | grep content && + git diff file | grep "new mode" +' + test_done -- cgit v1.2.1 From ca7246864b43e9ea1922cc5386225ecd1b3bdd98 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 27 Mar 2008 03:32:25 -0400 Subject: add--interactive: allow user to choose mode update When using the 'p'atch command, instead of just throwing out any mode change, present it to the user in the same way that we show hunks. This way, the mode change can be staged independently from the changes to the contents. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- git-add--interactive.perl | 33 +++++++++++++++++++++++++++++++++ t/t3701-add-interactive.sh | 12 +++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/git-add--interactive.perl b/git-add--interactive.perl index 5cdda29c5..903953e68 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -814,6 +814,36 @@ sub patch_update_file { for (@{$head->{DISPLAY}}) { print; } + + if (@{$mode->{TEXT}}) { + while (1) { + print @{$mode->{DISPLAY}}; + print colored $prompt_color, + "Stage mode change [y/n/a/d/?]? "; + my $line = ; + if ($line =~ /^y/i) { + $mode->{USE} = 1; + last; + } + elsif ($line =~ /^n/i) { + $mode->{USE} = 0; + last; + } + elsif ($line =~ /^a/i) { + $_->{USE} = 1 foreach ($mode, @hunk); + last; + } + elsif ($line =~ /^d/i) { + $_->{USE} = 0 foreach ($mode, @hunk); + last; + } + else { + help_patch_cmd(''); + next; + } + } + } + $num = scalar @hunk; $ix = 0; @@ -936,6 +966,9 @@ sub patch_update_file { my $n_lofs = 0; my @result = (); + if ($mode->{USE}) { + push @result, @{$mode->{TEXT}}; + } for (@hunk) { my $text = $_->{TEXT}; my ($o_ofs, $o_cnt, $n_ofs, $n_cnt) = diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index d920d06d5..f15be93e7 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -70,9 +70,19 @@ test_expect_success 'patch does not affect mode' ' git reset --hard && echo content >>file && chmod +x file && - printf "y\\n" | git add -p && + printf "n\\ny\\n" | git add -p && git show :file | grep content && git diff file | grep "new mode" ' +test_expect_success 'stage mode but not hunk' ' + git reset --hard && + echo content >>file && + chmod +x file && + printf "y\\nn\\n" | git add -p && + git diff --cached file | grep "new mode" && + git diff file | grep "+content" +' + + test_done -- cgit v1.2.1