Skip to content

Commit

Permalink
Fix overwriting of files when applying contextually independent diffs
Browse files Browse the repository at this point in the history
Noticed by applying two diffs of different contexts to the same file.

The check for existence of a file was wrong: the test assumed it was
a directory and reset the errno (twice: directly and by calling
lstat). So if an entry existed and was _not_ a directory no attempt
was made to rename into it, because the errno (expected by renaming
code) was already reset to 0. This resulted in error:

    fatal: unable to write file file mode 100644

For Linux, removing "errno = 0" is enough, as lstat wont modify errno
if it was successful. The behavior should not be depended upon,
though, so modify the "if" as well.

The test simulates this situation.

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Alex Riesen authored and Junio C Hamano committed Apr 18, 2007
1 parent 0c1ec5a commit 0afa764
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 2 deletions.
3 changes: 1 addition & 2 deletions builtin-apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -2416,8 +2416,7 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
* used to be.
*/
struct stat st;
errno = 0;
if (!lstat(path, &st) && S_ISDIR(st.st_mode) && !rmdir(path))
if (!lstat(path, &st) && (!S_ISDIR(st.st_mode) || !rmdir(path)))
errno = EEXIST;
}

Expand Down
33 changes: 33 additions & 0 deletions t/t4121-apply-diffs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/sh

test_description='git-apply for contextually independent diffs'
. ./test-lib.sh

echo '1
2
3
4
5
6
7
8' >file

test_expect_success 'setup' \
'git add file &&
git commit -q -m 1 &&
git checkout -b test &&
mv file file.tmp &&
echo 0 >file &&
cat file.tmp >>file &&
rm file.tmp &&
git commit -a -q -m 2 &&
echo 9 >>file &&
git commit -a -q -m 3 &&
git checkout master'

test_expect_success \
'check if contextually independent diffs for the same file apply' \
'( git diff test~2 test~1; git diff test~1 test~0 )| git apply'

test_done

0 comments on commit 0afa764

Please sign in to comment.