shallow: automatically clean up shallow tempfiles
authorJeff King <peff@peff.net>
Thu, 27 Feb 2014 11:25:20 +0000 (06:25 -0500)
committerJunio C Hamano <gitster@pobox.com>
Thu, 27 Feb 2014 20:07:13 +0000 (12:07 -0800)
We sometimes write tempfiles of the form "shallow_XXXXXX"
during fetch/push operations with shallow repositories.
Under normal circumstances, we clean up the result when we
are done. However, we do no take steps to clean up after
ourselves when we exit due to die() or signal death.

This patch teaches the tempfile creation code to register
handlers to clean up after ourselves. To handle this, we
change the ownership semantics of the filename returned by
setup_temporary_shallow. It now keeps a copy of the filename
itself, and returns only a const pointer to it.

We can also do away with explicit tempfile removal in the
callers. They all exit not long after finishing with the
file, so they can rely on the auto-cleanup, simplifying the
code.

Note that we keep things simple and maintain only a single
filename to be cleaned. This is sufficient for the current
caller, but we future-proof it with a die("BUG").

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/receive-pack.c
commit.h
fetch-pack.c
shallow.c
upload-pack.c
index 85bba356fab7743506f00bb0c5ca955eb9112bd5..c3230817db4a7676eb74335b254f30597e66edd9 100644 (file)
@@ -828,14 +828,10 @@ static void execute_commands(struct command *commands,
                }
        }
 
-       if (shallow_update) {
-               if (!checked_connectivity)
-                       error("BUG: run 'git fsck' for safety.\n"
-                             "If there are errors, try to remove "
-                             "the reported refs above");
-               if (alt_shallow_file && *alt_shallow_file)
-                       unlink(alt_shallow_file);
-       }
+       if (shallow_update && !checked_connectivity)
+               error("BUG: run 'git fsck' for safety.\n"
+                     "If there are errors, try to remove "
+                     "the reported refs above");
 }
 
 static struct command *read_head_info(struct sha1_array *shallow)
@@ -1087,10 +1083,6 @@ static void update_shallow_info(struct command *commands,
                        cmd->skip_update = 1;
                }
        }
-       if (alt_shallow_file && *alt_shallow_file) {
-               unlink(alt_shallow_file);
-               alt_shallow_file = NULL;
-       }
        free(ref_status);
 }
 
index 16d9c4351395ac55d6856d8d92d24ce7064df974..55631f191f2a01276e8a16192117fb3cf25bc958 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -209,7 +209,7 @@ extern int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
 extern void setup_alternate_shallow(struct lock_file *shallow_lock,
                                    const char **alternate_shallow_file,
                                    const struct sha1_array *extra);
-extern char *setup_temporary_shallow(const struct sha1_array *extra);
+extern const char *setup_temporary_shallow(const struct sha1_array *extra);
 extern void advertise_shallow_grafts(int);
 
 struct shallow_info {
index 90fdd49821a1d6d3e104124444e37ac4b9b03fa2..ae8550eb48ae1c96dff2fcd1e47333cee7bc79fd 100644 (file)
@@ -947,17 +947,6 @@ static void update_shallow(struct fetch_pack_args *args,
        if (!si->shallow || !si->shallow->nr)
                return;
 
-       if (alternate_shallow_file) {
-               /*
-                * The temporary shallow file is only useful for
-                * index-pack and unpack-objects because it may
-                * contain more roots than we want. Delete it.
-                */
-               if (*alternate_shallow_file)
-                       unlink(alternate_shallow_file);
-               free((char *)alternate_shallow_file);
-       }
-
        if (args->cloning) {
                /*
                 * remote is shallow, but this is a clone, there are
index 1a6f022fa88bed0d29b10a1b79650ea6ff8ed44d..c7602ce3a2076f1ec0dfdfaee65a1810f45e5601 100644 (file)
--- a/shallow.c
+++ b/shallow.c
@@ -8,6 +8,7 @@
 #include "diff.h"
 #include "revision.h"
 #include "commit-slab.h"
+#include "sigchain.h"
 
 static int is_shallow = -1;
 static struct stat_validity shallow_stat;
@@ -206,27 +207,53 @@ int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
        return write_shallow_commits_1(out, use_pack_protocol, extra, 0);
 }
 
-char *setup_temporary_shallow(const struct sha1_array *extra)
+static struct strbuf temporary_shallow = STRBUF_INIT;
+
+static void remove_temporary_shallow(void)
+{
+       if (temporary_shallow.len) {
+               unlink_or_warn(temporary_shallow.buf);
+               strbuf_reset(&temporary_shallow);
+       }
+}
+
+static void remove_temporary_shallow_on_signal(int signo)
+{
+       remove_temporary_shallow();
+       sigchain_pop(signo);
+       raise(signo);
+}
+
+const char *setup_temporary_shallow(const struct sha1_array *extra)
 {
+       static int installed_handler;
        struct strbuf sb = STRBUF_INIT;
        int fd;
 
+       if (temporary_shallow.len)
+               die("BUG: attempt to create two temporary shallow files");
+
        if (write_shallow_commits(&sb, 0, extra)) {
-               struct strbuf path = STRBUF_INIT;
-               strbuf_addstr(&path, git_path("shallow_XXXXXX"));
-               fd = xmkstemp(path.buf);
+               strbuf_addstr(&temporary_shallow, git_path("shallow_XXXXXX"));
+               fd = xmkstemp(temporary_shallow.buf);
+
+               if (!installed_handler) {
+                       atexit(remove_temporary_shallow);
+                       sigchain_push_common(remove_temporary_shallow_on_signal);
+               }
+
                if (write_in_full(fd, sb.buf, sb.len) != sb.len)
                        die_errno("failed to write to %s",
-                                 path.buf);
+                                 temporary_shallow.buf);
                close(fd);
                strbuf_release(&sb);
-               return strbuf_detach(&path, NULL);
+               return temporary_shallow.buf;
        }
        /*
         * is_repository_shallow() sees empty string as "no shallow
         * file".
         */
-       return xstrdup("");
+       return temporary_shallow.buf;
 }
 
 void setup_alternate_shallow(struct lock_file *shallow_lock,
index 0c44f6b292563e7c87bce0b7b5d9b8a4ccd32ec3..a3c52f691da5e5ce95d70a9ed43cffd00f620ccd 100644 (file)
@@ -81,7 +81,7 @@ static void create_pack_file(void)
        const char *argv[12];
        int i, arg = 0;
        FILE *pipe_fd;
-       char *shallow_file = NULL;
+       const char *shallow_file = NULL;
 
        if (shallow_nr) {
                shallow_file = setup_temporary_shallow(NULL);
@@ -242,11 +242,6 @@ static void create_pack_file(void)
                error("git upload-pack: git-pack-objects died with error.");
                goto fail;
        }
-       if (shallow_file) {
-               if (*shallow_file)
-                       unlink(shallow_file);
-               free(shallow_file);
-       }
 
        /* flush the data */
        if (0 <= buffered) {