summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-07-17 06:28:23 (GMT)
committerJunio C Hamano <junkio@cox.net>2006-07-17 06:28:36 (GMT)
commitc28c571c143a5145665f4bf334671ac3a7d0980c (patch)
tree713d684ddc39cc577b222449a1b340cfd2c5bec4
parent8641fb24ee3ab86bac62f88d31f6e92a9323f699 (diff)
downloadgit-c28c571c143a5145665f4bf334671ac3a7d0980c.zip
git-c28c571c143a5145665f4bf334671ac3a7d0980c.tar.gz
git-c28c571c143a5145665f4bf334671ac3a7d0980c.tar.bz2
apply: check D/F conflicts more carefully.
When creating a new file where a directory used to be (or the user had an empty directory) the code did not check the result from lstat() closely enough, and mistakenly thought the path already existed in the working tree. This does not fix the problem where you have a patch that creates a file at "foo" and removes a file at "foo/bar" (which presumably is the last file in "foo/" directory in the original). For that, we would need to restructure write_out_results() loop. Signed-off-by: Junio C Hamano <junkio@cox.net>
-rw-r--r--builtin-apply.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/builtin-apply.c b/builtin-apply.c
index c903146..9727442 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -1732,9 +1732,14 @@ static int check_patch(struct patch *patch)
if (check_index && cache_name_pos(new_name, strlen(new_name)) >= 0)
return error("%s: already exists in index", new_name);
if (!cached) {
- if (!lstat(new_name, &st))
- return error("%s: already exists in working directory", new_name);
- if (errno != ENOENT)
+ struct stat nst;
+ if (!lstat(new_name, &nst)) {
+ if (S_ISDIR(nst.st_mode))
+ ; /* ok */
+ else
+ return error("%s: already exists in working directory", new_name);
+ }
+ else if ((errno != ENOENT) && (errno != ENOTDIR))
return error("%s: %s", new_name, strerror(errno));
}
if (!patch->new_mode) {
@@ -2011,6 +2016,16 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
}
if (errno == EEXIST) {
+ /* We may be trying to create a file where a directory
+ * used to be.
+ */
+ struct stat st;
+ errno = 0;
+ if (!lstat(path, &st) && S_ISDIR(st.st_mode) && !rmdir(path))
+ errno = EEXIST;
+ }
+
+ if (errno == EEXIST) {
unsigned int nr = getpid();
for (;;) {