diff options
Diffstat (limited to 'builtin-apply.c')
-rw-r--r-- | builtin-apply.c | 75 |
1 files changed, 44 insertions, 31 deletions
diff --git a/builtin-apply.c b/builtin-apply.c index db52722455..0399743c4e 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -30,7 +30,7 @@ static int unidiff_zero; static int p_value = 1; static int p_value_known; static int check_index; -static int write_index; +static int update_index; static int cached; static int diffstat; static int numstat; @@ -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,15 +1468,15 @@ 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; } close(fd); nsize = got; - nbuf = buf; - if (convert_to_git(path, &nbuf, &nsize)) { + nbuf = convert_to_git(path, buf, &nsize); + if (nbuf) { free(buf); *buf_p = nbuf; *alloc_p = nsize; @@ -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) @@ -2308,7 +2325,7 @@ static void patch_stats(struct patch *patch) static void remove_file(struct patch *patch, int rmdir_empty) { - if (write_index) { + if (update_index) { if (remove_file_from_cache(patch->old_name) < 0) die("unable to remove %s from index", patch->old_name); cache_tree_invalidate_path(active_cache_tree, patch->old_name); @@ -2335,7 +2352,7 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned int namelen = strlen(path); unsigned ce_size = cache_entry_size(namelen); - if (!write_index) + if (!update_index) return; ce = xcalloc(1, ce_size); @@ -2355,9 +2372,8 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size) { - int fd, converted; + int fd; char *nbuf; - unsigned long nsize; if (has_symlinks && S_ISLNK(mode)) /* Although buf:size is counted string, it also is NUL @@ -2369,13 +2385,10 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, if (fd < 0) return -1; - nsize = size; - nbuf = (char *) buf; - converted = convert_to_working_tree(path, &nbuf, &nsize); - if (converted) { + nbuf = convert_to_working_tree(path, buf, &size); + if (nbuf) buf = nbuf; - size = nsize; - } + while (size) { int written = xwrite(fd, buf, size); if (written < 0) @@ -2387,7 +2400,7 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, } if (close(fd) < 0) die("closing file %s: %s", path, strerror(errno)); - if (converted) + if (nbuf) free(nbuf); return 0; } @@ -2661,10 +2674,10 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof) if (whitespace_error && (new_whitespace == error_on_whitespace)) apply = 0; - write_index = check_index && apply; - if (write_index && newfd < 0) - newfd = hold_lock_file_for_update(&lock_file, - get_index_file(), 1); + update_index = check_index && apply; + if (update_index && newfd < 0) + newfd = hold_locked_index(&lock_file, 1); + if (check_index) { if (read_cache() < 0) die("unable to read index file"); @@ -2869,9 +2882,9 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix) whitespace_error == 1 ? "s" : ""); } - if (write_index) { + if (update_index) { if (write_cache(newfd, active_cache, active_nr) || - close(newfd) || commit_lock_file(&lock_file)) + close(newfd) || commit_locked_index(&lock_file)) die("Unable to write new index file"); } |