X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=entry.c;h=fc3a506ecef4ed654f26c11996df109dd135a4ed;hb=5433235daec11550973f1e290f069ce0c27f53ab;hp=82bf7259a7d1d34a92a9bf214bccd9771748c582;hpb=667152528df417627e54de6cb281a63a727369af;p=git.git diff --git a/entry.c b/entry.c index 82bf7259a..fc3a506ec 100644 --- a/entry.c +++ b/entry.c @@ -8,17 +8,40 @@ static void create_directories(const char *path, const struct checkout *state) const char *slash = path; while ((slash = strchr(slash+1, '/')) != NULL) { + struct stat st; + int stat_status; + len = slash - path; memcpy(buf, path, len); buf[len] = 0; + + if (len <= state->base_dir_len) + /* + * checkout-index --prefix=; is + * allowed to be a symlink to an existing + * directory. + */ + stat_status = stat(buf, &st); + else + /* + * if there currently is a symlink, we would + * want to replace it with a real directory. + */ + stat_status = lstat(buf, &st); + + if (!stat_status && S_ISDIR(st.st_mode)) + continue; /* ok, it is already a directory. */ + + /* + * We know stat_status == 0 means something exists + * there and this mkdir would fail, but that is an + * error codepath; we do not care, as we unlink and + * mkdir again in such a case. + */ if (mkdir(buf, 0777)) { - if (errno == EEXIST) { - struct stat st; - if (len > state->base_dir_len && state->force && !unlink(buf) && !mkdir(buf, 0777)) - continue; - if (!stat(buf, &st) && S_ISDIR(st.st_mode)) - continue; /* ok */ - } + if (errno == EEXIST && state->force && + !unlink(buf) && !mkdir(buf, 0777)) + continue; die("cannot create directory at %s", buf); } } @@ -31,7 +54,7 @@ static void remove_subtree(const char *path) struct dirent *de; char pathbuf[PATH_MAX]; char *name; - + if (!dir) die("cannot opendir %s (%s)", path, strerror(errno)); strcpy(pathbuf, path); @@ -89,6 +112,16 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout if (!new) return error("git-checkout-index: unable to read sha1 file of %s (%s)", path, sha1_to_hex(ce->sha1)); + + /* + * Convert from git internal format to working tree format + */ + buf = convert_to_working_tree(ce->name, new, &size); + if (buf) { + free(new); + new = buf; + } + if (to_tempfile) { strcpy(path, ".merge_file_XXXXXX"); fd = mkstemp(path); @@ -100,15 +133,6 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout path, strerror(errno)); } - /* - * Convert from git internal format to working tree format - */ - buf = convert_to_working_tree(ce->name, new, &size); - if (buf) { - free(new); - new = buf; - } - wrote = write_in_full(fd, new, size); close(fd); free(new); @@ -145,7 +169,7 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout "symlink %s (%s)", path, strerror(errno)); } break; - case S_IFDIRLNK: + case S_IFGITLINK: if (to_tempfile) return error("git-checkout-index: cannot create temporary subproject %s", path); if (mkdir(path, 0777) < 0) @@ -194,7 +218,7 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t unlink(path); if (S_ISDIR(st.st_mode)) { /* If it is a gitlink, leave it alone! */ - if (S_ISDIRLNK(ntohl(ce->ce_mode))) + if (S_ISGITLINK(ntohl(ce->ce_mode))) return 0; if (!state->force) return error("%s is a directory", path);