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 /apply.c | |
parent | fa3e0655a45f53bbc1b48edc8f931426b183cba1 (diff) | |
download | git-5c8af185cc547b1babdd6292b1c77bec1941922f.tar.gz git-5c8af185cc547b1babdd6292b1c77bec1941922f.tar.xz |
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.
Diffstat (limited to 'apply.c')
-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; |