In a repository created with git older than f49fb35 (git-init-db: create "pack" subdirectory under objects, 2005-06-27), objects/pack/ directory is not created upon initialization. It was Ok because subdirectories are created as needed inside directories init-db creates. 8b4eb6b (Do not perform cross-directory renames when creating packs, 2008-09-22) moved the location temporary pack files are created from objects/ directory to objects/pack/ directory; this move broke many operations in such a repository, because it was not careful enough to make sure leading directories exist. Introduce odb_mkstemp() which is a specialized version of mkstemp() to refactor the code and teach it to create a leading directories properly to fix this buglet. Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> --- * I don't know why, but I somehow found doing this patch highly amusing. builtin-pack-objects.c | 5 ++--- fast-import.c | 10 ++++------ git-compat-util.h | 1 + index-pack.c | 5 ++--- pack-write.c | 4 +--- wrapper.c | 17 +++++++++++++++++ 6 files changed, 27 insertions(+), 15 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index cb51916..bcefa52 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -488,9 +488,8 @@ static void write_pack_file(void) } else { char tmpname[PATH_MAX]; int fd; - snprintf(tmpname, sizeof(tmpname), - "%s/pack/tmp_pack_XXXXXX", get_object_directory()); - fd = xmkstemp(tmpname); + fd = odb_mkstemp(tmpname, sizeof(tmpname), + "pack/tmp_pack_XXXXXX"); pack_tmp_name = xstrdup(tmpname); f = sha1fd(fd, pack_tmp_name); } diff --git a/fast-import.c b/fast-import.c index 3ef3413..99e4df4 100644 --- a/fast-import.c +++ b/fast-import.c @@ -817,9 +817,8 @@ static void start_packfile(void) struct pack_header hdr; int pack_fd; - snprintf(tmpfile, sizeof(tmpfile), - "%s/pack/tmp_pack_XXXXXX", get_object_directory()); - pack_fd = xmkstemp(tmpfile); + pack_fd = odb_mkstemp(tmpfile, sizeof(tmpfile), + "pack/tmp_pack_XXXXXX"); p = xcalloc(1, sizeof(*p) + strlen(tmpfile) + 2); strcpy(p->pack_name, tmpfile); p->pack_fd = pack_fd; @@ -879,9 +878,8 @@ static char *create_index(void) c = next; } - snprintf(tmpfile, sizeof(tmpfile), - "%s/pack/tmp_idx_XXXXXX", get_object_directory()); - idx_fd = xmkstemp(tmpfile); + idx_fd = odb_mkstemp(tmpfile, sizeof(tmpfile), + "pack/tmp_idx_XXXXXX"); f = sha1fd(idx_fd, tmpfile); sha1write(f, array, 256 * sizeof(int)); git_SHA1_Init(&ctx); diff --git a/git-compat-util.h b/git-compat-util.h index 079cbe9..c1744b9 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -303,6 +303,7 @@ extern ssize_t xwrite(int fd, const void *buf, size_t len); extern int xdup(int fd); extern FILE *xfdopen(int fd, const char *mode); extern int xmkstemp(char *template); +extern int odb_mkstemp(char *template, size_t limit, const char *pattern); static inline size_t xsize_t(off_t len) { diff --git a/index-pack.c b/index-pack.c index f7a3807..0350c29 100644 --- a/index-pack.c +++ b/index-pack.c @@ -172,9 +172,8 @@ static char *open_pack_file(char *pack_name) input_fd = 0; if (!pack_name) { static char tmpfile[PATH_MAX]; - snprintf(tmpfile, sizeof(tmpfile), - "%s/pack/tmp_pack_XXXXXX", get_object_directory()); - output_fd = xmkstemp(tmpfile); + output_fd = odb_mkstemp(tmpfile, sizeof(tmpfile), + "pack/tmp_pack_XXXXXX"); pack_name = xstrdup(tmpfile); } else output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600); diff --git a/pack-write.c b/pack-write.c index b426006..3ab55b9 100644 --- a/pack-write.c +++ b/pack-write.c @@ -44,9 +44,7 @@ char *write_idx_file(char *index_name, struct pack_idx_entry **objects, if (!index_name) { static char tmpfile[PATH_MAX]; - snprintf(tmpfile, sizeof(tmpfile), - "%s/pack/tmp_idx_XXXXXX", get_object_directory()); - fd = xmkstemp(tmpfile); + fd = odb_mkstemp(tmpfile, sizeof(tmpfile), "pack/tmp_idx_XXXXXX"); index_name = xstrdup(tmpfile); } else { unlink(index_name); diff --git a/wrapper.c b/wrapper.c index c85ca52..371cee1 100644 --- a/wrapper.c +++ b/wrapper.c @@ -197,6 +197,23 @@ int xmkstemp(char *template) return fd; } +int odb_mkstemp(char *template, size_t limit, const char *pattern) +{ + int fd; + + snprintf(template, limit, "%s/%s", + get_object_directory(), pattern); + fd = mkstemp(template); + if (0 <= fd) + return fd; + + /* slow path */ + safe_create_leading_directories(template); + snprintf(template, limit, "%s/%s", + get_object_directory(), pattern); + return xmkstemp(template); +} + /* * zlib wrappers to make sure we don't silently miss errors * at init time. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html