diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-21 19:10:21 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-21 19:10:21 -0700 |
commit | 5c8af185cc547b1babdd6292b1c77bec1941922f (patch) | |
tree | b5c34bca2e519e8f675eae30ef581464ada17687 | |
parent | fa3e0655a45f53bbc1b48edc8f931426b183cba1 (diff) | |
download | git-5c8af185cc547b1babdd6292b1c77bec1941922f.tar.gz |
git-apply: create subdirectories leading up to a new file
Applying Andrew's latest patch-bomb showed us failing miserably if a new
subdirectory needed to be created.. That said, it's uncommon enough
that it's worth optimistically assuming it won't be needed, and then
creating the subdirectories only on failure.
-rw-r--r-- | apply.c | 49 |
1 files changed, 47 insertions, 2 deletions
@@ -1144,6 +1144,51 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned die("unable to add cache entry for %s", path); } +static void create_subdirectories(const char *path) +{ + int len = strlen(path); + char *buf = xmalloc(len + 1); + const char *slash = path; + + while ((slash = strchr(slash+1, '/')) != NULL) { + len = slash - path; + memcpy(buf, path, len); + buf[len] = 0; + if (mkdir(buf, 0755) < 0) { + if (errno != EEXIST) + break; + } + } + free(buf); +} + +/* + * We optimistically assume that the directories exist, + * which is true 99% of the time anyway. If they don't, + * we create them and try again. + */ +static int create_regular_file(const char *path, unsigned int mode) +{ + int ret = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); + + if (ret < 0 && errno == ENOENT) { + create_subdirectories(path); + ret = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); + } + return ret; +} + +static int create_symlink(const char *buf, const char *path) +{ + int ret = symlink(buf, path); + + if (ret < 0 && errno == ENOENT) { + create_subdirectories(path); + ret = symlink(buf, path); + } + return ret; +} + static void create_file(struct patch *patch) { const char *path = patch->new_name; @@ -1156,7 +1201,7 @@ static void create_file(struct patch *patch) if (S_ISREG(mode)) { int fd; mode = (mode & 0100) ? 0777 : 0666; - fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); + fd = create_regular_file(path, mode); if (fd < 0) die("unable to create file %s (%s)", path, strerror(errno)); if (write(fd, buf, size) != size) @@ -1169,7 +1214,7 @@ static void create_file(struct patch *patch) if (size && buf[size-1] == '\n') size--; buf[size] = 0; - if (symlink(buf, path) < 0) + if (create_symlink(buf, path) < 0) die("unable to write symlink %s", path); add_index_file(path, mode, buf, size); return; |