* git-apply fails on creating a new file, with both -p and --directory specified @ 2009-11-23 19:45 Steven J. Murdoch 2009-11-25 10:56 ` Junio C Hamano 0 siblings, 1 reply; 16+ messages in thread From: Steven J. Murdoch @ 2009-11-23 19:45 UTC (permalink / raw) To: git While trying to apply a patch from one repository (created by git-format-patch), to another (using git-am), git fails with: "fatal: git apply: bad git-diff - inconsistent new filename on line X" This appears to be because I was both using -p to strip some path components, and --directory to add different ones in. Only creating new files was affected. This was the case in git 1.6.5.2, and also the development version 1.6.6.rc0.15.g4fa80. I have tested this on MacOS X Snow Leopard. This appears related to the bug discussed in: http://marc.info/?l=git&m=122237537312597&w=2 in which the following fix was posted: http://git.kernel.org/?p=git/git.git;a=commitdiff;h=969c877506cf8cc760c7b251fef6c5b6850bfc19 I have included a patch below to the test cases, which currently fails but, if I understand correctly, should succeed. Steven Murdoch. -- >8 -- Test git-apply creating a new file, combining --directory and -p flags Signed-off-by: Steven Murdoch <Steven.Murdoch@cl.cam.ac.uk> --- t/t4128-apply-root.sh | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-) diff --git a/t/t4128-apply-root.sh b/t/t4128-apply-root.sh index 8f6aea4..6cc741a 100755 --- a/t/t4128-apply-root.sh +++ b/t/t4128-apply-root.sh @@ -58,6 +58,23 @@ test_expect_success 'apply --directory (new file)' ' ' cat > patch << EOF +diff --git a/c/newfile2 b/c/newfile2 +new file mode 100644 +index 0000000..d95f3ad +--- /dev/null ++++ b/c/newfile2 +@@ -0,0 +1 @@ ++content +EOF + +test_expect_success 'apply --directory -p (new file)' ' + git reset --hard initial && + git apply -p2 --directory=some/sub/dir/ --index patch && + test content = $(git show :some/sub/dir/newfile2) && + test content = $(cat some/sub/dir/newfile2) +' + +cat > patch << EOF diff --git a/delfile b/delfile deleted file mode 100644 index d95f3ad..0000000 -- 1.6.5.2 -- http://www.cl.cam.ac.uk/users/sjm217/ ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2009-11-23 19:45 git-apply fails on creating a new file, with both -p and --directory specified Steven J. Murdoch @ 2009-11-25 10:56 ` Junio C Hamano 2009-12-07 21:35 ` James Vega 0 siblings, 1 reply; 16+ messages in thread From: Junio C Hamano @ 2009-11-25 10:56 UTC (permalink / raw) To: Steven J. Murdoch; +Cc: git "Steven J. Murdoch" <git+Steven.Murdoch@cl.cam.ac.uk> writes: > This appears to be because I was both using -p to strip some path > components, and --directory to add different ones in. Only creating > new files was affected. A very nicely done report. In addition to your test case, I suspect that a patch that only changes mode would have acted funny with -p<n> option. -- >8 -- [PATCH] builtin-apply.c: pay attention to -p<n> when determining the name The patch structure has def_name component that is used to validate the sanity of a "diff --git" patch by checking pathnames that appear on the patch header lines for consistency. The git_header_name() function is used to compute this out of "diff --git a/... b/..." line, but the code always stripped one level of prefix (i.e. "a/" and "b/"), without paying attention to -p<n> option. Code in find_name() function that parses other lines in the patch header (e.g. "--- a/..." and "+++ b/..." lines) however did strip the correct number of leading paths prefixes, and the sanity check between these computed values failed. Teach git_header_name() to honor -p<n> option like find_name() function does. Signed-off-by: Junio C Hamano <gitster@pobox.com> --- builtin-apply.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/builtin-apply.c b/builtin-apply.c index f667368..36e2f9d 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -823,12 +823,13 @@ static int gitdiff_unrecognized(const char *line, struct patch *patch) static const char *stop_at_slash(const char *line, int llen) { + int nslash = p_value; int i; for (i = 0; i < llen; i++) { int ch = line[i]; - if (ch == '/') - return line + i; + if (ch == '/' && --nslash <= 0) + return &line[i]; } return NULL; } ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2009-11-25 10:56 ` Junio C Hamano @ 2009-12-07 21:35 ` James Vega 2009-12-08 2:59 ` Junio C Hamano 0 siblings, 1 reply; 16+ messages in thread From: James Vega @ 2009-12-07 21:35 UTC (permalink / raw) To: git Junio C Hamano <gitster <at> pobox.com> writes: > > "Steven J. Murdoch" <git+Steven.Murdoch <at> cl.cam.ac.uk> writes: > > > This appears to be because I was both using -p to strip some path > > components, and --directory to add different ones in. Only creating > > new files was affected. > > A very nicely done report. > > In addition to your test case, I suspect that a patch that only changes > mode would have acted funny with -p<n> option. > It looks like this may have introduced a bug when staging a file removal. Here's an example git session showing the issue: $ git init test Initialized empty Git repository in /local_disk/tmp/test/.git/ $ cd test $ echo "foo" > foo $ git add foo $ git commit -m 'Add foo' [master (root-commit) 3643b5d] Add foo 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 foo $ mv foo bar $ git add -p diff --git a/foo b/foo index 257cc56..0000000 --- a/foo +++ /dev/null @@ -1 +0,0 @@ -foo Stage this hunk [y,n,q,a,d,/,e,?]? y $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: dev/null # deleted: foo # # Changed but not updated: # (use "git add/rm ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # deleted: dev/null # # Untracked files: # (use "git add ..." to include in what will be committed) # # bar Replacing the 'git add -p' with git diff | sed '/^deleted file/d' | git apply --cached also exhibits the problem. ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2009-12-07 21:35 ` James Vega @ 2009-12-08 2:59 ` Junio C Hamano 2009-12-08 3:20 ` Junio C Hamano 2009-12-08 3:39 ` James Vega 0 siblings, 2 replies; 16+ messages in thread From: Junio C Hamano @ 2009-12-08 2:59 UTC (permalink / raw) To: James Vega; +Cc: git James Vega <vega.james@gmail.com> writes: > It looks like this may have introduced a bug when staging a file > removal. Here's an example git session showing the issue: > <<snipped>> Thanks for a report, but I cannot get the evidence that the said patch has anything to do with the issue you illustrated. $ cat >patch0 <<\EOF diff --git a/foo b/foo deleted file mode 100644 index 257cc56..0000000 --- a/foo +++ /dev/null @@ -1 +0,0 @@ -foo EOF $ git apply --numstat patch0 0 1 foo $ sed -e '/deleted file/d' patch0 | git apply --numstat 0 1 dev/null The last one is showing the symptom in your message. Git versions 1.4.0 and newer yield the same result, but 1.3.0 gives a funny message: ** warning: file dev/null becomes empty but is not deleted 0 1 foo So it appears that the bug is somewhere else not in that patch. ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2009-12-08 2:59 ` Junio C Hamano @ 2009-12-08 3:20 ` Junio C Hamano 2009-12-08 5:47 ` Jeff King 2009-12-08 3:39 ` James Vega 1 sibling, 1 reply; 16+ messages in thread From: Junio C Hamano @ 2009-12-08 3:20 UTC (permalink / raw) To: James Vega; +Cc: git, Jeff King Junio C Hamano <gitster@pobox.com> writes: > James Vega <vega.james@gmail.com> writes: > >> It looks like this may have introduced a bug when staging a file >> removal. Here's an example git session showing the issue: An update. I tried your reproduction recipe with 1.6.5.2 and it doesn't reproduce, but with 1.6.5.3 it does. $ git init test Initialized empty Git repository in /local_disk/tmp/test/.git/ $ cd test $ echo "foo" > foo $ git add foo $ git commit -m 'Add foo' [master (root-commit) 3643b5d] Add foo 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 foo $ mv foo bar $ git add -p diff --git a/foo b/foo index 257cc56..0000000 --- a/foo +++ /dev/null @@ -1 +0,0 @@ -foo Stage this hunk [y,n,q,a,d,/,e,?]? y $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: dev/null # deleted: foo # A quick bisection of the original issue points at 24ab81a (add-interactive: handle deletion of empty files, 2009-10-27) ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2009-12-08 3:20 ` Junio C Hamano @ 2009-12-08 5:47 ` Jeff King 2009-12-08 6:01 ` Jeff King 2009-12-08 7:11 ` Junio C Hamano 0 siblings, 2 replies; 16+ messages in thread From: Jeff King @ 2009-12-08 5:47 UTC (permalink / raw) To: Junio C Hamano; +Cc: James Vega, git On Mon, Dec 07, 2009 at 07:20:30PM -0800, Junio C Hamano wrote: > An update. I tried your reproduction recipe with 1.6.5.2 and it doesn't > reproduce, but with 1.6.5.3 it does. Thanks, both, for a very helpful bug report. 24ab81a was totally bogus, but we lacked a test for deleting a non-empty file. That test and a fix for the problem are in the patch below. I am still slightly concerned that James's git diff | sed '/^deleted file/d' | git apply --cached behaves as it does. What should git-apply do with a patch like: diff --git a/foo b/foo index 257cc56..0000000 --- a/foo +++ /dev/null @@ -1 +0,0 @@ -foo ? I can see either turning it into a deletion patch (because /dev/null is special) or barfing (because /dev/null as a special case should have appeared in the "diff" line). But creating a dev/null file seems very wrong. But maybe it is not worth worrying about too much. That patch format is not generated intentionally by any known software. Here is the fix directly on top of 24ab81a. -- >8 -- Subject: [PATCH] add-interactive: fix deletion of non-empty files Commit 24ab81a fixed the deletion of empty files, but broke deletion of non-empty files. The approach it took was to factor out the "deleted" line from the patch header into its own hunk, the same way we do for mode changes. However, unlike mode changes, we only showed the special "delete this file" hunk if there were no other hunks. Otherwise, the user would annoyingly be presented with _two_ hunks: one for deleting the file and one for deleting the content. Instead, this patch takes a separate approach. We leave the deletion line in the header, so it will be used as usual by non-empty files if their deletion hunk is staged. For empty files, we create a deletion hunk with no content; it doesn't add anything to the patch, but by staging it we trigger the application of the header, which does contain the deletion. Signed-off-by: Jeff King <peff@peff.net> --- There is a slightly different approach we could take, too: keep the "deletion" hunk as a first-class hunk, and just meld the content hunk's output into it. Then both cases would get the "Stage deletion" question instead of the "Stage this hunk" you get now for non-empty files (which just happens to trigger a deletion due to the headers). That would take some refactoring, though, as pulling the deletion hunk out means we are re-ordering the headers. So right now if you did that your ($head, @hunk) output would be something like: diff --git a/foo b/foo index 257cc56..0000000 --- a/foo +++ /dev/null deleted file mode 100644 @@ -1 +0,0 @@ -foo which is pretty weird. On the other hand, we already do that funny ordering for mode hunks, and git-apply is just fine with it. A mode hunk with content change looks like this: diff --git a/foo b/foo index 257cc56..19c6cc1 --- a/foo +++ b/foo old mode 100644 new mode 100755 And it also opens the door to editing the hunk to stop the deletion, but still tweak the content change. Right now if you edit a deletion patch, you can't remove the 'deleted' bit, and if your edit result keeps any content in the file, apply will complain. I'm not sure that particular feature would be useful though (I have certainly never wanted it). git-add--interactive.perl | 18 +++++++++++------- t/t3701-add-interactive.sh | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/git-add--interactive.perl b/git-add--interactive.perl index 35f4ef1..f4b95b1 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -731,17 +731,19 @@ sub parse_diff_header { my $head = { TEXT => [], DISPLAY => [], TYPE => 'header' }; my $mode = { TEXT => [], DISPLAY => [], TYPE => 'mode' }; - my $deletion = { TEXT => [], DISPLAY => [], TYPE => 'deletion' }; + my $is_deletion; for (my $i = 0; $i < @{$src->{TEXT}}; $i++) { my $dest = $src->{TEXT}->[$i] =~ /^(old|new) mode (\d+)$/ ? $mode : - $src->{TEXT}->[$i] =~ /^deleted file/ ? $deletion : $head; push @{$dest->{TEXT}}, $src->{TEXT}->[$i]; push @{$dest->{DISPLAY}}, $src->{DISPLAY}->[$i]; + if ($src->{TEXT}->[$i] =~ /^deleted file/) { + $is_deletion = 1; + } } - return ($head, $mode, $deletion); + return ($head, $mode, $is_deletion); } sub hunk_splittable { @@ -1209,7 +1211,7 @@ sub patch_update_file { my ($ix, $num); my $path = shift; my ($head, @hunk) = parse_diff($path); - ($head, my $mode, my $deletion) = parse_diff_header($head); + ($head, my $mode, my $is_deletion) = parse_diff_header($head); for (@{$head->{DISPLAY}}) { print; } @@ -1217,8 +1219,8 @@ sub patch_update_file { if (@{$mode->{TEXT}}) { unshift @hunk, $mode; } - if (@{$deletion->{TEXT}} && !@hunk) { - @hunk = ($deletion); + if ($is_deletion && !@hunk) { + @hunk = ({TEXT => [], DISPLAY => [], TYPE => 'deletion'}); } $num = scalar @hunk; @@ -1441,14 +1443,16 @@ sub patch_update_file { @hunk = coalesce_overlapping_hunks(@hunk); my $n_lofs = 0; + my $hunks_used = 0; my @result = (); for (@hunk) { if ($_->{USE}) { push @result, @{$_->{TEXT}}; + $hunks_used++; } } - if (@result) { + if ($hunks_used) { my $fh; my @patch = (@{$head->{TEXT}}, @result); my $apply_routine = $patch_mode_flavour{APPLY}; diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index aa5909b..0926b91 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -215,6 +215,26 @@ test_expect_success 'add first line works' ' ' cat >expected <<EOF +diff --git a/non-empty b/non-empty +deleted file mode 100644 +index d95f3ad..0000000 +--- a/non-empty ++++ /dev/null +@@ -1 +0,0 @@ +-content +EOF +test_expect_success 'deleting a non-empty file' ' + git reset --hard && + echo content >non-empty && + git add non-empty && + git commit -m non-empty && + rm non-empty && + echo y | git add -p non-empty && + git diff --cached >diff && + test_cmp expected diff +' + +cat >expected <<EOF diff --git a/empty b/empty deleted file mode 100644 index e69de29..0000000 -- 1.6.5.1.g24ab.dirty ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2009-12-08 5:47 ` Jeff King @ 2009-12-08 6:01 ` Jeff King 2009-12-08 6:49 ` James Vega 2009-12-08 7:28 ` Junio C Hamano 2009-12-08 7:11 ` Junio C Hamano 1 sibling, 2 replies; 16+ messages in thread From: Jeff King @ 2009-12-08 6:01 UTC (permalink / raw) To: Junio C Hamano; +Cc: James Vega, git On Tue, Dec 08, 2009 at 12:47:24AM -0500, Jeff King wrote: > There is a slightly different approach we could take, too: keep the > "deletion" hunk as a first-class hunk, and just meld the content hunk's > output into it. Then both cases would get the "Stage deletion" question > instead of the "Stage this hunk" you get now for non-empty files (which > just happens to trigger a deletion due to the headers). BTW, the code for this is the much smaller change below. If you prefer that, I can squash in the test and write up an appropriate commit message. diff --git a/git-add--interactive.perl b/git-add--interactive.perl index 35f4ef1..02e97b9 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -1217,7 +1217,11 @@ sub patch_update_file { if (@{$mode->{TEXT}}) { unshift @hunk, $mode; } - if (@{$deletion->{TEXT}} && !@hunk) { + if (@{$deletion->{TEXT}}) { + foreach my $hunk (@hunk) { + push @{$deletion->{TEXT}}, @{$hunk->{TEXT}}; + push @{$deletion->{DISPLAY}}, @{$hunk->{DISPLAY}}; + } @hunk = ($deletion); } ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2009-12-08 6:01 ` Jeff King @ 2009-12-08 6:49 ` James Vega 2009-12-08 7:28 ` Junio C Hamano 1 sibling, 0 replies; 16+ messages in thread From: James Vega @ 2009-12-08 6:49 UTC (permalink / raw) To: Jeff King; +Cc: Junio C Hamano, git On Tue, Dec 08, 2009 at 01:01:09AM -0500, Jeff King wrote: > On Tue, Dec 08, 2009 at 12:47:24AM -0500, Jeff King wrote: > > > There is a slightly different approach we could take, too: keep the > > "deletion" hunk as a first-class hunk, and just meld the content hunk's > > output into it. Then both cases would get the "Stage deletion" question > > instead of the "Stage this hunk" you get now for non-empty files (which > > just happens to trigger a deletion due to the headers). > > BTW, the code for this is the much smaller change below. If you prefer > that, I can squash in the test and write up an appropriate commit > message. > > diff --git a/git-add--interactive.perl b/git-add--interactive.perl > index 35f4ef1..02e97b9 100755 > --- a/git-add--interactive.perl > +++ b/git-add--interactive.perl > @@ -1217,7 +1217,11 @@ sub patch_update_file { > if (@{$mode->{TEXT}}) { > unshift @hunk, $mode; > } > - if (@{$deletion->{TEXT}} && !@hunk) { > + if (@{$deletion->{TEXT}}) { > + foreach my $hunk (@hunk) { > + push @{$deletion->{TEXT}}, @{$hunk->{TEXT}}; > + push @{$deletion->{DISPLAY}}, @{$hunk->{DISPLAY}}; > + } > @hunk = ($deletion); > } > Thanks for the quick patches. This was similar to what I was working on, but cleaner than what I had. Works well for me. -- James GPG Key: 1024D/61326D40 2003-09-02 James Vega <vega.james@gmail.com> ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2009-12-08 6:01 ` Jeff King 2009-12-08 6:49 ` James Vega @ 2009-12-08 7:28 ` Junio C Hamano 2009-12-08 7:49 ` Jeff King 1 sibling, 1 reply; 16+ messages in thread From: Junio C Hamano @ 2009-12-08 7:28 UTC (permalink / raw) To: Jeff King; +Cc: Junio C Hamano, James Vega, git Jeff King <peff@peff.net> writes: > On Tue, Dec 08, 2009 at 12:47:24AM -0500, Jeff King wrote: > >> There is a slightly different approach we could take, too: keep the >> "deletion" hunk as a first-class hunk, and just meld the content hunk's >> output into it. Then both cases would get the "Stage deletion" question >> instead of the "Stage this hunk" you get now for non-empty files (which >> just happens to trigger a deletion due to the headers). > > BTW, the code for this is the much smaller change below. If you prefer > that, I can squash in the test and write up an appropriate commit > message. Doubly interesting, as I recall reading "That would take some refactoring, though, as pulling the deletion hunk" ... goes and looks ... Ah, Ok, the "refactoring" refers to the "header reordering weirdness". That might be something we may want to fix someday, when we find ourselves needing to add a feature to turn deletion into non-deletion or vice versa during "add -p" [e]dit, as I suspect that the "hunk editing" codepath does not keep track of what the user's patch is doing, to the point that it does not even know how many lines there are supposed to be in the resulting hunk that it asks "git apply" to recount. There is no way to add/delete "deleted file" line if the logic does not know what the patch is doing. But someday is not today. I think this six-liner is preferable. > diff --git a/git-add--interactive.perl b/git-add--interactive.perl > index 35f4ef1..02e97b9 100755 > --- a/git-add--interactive.perl > +++ b/git-add--interactive.perl > @@ -1217,7 +1217,11 @@ sub patch_update_file { > if (@{$mode->{TEXT}}) { > unshift @hunk, $mode; > } > - if (@{$deletion->{TEXT}} && !@hunk) { > + if (@{$deletion->{TEXT}}) { > + foreach my $hunk (@hunk) { > + push @{$deletion->{TEXT}}, @{$hunk->{TEXT}}; > + push @{$deletion->{DISPLAY}}, @{$hunk->{DISPLAY}}; > + } > @hunk = ($deletion); > } > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2009-12-08 7:28 ` Junio C Hamano @ 2009-12-08 7:49 ` Jeff King 2009-12-08 7:53 ` Junio C Hamano 0 siblings, 1 reply; 16+ messages in thread From: Jeff King @ 2009-12-08 7:49 UTC (permalink / raw) To: Junio C Hamano; +Cc: James Vega, git On Mon, Dec 07, 2009 at 11:28:01PM -0800, Junio C Hamano wrote: > That might be something we may want to fix someday, when we find ourselves > needing to add a feature to turn deletion into non-deletion or vice versa > during "add -p" [e]dit, as I suspect that the "hunk editing" codepath does > not keep track of what the user's patch is doing, to the point that it > does not even know how many lines there are supposed to be in the > resulting hunk that it asks "git apply" to recount. There is no way to > add/delete "deleted file" line if the logic does not know what the patch > is doing. > > But someday is not today. I think this six-liner is preferable. OK, here it is with the test and an amended commit message. You could almost do an [e]dit on this and delete the "deleted" line, but you have no way of fixing up the "+++ /dev/null" line. For now, we have disabled [e]dit entirely for non-content hunks, so at least you cannot get yourself into trouble creating a broken patch. :) -- >8 -- Subject: [PATCH] add-interactive: fix deletion of non-empty files Commit 24ab81a fixed the deletion of empty files, but broke deletion of non-empty files. The approach it took was to factor out the "deleted" line from the patch header into its own hunk, the same way we do for mode changes. However, unlike mode changes, we only showed the special "delete this file" hunk if there were no other hunks. Otherwise, the user would annoyingly be presented with _two_ hunks: one for deleting the file and one for deleting the content. This meant that in the non-empty case, we forgot about the deleted line entirely, and we submitted a bogus patch to git-apply (with "/dev/null" as the destination file, but not marked as a deletion). Instead, this patch combines the file deletion hunk and the content deletion hunk (if there is one) into a single deletion hunk which is either staged or not. Signed-off-by: Jeff King <peff@peff.net> --- git-add--interactive.perl | 6 +++++- t/t3701-add-interactive.sh | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletions(-) diff --git a/git-add--interactive.perl b/git-add--interactive.perl index 35f4ef1..02e97b9 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -1217,7 +1217,11 @@ sub patch_update_file { if (@{$mode->{TEXT}}) { unshift @hunk, $mode; } - if (@{$deletion->{TEXT}} && !@hunk) { + if (@{$deletion->{TEXT}}) { + foreach my $hunk (@hunk) { + push @{$deletion->{TEXT}}, @{$hunk->{TEXT}}; + push @{$deletion->{DISPLAY}}, @{$hunk->{DISPLAY}}; + } @hunk = ($deletion); } diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index aa5909b..0926b91 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -215,6 +215,26 @@ test_expect_success 'add first line works' ' ' cat >expected <<EOF +diff --git a/non-empty b/non-empty +deleted file mode 100644 +index d95f3ad..0000000 +--- a/non-empty ++++ /dev/null +@@ -1 +0,0 @@ +-content +EOF +test_expect_success 'deleting a non-empty file' ' + git reset --hard && + echo content >non-empty && + git add non-empty && + git commit -m non-empty && + rm non-empty && + echo y | git add -p non-empty && + git diff --cached >diff && + test_cmp expected diff +' + +cat >expected <<EOF diff --git a/empty b/empty deleted file mode 100644 index e69de29..0000000 -- 1.6.5.1.g24ab.dirty ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2009-12-08 7:49 ` Jeff King @ 2009-12-08 7:53 ` Junio C Hamano 0 siblings, 0 replies; 16+ messages in thread From: Junio C Hamano @ 2009-12-08 7:53 UTC (permalink / raw) To: Jeff King; +Cc: James Vega, git Jeff King <peff@peff.net> writes: > OK, here it is with the test and an amended commit message. You could > almost do an [e]dit on this and delete the "deleted" line, but you have > no way of fixing up the "+++ /dev/null" line. For now, we have > disabled [e]dit entirely for non-content hunks, so at least you cannot > get yourself into trouble creating a broken patch. :) ;-) Thanks. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2009-12-08 5:47 ` Jeff King 2009-12-08 6:01 ` Jeff King @ 2009-12-08 7:11 ` Junio C Hamano 2009-12-08 7:38 ` Jeff King 1 sibling, 1 reply; 16+ messages in thread From: Junio C Hamano @ 2009-12-08 7:11 UTC (permalink / raw) To: Jeff King; +Cc: Junio C Hamano, James Vega, git Jeff King <peff@peff.net> writes: > On Mon, Dec 07, 2009 at 07:20:30PM -0800, Junio C Hamano wrote: > >> An update. I tried your reproduction recipe with 1.6.5.2 and it doesn't >> reproduce, but with 1.6.5.3 it does. > > Thanks, both, for a very helpful bug report. 24ab81a was totally bogus, > but we lacked a test for deleting a non-empty file. That test and a fix > for the problem are in the patch below. Thanks. > I am still slightly concerned that James's > > git diff | sed '/^deleted file/d' | git apply --cached > > behaves as it does. What should git-apply do with a patch like: > > diff --git a/foo b/foo > index 257cc56..0000000 > --- a/foo > +++ /dev/null > @@ -1 +0,0 @@ > -foo > > ? I can see either turning it into a deletion patch (because /dev/null > is special) or barfing (because /dev/null as a special case should have > appeared in the "diff" line). But creating a dev/null file seems very > wrong. I was wondering about the same thing while bisecting. By the current definition of "diff --git", removing the "deleted file" or "new file" line makes the patch an invalid "git format diff". See the beginning of parse_git_header() where we say "we don't guess" and initialize both is_new and is_delete to false (and we flip them upon seeing "deleted file" and "new file", but never with "/dev/null"). > But maybe it is not worth worrying about too much. That patch format is > not generated intentionally by any known software. I think some recent other SCMs produce what they claim to be "diff --git", but I don't know if they implement the format correctly enough. I am not worried about their implemention of binary patches (if they do not implement it correctly they will most likely get garbage), but do they get the abbreviated hash on the "index" line correctly? You can put garbage on the line and most of the time it would work but it will break "am -3" by breaking "apply --build-fake-ancestor". I just checked "hg diff --git"; at least it shows "deleted file". > That would take some refactoring, though, as pulling the deletion hunk > out means we are re-ordering the headers. So right now if you did that > your ($head, @hunk) output would be something like: > > diff --git a/foo b/foo > index 257cc56..0000000 > --- a/foo > +++ /dev/null > deleted file mode 100644 > @@ -1 +0,0 @@ > -foo > > which is pretty weird. I agree it is weird. > And it also opens the door to editing the hunk to stop the deletion, but > still tweak the content change. Right now if you edit a deletion patch, > you can't remove the 'deleted' bit, and if your edit result keeps any > content in the file, apply will complain. I'm not sure that particular > feature would be useful though (I have certainly never wanted it). Interesting. Does "add -p" (especially its [e]dit codepath) know enough about what it is doing? If so, it should be able to add "deleted file" on its own (and remove it when the result of editing and picking hunks makes the patch a non-deletion). For example, if you have a two-liner in the index and have deleted one line in the work tree, and run "add -p": diff --git a/foo b/foo index 3bd1f0e..257cc56 100644 --- a/foo +++ b/foo @@ -1,2 +1 @@ foo -bar you *should* be able to edit it into a patch that removes all lines. Perhaps the "add -i" at the end should offer, after noticing that the chosen and edited hunks will make the postimage an empty file, a chance for the user to say "I not only want to remove the contents from the path, but want to remove the path itself" in such a case? I dunno. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2009-12-08 7:11 ` Junio C Hamano @ 2009-12-08 7:38 ` Jeff King 0 siblings, 0 replies; 16+ messages in thread From: Jeff King @ 2009-12-08 7:38 UTC (permalink / raw) To: Junio C Hamano; +Cc: James Vega, git On Mon, Dec 07, 2009 at 11:11:08PM -0800, Junio C Hamano wrote: > I was wondering about the same thing while bisecting. By the current > definition of "diff --git", removing the "deleted file" or "new file" line > makes the patch an invalid "git format diff". See the beginning of > parse_git_header() where we say "we don't guess" and initialize both > is_new and is_delete to false (and we flip them upon seeing "deleted file" > and "new file", but never with "/dev/null"). Hmm. In that case, I think converting it to deletion is definitely wrong; "diff --git" is about not guessing. So the only question is whether it should be flagged as an error. I was somewhat worried that you could produce a patch which would make apply complain by doing "git diff /dev/null /your/file". But actually that already produces a "new file" header (and the opposite produces a "deleted file" header). So I think the patch below would notice both the new and deleted cases, and is probably a good thing. diff --git a/builtin-apply.c b/builtin-apply.c index c8372a0..43a1535 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -673,8 +673,12 @@ static int gitdiff_hdrend(const char *line, struct patch *patch) */ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, const char *oldnew) { - if (!orig_name && !isnull) + if (!orig_name && !isnull) { + if (!memcmp(line, "/dev/null\n", 10)) + die("git apply: bad git-diff - expected filename, got /dev/null on line %d", linenr); return find_name(line, NULL, p_value, TERM_TAB); + } + if (orig_name) { int len; > I think some recent other SCMs produce what they claim to be "diff --git", > but I don't know if they implement the format correctly enough. I am not > worried about their implemention of binary patches (if they do not > implement it correctly they will most likely get garbage), but do they get > the abbreviated hash on the "index" line correctly? You can put garbage > on the line and most of the time it would work but it will break "am -3" > by breaking "apply --build-fake-ancestor". > > I just checked "hg diff --git"; at least it shows "deleted file". Ugh. A whole new source of problems. :) I am not too interested in seeking out and evaluating other SCM's implementations; I think we should wait for people who actually use those systems to find interoperability bugs, determine whether they are or are not simply bugs in the other people's implementations, and then report the bug to us. > > That would take some refactoring, though, as pulling the deletion hunk > > out means we are re-ordering the headers. So right now if you did that > > your ($head, @hunk) output would be something like: > > > > diff --git a/foo b/foo > > index 257cc56..0000000 > > --- a/foo > > +++ /dev/null > > deleted file mode 100644 > > @@ -1 +0,0 @@ > > -foo > > > > which is pretty weird. > > I agree it is weird. Note that we already do this for mode changes which also have a content change. They look like: diff --git a/foo b/foo index 257cc56..19c6cc1 --- a/foo +++ b/foo old mode 100644 new mode 100755 Stage mode change [y,n,q,a,d,/,j,J,g,?]? @@ -1 +1,2 @@ foo +content Stage this hunk [y,n,q,a,d,/,K,g,e,?]? > Interesting. Does "add -p" (especially its [e]dit codepath) know enough > about what it is doing? If so, it should be able to add "deleted file" on > its own (and remove it when the result of editing and picking hunks makes > the patch a non-deletion). For example, if you have a two-liner in the > index and have deleted one line in the work tree, and run "add -p": No, it doesn't know enough now. That would be part of the refactoring I mentioned. I'm not sure how useful it is to support this. I can see going from "I had hunk A, but I really wanted to tweak it to hunk B". I can't think of a single time I've wanted "I deleted the entire file, but I really wanted to keep 2 lines". And if I did, I would probably just: git checkout file $EDITOR file git add -p file > Perhaps the "add -i" at the end should offer, after noticing that the > chosen and edited hunks will make the postimage an empty file, a chance > for the user to say "I not only want to remove the contents from the path, > but want to remove the path itself" in such a case? > > I dunno. I would not say no to such a patch, but I really have no interest in writing it myself. -Peff ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2009-12-08 2:59 ` Junio C Hamano 2009-12-08 3:20 ` Junio C Hamano @ 2009-12-08 3:39 ` James Vega 1 sibling, 0 replies; 16+ messages in thread From: James Vega @ 2009-12-08 3:39 UTC (permalink / raw) To: Junio C Hamano; +Cc: git On Mon, Dec 07, 2009 at 06:59:28PM -0800, Junio C Hamano wrote: > James Vega <vega.james@gmail.com> writes: > > > It looks like this may have introduced a bug when staging a file > > removal. Here's an example git session showing the issue: > > <<snipped>> > > Thanks for a report, but I cannot get the evidence that the said patch has > anything to do with the issue you illustrated. Right, I incorrectly assumed the problem was with git-apply when I saw Steve's patch since the symptoms seemed similar. I just finished a bisect, though, and the problem is in removing a non-empty file with "git add -p". This wasn't caught by existing tests because they only try to remove an empty file. This was introduced in 8f0bef6 (git-apply--interactive: Refactor patch mode code, 2009-08-13) -- James GPG Key: 1024D/61326D40 2003-09-02 James Vega <vega.james@gmail.com> ^ permalink raw reply [flat|nested] 16+ messages in thread
* git-apply fails on creating a new file, with both -p and --directory specified @ 2010-04-28 12:29 Matthias Lehmann 2010-04-29 8:20 ` Matthias Lehmann 0 siblings, 1 reply; 16+ messages in thread From: Matthias Lehmann @ 2010-04-28 12:29 UTC (permalink / raw) To: git Hi all, the subject of this mail may read familiar to some - there was a discussion in November last year (see http://kerneltrap.org/mailarchive/git/2009/11/23/16899/) concerning this problem. Today I had this same issue with git 1.7.0.4. Reading the above mentioned discussion and seaching the net did not help me in finding a solution to the problem. I have to apply patches from one repository to another repository, which have a different layout (I am working on splitting one big repository into several smaller ones, while development still continues on the big repository). So I did big-repo$ git format-patche -o /tmp/foo small-repo$ git apply -p2 --directory=some/path --check /tmp/foo/* and get fatal: git diff header lacks filename information when removing 2 leading pathname components (line 37) the patch looks like this: 35| diff --git a/xyz/bar.jpg b/xyz/bar.jpg 36| new file mode 100644 37| index 0000000000000000000000000000000000000000..3dcce2e1f68586ed2089d86b1bf4e7e41c818d97 38| GIT binary patch 39| literal 8791 Since this problem was discussed before - is there a solution? This is something like a showstopper for me right now, so I am very thankful for any hints. Best regards, Mat ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: git-apply fails on creating a new file, with both -p and --directory specified 2010-04-28 12:29 Matthias Lehmann @ 2010-04-29 8:20 ` Matthias Lehmann 0 siblings, 0 replies; 16+ messages in thread From: Matthias Lehmann @ 2010-04-29 8:20 UTC (permalink / raw) To: git Matthias Lehmann wrote: > Hi all, > > the subject of this mail may read familiar to some - there was a > discussion in November last year (see > http://kerneltrap.org/mailarchive/git/2009/11/23/16899/) concerning this > problem. > > Today I had this same issue with git 1.7.0.4. Reading the above mentioned > discussion and seaching the net did not help me in finding a solution to > the problem. > > I have to apply patches from one repository to another repository, which > have a different layout (I am working on splitting one big repository into > several smaller ones, while development still continues on the big > repository). > > So I did > > big-repo$ git format-patche -o /tmp/foo > small-repo$ git apply -p2 --directory=some/path --check /tmp/foo/* > > and get > > fatal: git diff header lacks filename information when removing 2 leading > pathname components (line 37) > > the patch looks like this: > > 35| diff --git a/xyz/bar.jpg b/xyz/bar.jpg > 36| new file mode 100644 > 37| index > 0000000000000000000000000000000000000000..3dcce2e1f68586ed2089d86b1bf4e7e41c818d97 > 38| GIT binary patch > 39| literal 8791 > > > > Since this problem was discussed before - is there a solution? > This is something like a showstopper for me right now, so I am very > thankful for any hints. > > Best regards, > > Mat Is there anything I can do to get some feedback to this issue? I don't want to be impatient, it's just quite important to me. Since I have not much experience in reporting issues to a mailing list, it might well be, that I did something wrong - so please correct me and direct me to how I can be of better help. Best regards, Mat ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2010-04-30 18:32 UTC | newest] Thread overview: 16+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-11-23 19:45 git-apply fails on creating a new file, with both -p and --directory specified Steven J. Murdoch 2009-11-25 10:56 ` Junio C Hamano 2009-12-07 21:35 ` James Vega 2009-12-08 2:59 ` Junio C Hamano 2009-12-08 3:20 ` Junio C Hamano 2009-12-08 5:47 ` Jeff King 2009-12-08 6:01 ` Jeff King 2009-12-08 6:49 ` James Vega 2009-12-08 7:28 ` Junio C Hamano 2009-12-08 7:49 ` Jeff King 2009-12-08 7:53 ` Junio C Hamano 2009-12-08 7:11 ` Junio C Hamano 2009-12-08 7:38 ` Jeff King 2009-12-08 3:39 ` James Vega -- strict thread matches above, loose matches on Subject: below -- 2010-04-28 12:29 Matthias Lehmann 2010-04-29 8:20 ` Matthias Lehmann
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).