[PATCH] write_sha1_to_fd()
[git/git.git] / sha1_file.c
index 74dc2aa..b13578b 100644 (file)
@@ -102,26 +102,23 @@ char *get_index_file(void)
        return git_index_file;
 }
 
-char *git_path(const char *fmt, ...)
+int safe_create_leading_directories(char *path)
 {
-       static char pathname[PATH_MAX];
-       va_list args;
-       int len;
+       char *pos = path;
 
-       if (!git_dir)
-               setup_git_env();
-       len = strlen(git_dir);
-       if (len == 1 && *git_dir == '.')
-               len = 0;
-       if (len > PATH_MAX-100)
-               return "pad-path";
-       memcpy(pathname, git_dir, len);
-       if (len && git_dir[len-1] != '/')
-               pathname[len++] = '/';
-       va_start(args, fmt);
-       vsnprintf(pathname + len, sizeof(pathname) - len, fmt, args);
-       va_end(args);
-       return pathname;
+       while (pos) {
+               pos = strchr(pos, '/');
+               if (!pos)
+                       break;
+               *pos = 0;
+               if (mkdir(path, 0777) < 0)
+                       if (errno != EEXIST) {
+                               *pos = '/';
+                               return -1;
+                       }
+               *pos++ = '/';
+       }
+       return 0;
 }
 
 int get_sha1(const char *str, unsigned char *sha1)
@@ -457,6 +454,7 @@ static void prepare_packed_git_one(char *objdir)
                p->next = packed_git;
                packed_git = p;
        }
+       closedir(dir);
 }
 
 void prepare_packed_git(void)
@@ -1102,12 +1100,12 @@ void *read_object_with_reference(const unsigned char *sha1,
        }
 }
 
-static char *write_sha1_file_prepare(void *buf,
-                                    unsigned long len,
-                                    const char *type,
-                                    unsigned char *sha1,
-                                    unsigned char *hdr,
-                                    int *hdrlen)
+char *write_sha1_file_prepare(void *buf,
+                             unsigned long len,
+                             const char *type,
+                             unsigned char *sha1,
+                             unsigned char *hdr,
+                             int *hdrlen)
 {
        SHA_CTX c;
 
@@ -1223,6 +1221,65 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
        return 0;
 }
 
+int write_sha1_to_fd(int fd, const unsigned char *sha1)
+{
+       ssize_t size;
+       unsigned long objsize;
+       int posn = 0;
+       char *buf = map_sha1_file_internal(sha1, &objsize, 0);
+       z_stream stream;
+       if (!buf) {
+               unsigned char *unpacked;
+               unsigned long len;
+               char type[20];
+               char hdr[50];
+               int hdrlen;
+               // need to unpack and recompress it by itself
+               unpacked = read_packed_sha1(sha1, type, &len);
+
+               hdrlen = sprintf(hdr, "%s %lu", type, len) + 1;
+
+               /* Set it up */
+               memset(&stream, 0, sizeof(stream));
+               deflateInit(&stream, Z_BEST_COMPRESSION);
+               size = deflateBound(&stream, len + hdrlen);
+               buf = xmalloc(size);
+
+               /* Compress it */
+               stream.next_out = buf;
+               stream.avail_out = size;
+               
+               /* First header.. */
+               stream.next_in = hdr;
+               stream.avail_in = hdrlen;
+               while (deflate(&stream, 0) == Z_OK)
+                       /* nothing */;
+
+               /* Then the data itself.. */
+               stream.next_in = unpacked;
+               stream.avail_in = len;
+               while (deflate(&stream, Z_FINISH) == Z_OK)
+                       /* nothing */;
+               deflateEnd(&stream);
+               
+               objsize = stream.total_out;
+       }
+
+       do {
+               size = write(fd, buf + posn, objsize - posn);
+               if (size <= 0) {
+                       if (!size) {
+                               fprintf(stderr, "write closed");
+                       } else {
+                               perror("write ");
+                       }
+                       return -1;
+               }
+               posn += size;
+       } while (posn < objsize);
+       return 0;
+}
+
 int write_sha1_from_fd(const unsigned char *sha1, int fd)
 {
        char *filename = sha1_file_name(sha1);
@@ -1301,11 +1358,13 @@ int has_sha1_file(const unsigned char *sha1)
        return find_pack_entry(sha1, &e);
 }
 
-int index_fd(unsigned char *sha1, int fd, struct stat *st)
+int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type)
 {
        unsigned long size = st->st_size;
        void *buf;
        int ret;
+       unsigned char hdr[50];
+       int hdrlen;
 
        buf = "";
        if (size)
@@ -1314,7 +1373,14 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st)
        if ((int)(long)buf == -1)
                return -1;
 
-       ret = write_sha1_file(buf, size, "blob", sha1);
+       if (!type)
+               type = "blob";
+       if (write_object)
+               ret = write_sha1_file(buf, size, type, sha1);
+       else {
+               write_sha1_file_prepare(buf, size, type, sha1, hdr, &hdrlen);
+               ret = 0;
+       }
        if (size)
                munmap(buf, size);
        return ret;