[PATCH] Fix fd leak in git-cvsimport-script
[git.git] / sha1_file.c
index f3920c2..1747276 100644 (file)
@@ -102,9 +102,36 @@ char *get_index_file(void)
        return git_index_file;
 }
 
+char *git_path(const char *fmt, ...)
+{
+       static char pathname[PATH_MAX], *ret;
+       va_list args;
+       int len;
+
+       if (!git_dir)
+               setup_git_env();
+       len = strlen(git_dir);
+       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);
+       ret = pathname;
+
+       /* Clean it up */
+       if (!memcmp(pathname, "./", 2)) {
+               ret += 2;
+               while (*ret == '/')
+                       ret++;
+       }
+       return ret;
+}
+
 int get_sha1(const char *str, unsigned char *sha1)
 {
-       static char pathname[PATH_MAX];
        static const char *prefix[] = {
                "",
                "refs",
@@ -118,11 +145,8 @@ int get_sha1(const char *str, unsigned char *sha1)
        if (!get_sha1_hex(str, sha1))
                return 0;
 
-       if (!git_dir)
-               setup_git_env();
        for (p = prefix; *p; p++) {
-               snprintf(pathname, sizeof(pathname), "%s/%s/%s",
-                        git_dir, *p, str);
+               char * pathname = git_path("%s/%s", *p, str);
                if (!get_sha1_file(pathname, sha1))
                        return 0;
        }
@@ -294,6 +318,8 @@ static int check_packed_git_idx(const char *path, unsigned long *idx_size_,
                return -1;
 
        index = idx_map;
+       *idx_map_ = idx_map;
+       *idx_size_ = idx_size;
 
        /* check index map */
        if (idx_size < 4*256 + 20 + 20)
@@ -316,8 +342,6 @@ static int check_packed_git_idx(const char *path, unsigned long *idx_size_,
        if (idx_size != 4*256 + nr * 24 + 20 + 20)
                return error("wrong index file size");
 
-       *idx_map_ = idx_map;
-       *idx_size_ = idx_size;
        return 0;
 }
 
@@ -439,6 +463,7 @@ static void prepare_packed_git_one(char *objdir)
                p->next = packed_git;
                packed_git = p;
        }
+       closedir(dir);
 }
 
 void prepare_packed_git(void)
@@ -531,7 +556,7 @@ int unpack_sha1_header(z_stream *stream, void *map, unsigned long mapsize, void
        return inflate(stream, 0);
 }
 
-void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size)
+static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size)
 {
        int bytes = strlen(buffer) + 1;
        unsigned char *buf = xmalloc(1+size);
@@ -704,6 +729,57 @@ static unsigned long unpack_object_header(struct packed_git *p, unsigned long of
        return offset;
 }
 
+void packed_object_info_detail(struct pack_entry *e,
+                              char *type,
+                              unsigned long *size,
+                              unsigned long *store_size,
+                              int *delta_chain_length,
+                              unsigned char *base_sha1)
+{
+       struct packed_git *p = e->p;
+       unsigned long offset, left;
+       unsigned char *pack;
+       enum object_type kind;
+
+       offset = unpack_object_header(p, e->offset, &kind, size);
+       pack = p->pack_base + offset;
+       left = p->pack_size - offset;
+       if (kind != OBJ_DELTA)
+               *delta_chain_length = 0;
+       else {
+               int chain_length = 0;
+               memcpy(base_sha1, pack, 20);
+               do {
+                       struct pack_entry base_ent;
+                       unsigned long junk;
+
+                       find_pack_entry_one(pack, &base_ent, p);
+                       offset = unpack_object_header(p, base_ent.offset,
+                                                     &kind, &junk);
+                       pack = p->pack_base + offset;
+                       chain_length++;
+               } while (kind == OBJ_DELTA);
+               *delta_chain_length = chain_length;
+       }
+       switch (kind) {
+       case OBJ_COMMIT:
+               strcpy(type, "commit");
+               break;
+       case OBJ_TREE:
+               strcpy(type, "tree");
+               break;
+       case OBJ_BLOB:
+               strcpy(type, "blob");
+               break;
+       case OBJ_TAG:
+               strcpy(type, "tag");
+               break;
+       default:
+               die("corrupted pack file");
+       }
+       *store_size = 0; /* notyet */
+}
+
 static int packed_object_info(struct pack_entry *entry,
                              char *type, unsigned long *sizep)
 {
@@ -806,7 +882,7 @@ static void *unpack_non_delta_entry(unsigned char *data,
 {
        int st;
        z_stream stream;
-       char *buffer;
+       unsigned char *buffer;
 
        buffer = xmalloc(size + 1);
        buffer[size] = 0;
@@ -898,7 +974,7 @@ int nth_packed_object_sha1(const struct packed_git *p, int n,
 int find_pack_entry_one(const unsigned char *sha1,
                        struct pack_entry *e, struct packed_git *p)
 {
-       int *level1_ofs = p->index_base;
+       unsigned int *level1_ofs = p->index_base;
        int hi = ntohl(level1_ofs[*sha1]);
        int lo = ((*sha1 == 0x0) ? 0 : ntohl(level1_ofs[*sha1 - 1]));
        void *index = p->index_base + 256;
@@ -1216,6 +1292,12 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd)
        return 0;
 }
 
+int has_sha1_pack(const unsigned char *sha1)
+{
+       struct pack_entry e;
+       return find_pack_entry(sha1, &e);
+}
+
 int has_sha1_file(const unsigned char *sha1)
 {
        struct stat st;