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;
void *buffer = xmalloc(alloc);
for (;;) {
- int nr = alloc - size;
+ ssize_t nr = alloc - size;
if (nr < 1024) {
alloc += CHUNKSIZE;
buffer = xrealloc(buffer, alloc);
static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, const char *oldnew)
{
if (!orig_name && !isnull)
- return find_name(line, NULL, 1, TERM_TAB);
+ return find_name(line, NULL, p_value, TERM_TAB);
if (orig_name) {
int len;
len = strlen(name);
if (isnull)
die("git-apply: bad git-diff - expected /dev/null, got %s on line %d", name, linenr);
- another = find_name(line, NULL, 1, TERM_TAB);
+ another = find_name(line, NULL, p_value, TERM_TAB);
if (!another || memcmp(another, name, len))
die("git-apply: bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
free(another);
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;
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;
!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)
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);
int namelen = strlen(path);
unsigned ce_size = cache_entry_size(namelen);
- if (!write_index)
+ if (!update_index)
return;
ce = xcalloc(1, ce_size);
{
int fd;
char *nbuf;
- unsigned long nsize;
if (has_symlinks && S_ISLNK(mode))
/* Although buf:size is counted string, it also is NUL
* terminated.
*/
return symlink(buf, path);
- nsize = size;
- nbuf = (char *) buf;
- if (convert_to_working_tree(path, &nbuf, &nsize)) {
- free((char *) buf);
- buf = nbuf;
- size = nsize;
- }
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666);
if (fd < 0)
return -1;
+
+ nbuf = convert_to_working_tree(path, buf, &size);
+ if (nbuf)
+ buf = nbuf;
+
while (size) {
int written = xwrite(fd, buf, size);
if (written < 0)
}
if (close(fd) < 0)
die("closing file %s: %s", path, strerror(errno));
+ if (nbuf)
+ free(nbuf);
return 0;
}
* 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;
}
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");
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");
}