GIT 1.5.2
[gitweb.git] / builtin-apply.c
index f94d0dbf488ff43ccc496939560c81daf05772cf..0399743c4e2288a0812faeea92c07a5f6a13fccc 100644 (file)
@@ -185,7 +185,7 @@ static void *read_patch_file(int fd, unsigned long *sizep)
        void *buffer = xmalloc(alloc);
 
        for (;;) {
-               int nr = alloc - size;
+               ssize_t nr = alloc - size;
                if (nr < 1024) {
                        alloc += CHUNKSIZE;
                        buffer = xrealloc(buffer, alloc);
@@ -1468,7 +1468,7 @@ static int read_old_data(struct stat *st, const char *path, char **buf_p, unsign
                        return error("unable to open %s", path);
                got = 0;
                for (;;) {
-                       int ret = xread(fd, buf + got, size - got);
+                       ssize_t ret = xread(fd, buf + got, size - got);
                        if (ret <= 0)
                                break;
                        got += ret;
@@ -2009,6 +2009,29 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
        return 0;
 }
 
+static int check_to_create_blob(const char *new_name, int ok_if_exists)
+{
+       struct stat nst;
+       if (!lstat(new_name, &nst)) {
+               if (S_ISDIR(nst.st_mode) || ok_if_exists)
+                       return 0;
+               /*
+                * A leading component of new_name might be a symlink
+                * that is going to be removed with this patch, but
+                * still pointing at somewhere that has the path.
+                * In such a case, path "new_name" does not exist as
+                * far as git is concerned.
+                */
+               if (has_symlink_leading_path(new_name, NULL))
+                       return 0;
+
+               return error("%s: already exists in working directory", new_name);
+       }
+       else if ((errno != ENOENT) && (errno != ENOTDIR))
+               return error("%s: %s", new_name, strerror(errno));
+       return 0;
+}
+
 static int check_patch(struct patch *patch, struct patch *prev_patch)
 {
        struct stat st;
@@ -2095,15 +2118,9 @@ static int check_patch(struct patch *patch, struct patch *prev_patch)
                    !ok_if_exists)
                        return error("%s: already exists in index", new_name);
                if (!cached) {
-                       struct stat nst;
-                       if (!lstat(new_name, &nst)) {
-                               if (S_ISDIR(nst.st_mode) || ok_if_exists)
-                                       ; /* 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));
+                       int err = check_to_create_blob(new_name, ok_if_exists);
+                       if (err)
+                               return err;
                }
                if (!patch->new_mode) {
                        if (0 < patch->is_new)