add-interactive: handle deletion of empty files

Usually we show deletion as a big hunk deleting all of the
file's text. However, for files with no content, the diff
shows just the 'deleted file mode ...' line. This patch
cause "add -p" (and related commands) to recognize that line
and explicitly ask about deleting the file.

We only add the "stage this deletion" hunk for empty files,
since other files will already ask about the big content
deletion hunk. We could also change those files to simply
display "stage this deletion", but showing the actual
deleted content is probably what an interactive user wants.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff King 2009-10-27 20:52:57 -04:00 коммит произвёл Junio C Hamano
Родитель 78d553b7d7
Коммит 24ab81ae4d
2 изменённых файлов: 30 добавлений и 5 удалений

Просмотреть файл

@ -731,14 +731,17 @@ sub parse_diff_header {
my $head = { TEXT => [], DISPLAY => [], TYPE => 'header' }; my $head = { TEXT => [], DISPLAY => [], TYPE => 'header' };
my $mode = { TEXT => [], DISPLAY => [], TYPE => 'mode' }; my $mode = { TEXT => [], DISPLAY => [], TYPE => 'mode' };
my $deletion = { TEXT => [], DISPLAY => [], TYPE => 'deletion' };
for (my $i = 0; $i < @{$src->{TEXT}}; $i++) { for (my $i = 0; $i < @{$src->{TEXT}}; $i++) {
my $dest = $src->{TEXT}->[$i] =~ /^(old|new) mode (\d+)$/ ? my $dest =
$mode : $head; $src->{TEXT}->[$i] =~ /^(old|new) mode (\d+)$/ ? $mode :
$src->{TEXT}->[$i] =~ /^deleted file/ ? $deletion :
$head;
push @{$dest->{TEXT}}, $src->{TEXT}->[$i]; push @{$dest->{TEXT}}, $src->{TEXT}->[$i];
push @{$dest->{DISPLAY}}, $src->{DISPLAY}->[$i]; push @{$dest->{DISPLAY}}, $src->{DISPLAY}->[$i];
} }
return ($head, $mode); return ($head, $mode, $deletion);
} }
sub hunk_splittable { sub hunk_splittable {
@ -1206,7 +1209,7 @@ sub patch_update_file {
my ($ix, $num); my ($ix, $num);
my $path = shift; my $path = shift;
my ($head, @hunk) = parse_diff($path); my ($head, @hunk) = parse_diff($path);
($head, my $mode) = parse_diff_header($head); ($head, my $mode, my $deletion) = parse_diff_header($head);
for (@{$head->{DISPLAY}}) { for (@{$head->{DISPLAY}}) {
print; print;
} }
@ -1214,6 +1217,9 @@ sub patch_update_file {
if (@{$mode->{TEXT}}) { if (@{$mode->{TEXT}}) {
unshift @hunk, $mode; unshift @hunk, $mode;
} }
if (@{$deletion->{TEXT}} && !@hunk) {
@hunk = ($deletion);
}
$num = scalar @hunk; $num = scalar @hunk;
$ix = 0; $ix = 0;
@ -1267,7 +1273,9 @@ sub patch_update_file {
print; print;
} }
print colored $prompt_color, $patch_mode_flavour{VERB}, print colored $prompt_color, $patch_mode_flavour{VERB},
($hunk[$ix]{TYPE} eq 'mode' ? ' mode change' : ' this hunk'), ($hunk[$ix]{TYPE} eq 'mode' ? ' mode change' :
$hunk[$ix]{TYPE} eq 'deletion' ? ' deletion' :
' this hunk'),
$patch_mode_flavour{TARGET}, $patch_mode_flavour{TARGET},
" [y,n,q,a,d,/$other,?]? "; " [y,n,q,a,d,/$other,?]? ";
my $line = prompt_single_character; my $line = prompt_single_character;

Просмотреть файл

@ -214,4 +214,21 @@ test_expect_success 'add first line works' '
test_cmp expected diff test_cmp expected diff
' '
cat >expected <<EOF
diff --git a/empty b/empty
deleted file mode 100644
index e69de29..0000000
EOF
test_expect_success 'deleting an empty file' '
git reset --hard &&
> empty &&
git add empty &&
git commit -m empty &&
rm empty &&
echo y | git add -p empty &&
git diff --cached >diff &&
test_cmp expected diff
'
test_done test_done