Merge branch 'sb/submodule-rm-absorb'
[gitweb.git] / bundle.c
index b9dacc0241f0c58244b62ddff137c85291c37dd0..d15db03c84556af8a47783f4d4ee76379d721020 100644 (file)
--- a/bundle.c
+++ b/bundle.c
 
 static const char bundle_signature[] = "# v2 git bundle\n";
 
-static void add_to_ref_list(const unsigned char *sha1, const char *name,
+static void add_to_ref_list(const struct object_id *oid, const char *name,
                struct ref_list *list)
 {
        ALLOC_GROW(list->list, list->nr + 1, list->alloc);
-       hashcpy(list->list[list->nr].sha1, sha1);
+       oidcpy(&list->list[list->nr].oid, oid);
        list->list[list->nr].name = xstrdup(name);
        list->nr++;
 }
@@ -40,8 +40,9 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
        /* The bundle header ends with an empty line */
        while (!strbuf_getwholeline_fd(&buf, fd, '\n') &&
               buf.len && buf.buf[0] != '\n') {
-               unsigned char sha1[20];
+               struct object_id oid;
                int is_prereq = 0;
+               const char *p;
 
                if (*buf.buf == '-') {
                        is_prereq = 1;
@@ -54,9 +55,9 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
                 * Prerequisites have object name that is optionally
                 * followed by SP and subject line.
                 */
-               if (get_sha1_hex(buf.buf, sha1) ||
-                   (buf.len > 40 && !isspace(buf.buf[40])) ||
-                   (!is_prereq && buf.len <= 40)) {
+               if (parse_oid_hex(buf.buf, &oid, &p) ||
+                   (*p && !isspace(*p)) ||
+                   (!is_prereq && !*p)) {
                        if (report_path)
                                error(_("unrecognized header: %s%s (%d)"),
                                      (is_prereq ? "-" : ""), buf.buf, (int)buf.len);
@@ -64,9 +65,9 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
                        break;
                } else {
                        if (is_prereq)
-                               add_to_ref_list(sha1, "", &header->prerequisites);
+                               add_to_ref_list(&oid, "", &header->prerequisites);
                        else
-                               add_to_ref_list(sha1, buf.buf + 41, &header->references);
+                               add_to_ref_list(&oid, p + 1, &header->references);
                }
        }
 
@@ -115,7 +116,7 @@ static int list_refs(struct ref_list *r, int argc, const char **argv)
                        if (j == argc)
                                continue;
                }
-               printf("%s %s\n", sha1_to_hex(r->list[i].sha1),
+               printf("%s %s\n", oid_to_hex(&r->list[i].oid),
                                r->list[i].name);
        }
        return 0;
@@ -141,7 +142,7 @@ int verify_bundle(struct bundle_header *header, int verbose)
        init_revisions(&revs, NULL);
        for (i = 0; i < p->nr; i++) {
                struct ref_list_entry *e = p->list + i;
-               struct object *o = parse_object(e->sha1);
+               struct object *o = parse_object(&e->oid);
                if (o) {
                        o->flags |= PREREQ_MARK;
                        add_pending_object(&revs, o, e->name);
@@ -149,7 +150,7 @@ int verify_bundle(struct bundle_header *header, int verbose)
                }
                if (++ret == 1)
                        error("%s", message);
-               error("%s %s", sha1_to_hex(e->sha1), e->name);
+               error("%s %s", oid_to_hex(&e->oid), e->name);
        }
        if (revs.pending.nr != p->nr)
                return ret;
@@ -171,7 +172,7 @@ int verify_bundle(struct bundle_header *header, int verbose)
                if (!(refs.objects[i].item->flags & SHOWN)) {
                        if (++ret == 1)
                                error("%s", message);
-                       error("%s %s", sha1_to_hex(refs.objects[i].item->sha1),
+                       error("%s %s", oid_to_hex(&refs.objects[i].item->oid),
                                refs.objects[i].name);
                }
 
@@ -211,13 +212,13 @@ static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)
        unsigned long size;
        enum object_type type;
        char *buf = NULL, *line, *lineend;
-       unsigned long date;
+       timestamp_t date;
        int result = 1;
 
        if (revs->max_age == -1 && revs->min_age == -1)
                goto out;
 
-       buf = read_sha1_file(tag->sha1, &type, &size);
+       buf = read_sha1_file(tag->oid.hash, &type, &size);
        if (!buf)
                goto out;
        line = memmem(buf, size, "\ntagger ", 8);
@@ -227,7 +228,7 @@ static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)
        line = memchr(line, '>', lineend ? lineend - line : buf + size - line);
        if (!line++)
                goto out;
-       date = strtoul(line, NULL, 10);
+       date = parse_timestamp(line, NULL, 10);
        result = (revs->max_age == -1 || revs->max_age < date) &&
                (revs->min_age == -1 || revs->min_age > date);
 out:
@@ -256,7 +257,7 @@ static int write_pack_data(int bundle_fd, struct rev_info *revs)
                struct object *object = revs->pending.objects[i].item;
                if (object->flags & UNINTERESTING)
                        write_or_die(pack_objects.in, "^", 1);
-               write_or_die(pack_objects.in, sha1_to_hex(object->sha1), 40);
+               write_or_die(pack_objects.in, oid_to_hex(&object->oid), GIT_SHA1_HEXSZ);
                write_or_die(pack_objects.in, "\n", 1);
        }
        close(pack_objects.in);
@@ -285,16 +286,18 @@ static int compute_and_write_prerequisites(int bundle_fd,
                return -1;
        rls_fout = xfdopen(rls.out, "r");
        while (strbuf_getwholeline(&buf, rls_fout, '\n') != EOF) {
-               unsigned char sha1[20];
+               struct object_id oid;
                if (buf.len > 0 && buf.buf[0] == '-') {
                        write_or_die(bundle_fd, buf.buf, buf.len);
-                       if (!get_sha1_hex(buf.buf + 1, sha1)) {
-                               struct object *object = parse_object_or_die(sha1, buf.buf);
+                       if (!get_oid_hex(buf.buf + 1, &oid)) {
+                               struct object *object = parse_object_or_die(&oid,
+                                                                           buf.buf);
                                object->flags |= UNINTERESTING;
                                add_pending_object(revs, object, buf.buf);
                        }
-               } else if (!get_sha1_hex(buf.buf, sha1)) {
-                       struct object *object = parse_object_or_die(sha1, buf.buf);
+               } else if (!get_oid_hex(buf.buf, &oid)) {
+                       struct object *object = parse_object_or_die(&oid,
+                                                                   buf.buf);
                        object->flags |= SHOWN;
                }
        }
@@ -321,16 +324,16 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
 
        for (i = 0; i < revs->pending.nr; i++) {
                struct object_array_entry *e = revs->pending.objects + i;
-               unsigned char sha1[20];
+               struct object_id oid;
                char *ref;
                const char *display_ref;
                int flag;
 
                if (e->item->flags & UNINTERESTING)
                        continue;
-               if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)
+               if (dwim_ref(e->name, strlen(e->name), oid.hash, &ref) != 1)
                        goto skip_write_ref;
-               if (read_ref_full(e->name, RESOLVE_REF_READING, sha1, &flag))
+               if (read_ref_full(e->name, RESOLVE_REF_READING, oid.hash, &flag))
                        flag = 0;
                display_ref = (flag & REF_ISSYMREF) ? e->name : ref;
 
@@ -360,13 +363,13 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
                 * commit that is referenced by the tag, and not the tag
                 * itself.
                 */
-               if (hashcmp(sha1, e->item->sha1)) {
+               if (oidcmp(&oid, &e->item->oid)) {
                        /*
                         * Is this the positive end of a range expressed
                         * in terms of a tag (e.g. v2.0 from the range
                         * "v1.0..v2.0")?
                         */
-                       struct commit *one = lookup_commit_reference(sha1);
+                       struct commit *one = lookup_commit_reference(&oid);
                        struct object *obj;
 
                        if (e->item == &(one->object)) {
@@ -378,7 +381,7 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
                                 * end up triggering "empty bundle"
                                 * error.
                                 */
-                               obj = parse_object_or_die(sha1, e->name);
+                               obj = parse_object_or_die(&oid, e->name);
                                obj->flags |= SHOWN;
                                add_pending_object(revs, obj, e->name);
                        }
@@ -386,7 +389,7 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
                }
 
                ref_count++;
-               write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);
+               write_or_die(bundle_fd, oid_to_hex(&e->item->oid), 40);
                write_or_die(bundle_fd, " ", 1);
                write_or_die(bundle_fd, display_ref, strlen(display_ref));
                write_or_die(bundle_fd, "\n", 1);
@@ -435,12 +438,14 @@ int create_bundle(struct bundle_header *header, const char *path,
 
        /* write prerequisites */
        if (compute_and_write_prerequisites(bundle_fd, &revs, argc, argv))
-               return -1;
+               goto err;
 
        argc = setup_revisions(argc, argv, &revs, NULL);
 
-       if (argc > 1)
-               return error(_("unrecognized argument: %s"), argv[1]);
+       if (argc > 1) {
+               error(_("unrecognized argument: %s"), argv[1]);
+               goto err;
+       }
 
        object_array_remove_duplicates(&revs.pending);
 
@@ -448,17 +453,26 @@ int create_bundle(struct bundle_header *header, const char *path,
        if (!ref_count)
                die(_("Refusing to create empty bundle."));
        else if (ref_count < 0)
-               return -1;
+               goto err;
 
        /* write pack */
-       if (write_pack_data(bundle_fd, &revs))
-               return -1;
+       if (write_pack_data(bundle_fd, &revs)) {
+               bundle_fd = -1; /* already closed by the above call */
+               goto err;
+       }
 
        if (!bundle_to_stdout) {
                if (commit_lock_file(&lock))
                        die_errno(_("cannot create '%s'"), path);
        }
        return 0;
+err:
+       if (!bundle_to_stdout) {
+               if (0 <= bundle_fd)
+                       close(bundle_fd);
+               rollback_lock_file(&lock);
+       }
+       return -1;
 }
 
 int unbundle(struct bundle_header *header, int bundle_fd, int flags)