X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=entry.c;h=cfadc6a292033d349f6b1efff75d2c4f9f2525fe;hb=5410a02ab9e6a1987147724f8ea65e6a077b3832;hp=82bf7259a7d1d34a92a9bf214bccd9771748c582;hpb=404fdef22f1084141aeef5781d5a322554fed481;p=git.git
diff --git a/entry.c b/entry.c
index 82bf7259a..cfadc6a29 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);
@@ -81,7 +104,8 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
long wrote;
switch (ntohl(ce->ce_mode) & S_IFMT) {
- char *buf, *new;
+ char *new;
+ struct strbuf buf;
unsigned long size;
case S_IFREG:
@@ -89,6 +113,18 @@ 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
+ */
+ strbuf_init(&buf, 0);
+ if (convert_to_working_tree(ce->name, new, size, &buf)) {
+ size_t newsize = 0;
+ free(new);
+ new = strbuf_detach(&buf, &newsize);
+ size = newsize;
+ }
+
if (to_tempfile) {
strcpy(path, ".merge_file_XXXXXX");
fd = mkstemp(path);
@@ -100,15 +136,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 +172,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 +221,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);