Documentation: bisect: add some titles to some paragraphs.
[gitweb.git] / index-pack.c
index 5f6d128a836f8ed9447f81280ae679e19c9939ff..61eb20e45b993a4dbd3da8954d6ca4bebb64ca13 100644 (file)
@@ -277,13 +277,19 @@ static void *get_data_from_pack(struct object_entry *obj)
 {
        unsigned long from = obj[0].offset + obj[0].hdr_size;
        unsigned long len = obj[1].offset - from;
+       unsigned long rdy = 0;
        unsigned char *src, *data;
        z_stream stream;
        int st;
 
        src = xmalloc(len);
-       if (pread(pack_fd, src, len, from) != len)
-               die("cannot pread pack file: %s", strerror(errno));
+       data = src;
+       do {
+               ssize_t n = pread(pack_fd, data + rdy, len - rdy, from + rdy);
+               if (n <= 0)
+                       die("cannot pread pack file: %s", strerror(errno));
+               rdy += n;
+       } while (rdy < len);
        data = xmalloc(obj->size);
        memset(&stream, 0, sizeof(stream));
        stream.next_out = data;
@@ -341,26 +347,18 @@ static int find_delta_children(const union delta_base *base,
 static void sha1_object(const void *data, unsigned long size,
                        enum object_type type, unsigned char *sha1)
 {
-       SHA_CTX ctx;
-       char header[50];
-       int header_size;
-       const char *type_str;
-
-       switch (type) {
-       case OBJ_COMMIT: type_str = commit_type; break;
-       case OBJ_TREE:   type_str = tree_type; break;
-       case OBJ_BLOB:   type_str = blob_type; break;
-       case OBJ_TAG:    type_str = tag_type; break;
-       default:
-               die("bad type %d", type);
+       hash_sha1_file(data, size, typename(type), sha1);
+       if (has_sha1_file(sha1)) {
+               void *has_data;
+               enum object_type has_type;
+               unsigned long has_size;
+               has_data = read_sha1_file(sha1, &has_type, &has_size);
+               if (!has_data)
+                       die("cannot read existing object %s", sha1_to_hex(sha1));
+               if (size != has_size || type != has_type ||
+                   memcmp(data, has_data, size) != 0)
+                       die("SHA1 COLLISION FOUND WITH %s !", sha1_to_hex(sha1));
        }
-
-       header_size = sprintf(header, "%s %lu", type_str, size) + 1;
-
-       SHA1_Init(&ctx);
-       SHA1_Update(&ctx, header, header_size);
-       SHA1_Update(&ctx, data, size);
-       SHA1_Final(sha1, &ctx);
 }
 
 static void resolve_delta(struct object_entry *delta_obj, void *base_data,
@@ -457,7 +455,8 @@ static void parse_pack_objects(unsigned char *sha1)
        /* If input_fd is a file, we should have reached its end now. */
        if (fstat(input_fd, &st))
                die("cannot fstat packfile: %s", strerror(errno));
-       if (S_ISREG(st.st_mode) && st.st_size != consumed_bytes)
+       if (S_ISREG(st.st_mode) &&
+                       lseek(input_fd, 0, SEEK_CUR) - input_len != st.st_size)
                die("pack has junk at the end");
 
        if (!nr_deltas)
@@ -540,7 +539,7 @@ static int write_compressed(int fd, void *in, unsigned int size)
        return size;
 }
 
-static void append_obj_to_pack(void *buf,
+static void append_obj_to_pack(const unsigned char *sha1, void *buf,
                               unsigned long size, enum object_type type)
 {
        struct object_entry *obj = &objects[nr_objects++];
@@ -558,7 +557,7 @@ static void append_obj_to_pack(void *buf,
        write_or_die(output_fd, header, n);
        obj[1].offset = obj[0].offset + n;
        obj[1].offset += write_compressed(output_fd, buf, size);
-       sha1_object(buf, size, type, obj->sha1);
+       hashcpy(obj->sha1, sha1);
 }
 
 static int delta_pos_compare(const void *_a, const void *_b)
@@ -595,30 +594,25 @@ static void fix_unresolved_deltas(int nr_unresolved)
                struct delta_entry *d = sorted_by_pos[i];
                void *data;
                unsigned long size;
-               char type[10];
-               enum object_type obj_type;
+               enum object_type type;
                int j, first, last;
 
                if (objects[d->obj_no].real_type != OBJ_REF_DELTA)
                        continue;
-               data = read_sha1_file(d->base.sha1, type, &size);
+               data = read_sha1_file(d->base.sha1, &type, &size);
                if (!data)
                        continue;
-               if      (!strcmp(type, blob_type))   obj_type = OBJ_BLOB;
-               else if (!strcmp(type, tree_type))   obj_type = OBJ_TREE;
-               else if (!strcmp(type, commit_type)) obj_type = OBJ_COMMIT;
-               else if (!strcmp(type, tag_type))    obj_type = OBJ_TAG;
-               else die("base object %s is of type '%s'",
-                        sha1_to_hex(d->base.sha1), type);
 
                find_delta_children(&d->base, &first, &last);
                for (j = first; j <= last; j++) {
                        struct object_entry *child = objects + deltas[j].obj_no;
                        if (child->real_type == OBJ_REF_DELTA)
-                               resolve_delta(child, data, size, obj_type);
+                               resolve_delta(child, data, size, type);
                }
 
-               append_obj_to_pack(data, size, obj_type);
+               if (check_sha1_signature(d->base.sha1, data, size, typename(type)))
+                       die("local object %s is corrupt", sha1_to_hex(d->base.sha1));
+               append_obj_to_pack(d->base.sha1, data, size, type);
                free(data);
                if (verbose)
                        percent = display_progress(nr_resolved_deltas,
@@ -638,7 +632,7 @@ static void readjust_pack_header_and_sha1(unsigned char *sha1)
        /* Rewrite pack header with updated object number */
        if (lseek(output_fd, 0, SEEK_SET) != 0)
                die("cannot seek back: %s", strerror(errno));
-       if (xread(output_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
+       if (read_in_full(output_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
                die("cannot read pack header back: %s", strerror(errno));
        hdr.hdr_entries = htonl(nr_objects);
        if (lseek(output_fd, 0, SEEK_SET) != 0)
@@ -753,7 +747,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
                  const char *keep_name, const char *keep_msg,
                  unsigned char *sha1)
 {
-       char *report = "pack";
+       const char *report = "pack";
        char name[PATH_MAX];
        int err;
 
@@ -814,7 +808,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
                char buf[48];
                int len = snprintf(buf, sizeof(buf), "%s\t%s\n",
                                   report, sha1_to_hex(sha1));
-               xwrite(1, buf, len);
+               write_or_die(1, buf, len);
 
                /*
                 * Let's just mimic git-unpack-objects here and write
@@ -849,9 +843,9 @@ int main(int argc, char **argv)
                                fix_thin_pack = 1;
                        } else if (!strcmp(arg, "--keep")) {
                                keep_msg = "";
-                       } else if (!strncmp(arg, "--keep=", 7)) {
+                       } else if (!prefixcmp(arg, "--keep=")) {
                                keep_msg = arg + 7;
-                       } else if (!strncmp(arg, "--pack_header=", 14)) {
+                       } else if (!prefixcmp(arg, "--pack_header=")) {
                                struct pack_header *hdr;
                                char *c;