fetch-clone.con commit Merge git://git.kernel.org/pub/scm/gitk/gitk (90768da)
   1#include "cache.h"
   2#include "exec_cmd.h"
   3#include <sys/wait.h>
   4
   5static int finish_pack(const char *pack_tmp_name, const char *me)
   6{
   7        int pipe_fd[2];
   8        pid_t pid;
   9        char idx[PATH_MAX];
  10        char final[PATH_MAX];
  11        char hash[41];
  12        unsigned char sha1[20];
  13        char *cp;
  14        int err = 0;
  15
  16        if (pipe(pipe_fd) < 0)
  17                die("%s: unable to set up pipe", me);
  18
  19        strcpy(idx, pack_tmp_name); /* ".git/objects/pack-XXXXXX" */
  20        cp = strrchr(idx, '/');
  21        memcpy(cp, "/pidx", 5);
  22
  23        pid = fork();
  24        if (pid < 0)
  25                die("git-clone-pack: unable to fork off git-index-pack");
  26        if (!pid) {
  27                close(0);
  28                dup2(pipe_fd[1], 1);
  29                close(pipe_fd[0]);
  30                close(pipe_fd[1]);
  31                execl_git_cmd("index-pack", "-o", idx, pack_tmp_name, NULL);
  32                error("cannot exec git-index-pack <%s> <%s>",
  33                      idx, pack_tmp_name);
  34                exit(1);
  35        }
  36        close(pipe_fd[1]);
  37        if (read(pipe_fd[0], hash, 40) != 40) {
  38                error("%s: unable to read from git-index-pack", me);
  39                err = 1;
  40        }
  41        close(pipe_fd[0]);
  42
  43        for (;;) {
  44                int status, code;
  45                int retval = waitpid(pid, &status, 0);
  46
  47                if (retval < 0) {
  48                        if (errno == EINTR)
  49                                continue;
  50                        error("waitpid failed (%s)", strerror(errno));
  51                        goto error_die;
  52                }
  53                if (WIFSIGNALED(status)) {
  54                        int sig = WTERMSIG(status);
  55                        error("git-index-pack died of signal %d", sig);
  56                        goto error_die;
  57                }
  58                if (!WIFEXITED(status)) {
  59                        error("git-index-pack died of unnatural causes %d",
  60                              status);
  61                        goto error_die;
  62                }
  63                code = WEXITSTATUS(status);
  64                if (code) {
  65                        error("git-index-pack died with error code %d", code);
  66                        goto error_die;
  67                }
  68                if (err)
  69                        goto error_die;
  70                break;
  71        }
  72        hash[40] = 0;
  73        if (get_sha1_hex(hash, sha1)) {
  74                error("git-index-pack reported nonsense '%s'", hash);
  75                goto error_die;
  76        }
  77        /* Now we have pack in pack_tmp_name[], and
  78         * idx in idx[]; rename them to their final names.
  79         */
  80        snprintf(final, sizeof(final),
  81                 "%s/pack/pack-%s.pack", get_object_directory(), hash);
  82        move_temp_to_file(pack_tmp_name, final);
  83        chmod(final, 0444);
  84        snprintf(final, sizeof(final),
  85                 "%s/pack/pack-%s.idx", get_object_directory(), hash);
  86        move_temp_to_file(idx, final);
  87        chmod(final, 0444);
  88        return 0;
  89
  90 error_die:
  91        unlink(idx);
  92        unlink(pack_tmp_name);
  93        exit(1);
  94}
  95
  96int receive_unpack_pack(int fd[2], const char *me, int quiet)
  97{
  98        int status;
  99        pid_t pid;
 100
 101        pid = fork();
 102        if (pid < 0)
 103                die("%s: unable to fork off git-unpack-objects", me);
 104        if (!pid) {
 105                dup2(fd[0], 0);
 106                close(fd[0]);
 107                close(fd[1]);
 108                execl_git_cmd("unpack-objects", quiet ? "-q" : NULL, NULL);
 109                die("git-unpack-objects exec failed");
 110        }
 111        close(fd[0]);
 112        close(fd[1]);
 113        while (waitpid(pid, &status, 0) < 0) {
 114                if (errno != EINTR)
 115                        die("waiting for git-unpack-objects: %s",
 116                            strerror(errno));
 117        }
 118        if (WIFEXITED(status)) {
 119                int code = WEXITSTATUS(status);
 120                if (code)
 121                        die("git-unpack-objects died with error code %d",
 122                            code);
 123                return 0;
 124        }
 125        if (WIFSIGNALED(status)) {
 126                int sig = WTERMSIG(status);
 127                die("git-unpack-objects died of signal %d", sig);
 128        }
 129        die("git-unpack-objects died of unnatural causes %d", status);
 130}
 131
 132int receive_keep_pack(int fd[2], const char *me)
 133{
 134        char tmpfile[PATH_MAX];
 135        int ofd, ifd;
 136
 137        ifd = fd[0];
 138        snprintf(tmpfile, sizeof(tmpfile),
 139                 "%s/pack/tmp-XXXXXX", get_object_directory());
 140        ofd = mkstemp(tmpfile);
 141        if (ofd < 0)
 142                return error("unable to create temporary file %s", tmpfile);
 143
 144        while (1) {
 145                char buf[8192];
 146                ssize_t sz, wsz, pos;
 147                sz = read(ifd, buf, sizeof(buf));
 148                if (sz == 0)
 149                        break;
 150                if (sz < 0) {
 151                        error("error reading pack (%s)", strerror(errno));
 152                        close(ofd);
 153                        unlink(tmpfile);
 154                        return -1;
 155                }
 156                pos = 0;
 157                while (pos < sz) {
 158                        wsz = write(ofd, buf + pos, sz - pos);
 159                        if (wsz < 0) {
 160                                error("error writing pack (%s)",
 161                                      strerror(errno));
 162                                close(ofd);
 163                                unlink(tmpfile);
 164                                return -1;
 165                        }
 166                        pos += wsz;
 167                }
 168        }
 169        close(ofd);
 170        return finish_pack(tmpfile, me);
 171}