From: Junio C Hamano Date: Fri, 30 Mar 2018 19:42:08 +0000 (-0700) Subject: Merge branch 'sb/packfiles-in-repository' into next X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/caa68db14?hp=-c Merge branch 'sb/packfiles-in-repository' into next Refactoring of the internal global data structure continues. * sb/packfiles-in-repository: packfile: keep prepare_packed_git() private packfile: allow find_pack_entry to handle arbitrary repositories packfile: add repository argument to find_pack_entry packfile: allow reprepare_packed_git to handle arbitrary repositories packfile: allow prepare_packed_git to handle arbitrary repositories packfile: allow prepare_packed_git_one to handle arbitrary repositories packfile: add repository argument to reprepare_packed_git packfile: add repository argument to prepare_packed_git packfile: add repository argument to prepare_packed_git_one packfile: allow install_packed_git to handle arbitrary repositories packfile: allow rearrange_packed_git to handle arbitrary repositories packfile: allow prepare_packed_git_mru to handle arbitrary repositories --- caa68db14db9f582fb6802d6d3c880bb7760ad52 diff --combined builtin/fsck.c index 13c0a8048e,f9632353d9..087360a675 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@@ -67,12 -67,12 +67,12 @@@ static const char *printable_type(struc const char *ret; if (obj->type == OBJ_NONE) { - enum object_type type = sha1_object_info(obj->oid.hash, NULL); + enum object_type type = oid_object_info(&obj->oid, NULL); if (type > 0) object_as_type(obj, type, 0); } - ret = typename(obj->type); + ret = type_name(obj->type); if (!ret) ret = "unknown"; @@@ -139,7 -139,7 +139,7 @@@ static int mark_object(struct object *o printf("broken link from %7s %s\n", printable_type(parent), describe_object(parent)); printf("broken link from %7s %s\n", - (type == OBJ_ANY ? "unknown" : typename(type)), "unknown"); + (type == OBJ_ANY ? "unknown" : type_name(type)), "unknown"); errors_found |= ERROR_REACHABLE; return 1; } @@@ -182,13 -182,7 +182,13 @@@ static void mark_object_reachable(struc static int traverse_one_object(struct object *obj) { - return fsck_walk(obj, obj, &fsck_walk_options); + int result = fsck_walk(obj, obj, &fsck_walk_options); + + if (obj->type == OBJ_TREE) { + struct tree *tree = (struct tree *)obj; + free_tree_buffer(tree); + } + return result; } static int traverse_reachable(void) @@@ -515,7 -509,7 +515,7 @@@ static struct object *parse_loose_objec unsigned long size; int eaten; - if (read_loose_object(path, oid->hash, &type, &size, &contents) < 0) + if (read_loose_object(path, oid, &type, &size, &contents) < 0) return NULL; if (!contents && type != OBJ_BLOB) @@@ -735,8 -729,6 +735,6 @@@ int cmd_fsck(int argc, const char **arg uint32_t total = 0, count = 0; struct progress *progress = NULL; - prepare_packed_git(); - if (show_progress) { for (p = get_packed_git(the_repository); p; p = p->next) { diff --combined builtin/gc.c index cef38e5427,0a667972ab..3e67124eaa --- a/builtin/gc.c +++ b/builtin/gc.c @@@ -174,7 -174,6 +174,6 @@@ static int too_many_packs(void if (gc_auto_pack_limit <= 0) return 0; - prepare_packed_git(); for (cnt = 0, p = get_packed_git(the_repository); p; p = p->next) { if (!p->pack_local) continue; @@@ -362,11 -361,8 +361,11 @@@ int cmd_gc(int argc, const char **argv N_("prune unreferenced objects"), PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire }, OPT_BOOL(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")), - OPT_BOOL(0, "auto", &auto_gc, N_("enable auto-gc mode")), - OPT_BOOL(0, "force", &force, N_("force running gc even if there may be another gc running")), + OPT_BOOL_F(0, "auto", &auto_gc, N_("enable auto-gc mode"), + PARSE_OPT_NOCOMPLETE), + OPT_BOOL_F(0, "force", &force, + N_("force running gc even if there may be another gc running"), + PARSE_OPT_NOCOMPLETE), OPT_END() }; @@@ -481,7 -477,7 +480,7 @@@ return error(FAILED_RUN, rerere.argv[0]); report_garbage = report_pack_garbage; - reprepare_packed_git(); + reprepare_packed_git(the_repository); if (pack_garbage.nr > 0) clean_pack_garbage(); diff --combined builtin/pack-objects.c index 89f49bb5f6,2f49b03cb1..4bdae5a1d8 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@@ -124,10 -124,11 +124,10 @@@ static void *get_delta(struct object_en void *buf, *base_buf, *delta_buf; enum object_type type; - buf = read_sha1_file(entry->idx.oid.hash, &type, &size); + buf = read_object_file(&entry->idx.oid, &type, &size); if (!buf) die("unable to read %s", oid_to_hex(&entry->idx.oid)); - base_buf = read_sha1_file(entry->delta->idx.oid.hash, &type, - &base_size); + base_buf = read_object_file(&entry->delta->idx.oid, &type, &base_size); if (!base_buf) die("unable to read %s", oid_to_hex(&entry->delta->idx.oid)); @@@ -165,7 -166,7 +165,7 @@@ static unsigned long do_compress(void * return stream.total_out; } -static unsigned long write_large_blob_data(struct git_istream *st, struct sha1file *f, +static unsigned long write_large_blob_data(struct git_istream *st, struct hashfile *f, const struct object_id *oid) { git_zstream stream; @@@ -189,7 -190,7 +189,7 @@@ stream.next_out = obuf; stream.avail_out = sizeof(obuf); zret = git_deflate(&stream, readlen ? 0 : Z_FINISH); - sha1write(f, obuf, stream.next_out - obuf); + hashwrite(f, obuf, stream.next_out - obuf); olen += stream.next_out - obuf; } if (stream.avail_in) @@@ -234,7 -235,7 +234,7 @@@ static int check_pack_inflate(struct pa stream.total_in == len) ? 0 : -1; } -static void copy_pack_data(struct sha1file *f, +static void copy_pack_data(struct hashfile *f, struct packed_git *p, struct pack_window **w_curs, off_t offset, @@@ -247,14 -248,14 +247,14 @@@ in = use_pack(p, w_curs, offset, &avail); if (avail > len) avail = (unsigned long)len; - sha1write(f, in, avail); + hashwrite(f, in, avail); offset += avail; len -= avail; } } /* Return 0 if we will bust the pack-size limit */ -static unsigned long write_no_reuse_object(struct sha1file *f, struct object_entry *entry, +static unsigned long write_no_reuse_object(struct hashfile *f, struct object_entry *entry, unsigned long limit, int usable_delta) { unsigned long size, datalen; @@@ -268,10 -269,11 +268,10 @@@ if (!usable_delta) { if (entry->type == OBJ_BLOB && entry->size > big_file_threshold && - (st = open_istream(entry->idx.oid.hash, &type, &size, NULL)) != NULL) + (st = open_istream(&entry->idx.oid, &type, &size, NULL)) != NULL) buf = NULL; else { - buf = read_sha1_file(entry->idx.oid.hash, &type, - &size); + buf = read_object_file(&entry->idx.oid, &type, &size); if (!buf) die(_("unable to read %s"), oid_to_hex(&entry->idx.oid)); @@@ -326,8 -328,8 +326,8 @@@ free(buf); return 0; } - sha1write(f, header, hdrlen); - sha1write(f, dheader + pos, sizeof(dheader) - pos); + hashwrite(f, header, hdrlen); + hashwrite(f, dheader + pos, sizeof(dheader) - pos); hdrlen += sizeof(dheader) - pos; } else if (type == OBJ_REF_DELTA) { /* @@@ -340,8 -342,8 +340,8 @@@ free(buf); return 0; } - sha1write(f, header, hdrlen); - sha1write(f, entry->delta->idx.oid.hash, 20); + hashwrite(f, header, hdrlen); + hashwrite(f, entry->delta->idx.oid.hash, 20); hdrlen += 20; } else { if (limit && hdrlen + datalen + 20 >= limit) { @@@ -350,13 -352,13 +350,13 @@@ free(buf); return 0; } - sha1write(f, header, hdrlen); + hashwrite(f, header, hdrlen); } if (st) { datalen = write_large_blob_data(st, f, &entry->idx.oid); close_istream(st); } else { - sha1write(f, buf, datalen); + hashwrite(f, buf, datalen); free(buf); } @@@ -364,7 -366,7 +364,7 @@@ } /* Return 0 if we will bust the pack-size limit */ -static off_t write_reuse_object(struct sha1file *f, struct object_entry *entry, +static off_t write_reuse_object(struct hashfile *f, struct object_entry *entry, unsigned long limit, int usable_delta) { struct packed_git *p = entry->in_pack; @@@ -415,8 -417,8 +415,8 @@@ unuse_pack(&w_curs); return 0; } - sha1write(f, header, hdrlen); - sha1write(f, dheader + pos, sizeof(dheader) - pos); + hashwrite(f, header, hdrlen); + hashwrite(f, dheader + pos, sizeof(dheader) - pos); hdrlen += sizeof(dheader) - pos; reused_delta++; } else if (type == OBJ_REF_DELTA) { @@@ -424,8 -426,8 +424,8 @@@ unuse_pack(&w_curs); return 0; } - sha1write(f, header, hdrlen); - sha1write(f, entry->delta->idx.oid.hash, 20); + hashwrite(f, header, hdrlen); + hashwrite(f, entry->delta->idx.oid.hash, 20); hdrlen += 20; reused_delta++; } else { @@@ -433,7 -435,7 +433,7 @@@ unuse_pack(&w_curs); return 0; } - sha1write(f, header, hdrlen); + hashwrite(f, header, hdrlen); } copy_pack_data(f, p, &w_curs, offset, datalen); unuse_pack(&w_curs); @@@ -442,7 -444,7 +442,7 @@@ } /* Return 0 if we will bust the pack-size limit */ -static off_t write_object(struct sha1file *f, +static off_t write_object(struct hashfile *f, struct object_entry *entry, off_t write_offset) { @@@ -515,7 -517,7 +515,7 @@@ enum write_one_status WRITE_ONE_RECURSIVE = 2 /* already scheduled to be written */ }; -static enum write_one_status write_one(struct sha1file *f, +static enum write_one_status write_one(struct hashfile *f, struct object_entry *e, off_t *offset) { @@@ -734,7 -736,7 +734,7 @@@ static struct object_entry **compute_wr return wo; } -static off_t write_reused_pack(struct sha1file *f) +static off_t write_reused_pack(struct hashfile *f) { unsigned char buffer[8192]; off_t to_write, total; @@@ -765,7 -767,7 +765,7 @@@ if (read_pack > to_write) read_pack = to_write; - sha1write(f, buffer, read_pack); + hashwrite(f, buffer, read_pack); to_write -= read_pack; /* @@@ -794,7 -796,7 +794,7 @@@ static const char no_split_warning[] = static void write_pack_file(void) { uint32_t i = 0, j; - struct sha1file *f; + struct hashfile *f; off_t offset; uint32_t nr_remaining = nr_result; time_t last_mtime = 0; @@@ -810,7 -812,7 +810,7 @@@ char *pack_tmp_name = NULL; if (pack_to_stdout) - f = sha1fd_throughput(1, "", progress_state); + f = hashfd_throughput(1, "", progress_state); else f = create_tmp_packfile(&pack_tmp_name); @@@ -837,11 -839,11 +837,11 @@@ * If so, rewrite it like in fast-import */ if (pack_to_stdout) { - sha1close(f, oid.hash, CSUM_CLOSE); + hashclose(f, oid.hash, CSUM_CLOSE); } else if (nr_written == nr_remaining) { - sha1close(f, oid.hash, CSUM_FSYNC); + hashclose(f, oid.hash, CSUM_FSYNC); } else { - int fd = sha1close(f, oid.hash, 0); + int fd = hashclose(f, oid.hash, 0); fixup_pack_header_footer(fd, oid.hash, pack_tmp_name, nr_written, oid.hash, offset); close(fd); @@@ -1190,7 -1192,7 +1190,7 @@@ static struct pbase_tree_cache *pbase_t /* Did not find one. Either we got a bogus request or * we need to read and perhaps cache. */ - data = read_sha1_file(oid->hash, &type, &size); + data = read_object_file(oid, &type, &size); if (!data) return NULL; if (type != OBJ_TREE) { @@@ -1351,7 -1353,7 +1351,7 @@@ static void add_preferred_base(struct o if (window <= num_preferred_base++) return; - data = read_object_with_reference(oid->hash, tree_type, &size, tree_oid.hash); + data = read_object_with_reference(oid, tree_type, &size, &tree_oid); if (!data) return; @@@ -1379,10 -1381,10 +1379,10 @@@ static void cleanup_preferred_base(void it = pbase_tree; pbase_tree = NULL; while (it) { - struct pbase_tree *this = it; - it = this->next; - free(this->pcache.tree_data); - free(this); + struct pbase_tree *tmp = it; + it = tmp->next; + free(tmp->pcache.tree_data); + free(tmp); } for (i = 0; i < ARRAY_SIZE(pbase_tree_cache); i++) { @@@ -1516,7 -1518,7 +1516,7 @@@ static void check_object(struct object_ unuse_pack(&w_curs); } - entry->type = sha1_object_info(entry->idx.oid.hash, &entry->size); + entry->type = oid_object_info(&entry->idx.oid, &entry->size); /* * The error condition is checked in prepare_pack(). This is * to permit a missing preferred base object to be ignored @@@ -1578,7 -1580,8 +1578,7 @@@ static void drop_reused_delta(struct ob * And if that fails, the error will be recorded in entry->type * and dealt with in prepare_pack(). */ - entry->type = sha1_object_info(entry->idx.oid.hash, - &entry->size); + entry->type = oid_object_info(&entry->idx.oid, &entry->size); } } @@@ -1870,7 -1873,8 +1870,7 @@@ static int try_delta(struct unpacked *t /* Load data if not already done */ if (!trg->data) { read_lock(); - trg->data = read_sha1_file(trg_entry->idx.oid.hash, &type, - &sz); + trg->data = read_object_file(&trg_entry->idx.oid, &type, &sz); read_unlock(); if (!trg->data) die("object %s cannot be read", @@@ -1883,7 -1887,8 +1883,7 @@@ } if (!src->data) { read_lock(); - src->data = read_sha1_file(src_entry->idx.oid.hash, &type, - &sz); + src->data = read_object_file(&src_entry->idx.oid, &type, &sz); read_unlock(); if (!src->data) { if (src_entry->preferred_base) { @@@ -2546,7 -2551,6 +2546,7 @@@ static void read_object_list_from_stdin } } +/* Remember to update object flag allocation in object.h */ #define OBJECT_ADDED (1u<<20) static void show_commit(struct commit *commit, void *data) @@@ -2706,7 -2710,7 +2706,7 @@@ static void add_objects_in_unpacked_pac static int add_loose_object(const struct object_id *oid, const char *path, void *data) { - enum object_type type = sha1_object_info(oid->hash, NULL); + enum object_type type = oid_object_info(oid, NULL); if (type < 0) { warning("loose object at %s could not be examined", path); @@@ -2792,7 -2796,7 +2792,7 @@@ static void loosen_unused_packed_object if (!packlist_find(&to_pack, oid.hash, NULL) && !has_sha1_pack_kept_or_nonlocal(&oid) && !loosened_object_can_be_discarded(&oid, p->mtime)) - if (force_object_loose(oid.hash, p->mtime)) + if (force_object_loose(&oid, p->mtime)) die("unable to force loose object"); } } @@@ -3148,7 -3152,6 +3148,6 @@@ int cmd_pack_objects(int argc, const ch if (progress && all_progress_implied) progress = 2; - prepare_packed_git(); if (ignore_packed_keep) { struct packed_git *p; for (p = get_packed_git(the_repository); p; p = p->next) diff --combined builtin/pack-redundant.c index f060b941b5,710cd0fb69..354478a127 --- a/builtin/pack-redundant.c +++ b/builtin/pack-redundant.c @@@ -50,17 -50,17 +50,17 @@@ static inline void llist_item_put(struc static inline struct llist_item *llist_item_get(void) { - struct llist_item *new; + struct llist_item *new_item; if ( free_nodes ) { - new = free_nodes; + new_item = free_nodes; free_nodes = free_nodes->next; } else { int i = 1; - ALLOC_ARRAY(new, BLKSIZE); + ALLOC_ARRAY(new_item, BLKSIZE); for (; i < BLKSIZE; i++) - llist_item_put(&new[i]); + llist_item_put(&new_item[i]); } - return new; + return new_item; } static void llist_free(struct llist *list) @@@ -82,26 -82,26 +82,26 @@@ static inline void llist_init(struct ll static struct llist * llist_copy(struct llist *list) { struct llist *ret; - struct llist_item *new, *old, *prev; + struct llist_item *new_item, *old_item, *prev; llist_init(&ret); if ((ret->size = list->size) == 0) return ret; - new = ret->front = llist_item_get(); - new->sha1 = list->front->sha1; + new_item = ret->front = llist_item_get(); + new_item->sha1 = list->front->sha1; - old = list->front->next; - while (old) { - prev = new; - new = llist_item_get(); - prev->next = new; - new->sha1 = old->sha1; - old = old->next; + old_item = list->front->next; + while (old_item) { + prev = new_item; + new_item = llist_item_get(); + prev->next = new_item; + new_item->sha1 = old_item->sha1; + old_item = old_item->next; } - new->next = NULL; - ret->back = new; + new_item->next = NULL; + ret->back = new_item; return ret; } @@@ -110,24 -110,24 +110,24 @@@ static inline struct llist_item *llist_ struct llist_item *after, const unsigned char *sha1) { - struct llist_item *new = llist_item_get(); - new->sha1 = sha1; - new->next = NULL; + struct llist_item *new_item = llist_item_get(); + new_item->sha1 = sha1; + new_item->next = NULL; if (after != NULL) { - new->next = after->next; - after->next = new; + new_item->next = after->next; + after->next = new_item; if (after == list->back) - list->back = new; + list->back = new_item; } else {/* insert in front */ if (list->size == 0) - list->back = new; + list->back = new_item; else - new->next = list->front; - list->front = new; + new_item->next = list->front; + list->front = new_item; } list->size++; - return new; + return new_item; } static inline struct llist_item *llist_insert_back(struct llist *list, @@@ -631,8 -631,6 +631,6 @@@ int cmd_pack_redundant(int argc, const break; } - prepare_packed_git(); - if (load_all_packs) load_all(); else diff --combined builtin/receive-pack.c index f0edc6a846,469b916707..4fadf7e41e --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@@ -1,4 -1,5 +1,5 @@@ #include "builtin.h" + #include "repository.h" #include "config.h" #include "lockfile.h" #include "pack.h" @@@ -69,7 -70,7 +70,7 @@@ static int sent_capabilities static int shallow_update; static const char *alt_shallow_file; static struct strbuf push_cert = STRBUF_INIT; -static unsigned char push_cert_sha1[20]; +static struct object_id push_cert_oid; static struct signature_check sigcheck; static const char *push_cert_nonce; static const char *cert_nonce_seed; @@@ -633,9 -634,8 +634,9 @@@ static void prepare_push_cert_sha1(stru int bogs /* beginning_of_gpg_sig */; already_done = 1; - if (write_sha1_file(push_cert.buf, push_cert.len, "blob", push_cert_sha1)) - hashclr(push_cert_sha1); + if (write_object_file(push_cert.buf, push_cert.len, "blob", + &push_cert_oid)) + oidclr(&push_cert_oid); memset(&sigcheck, '\0', sizeof(sigcheck)); sigcheck.result = 'N'; @@@ -656,9 -656,9 +657,9 @@@ strbuf_release(&gpg_status); nonce_status = check_nonce(push_cert.buf, bogs); } - if (!is_null_sha1(push_cert_sha1)) { + if (!is_null_oid(&push_cert_oid)) { argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT=%s", - sha1_to_hex(push_cert_sha1)); + oid_to_hex(&push_cert_oid)); argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_SIGNER=%s", sigcheck.signer ? sigcheck.signer : ""); argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_KEY=%s", @@@ -1242,11 -1242,11 +1243,11 @@@ static void check_aliased_update(struc rp_error("refusing inconsistent update between symref '%s' (%s..%s) and" " its target '%s' (%s..%s)", cmd->ref_name, - find_unique_abbrev(cmd->old_oid.hash, DEFAULT_ABBREV), - find_unique_abbrev(cmd->new_oid.hash, DEFAULT_ABBREV), + find_unique_abbrev(&cmd->old_oid, DEFAULT_ABBREV), + find_unique_abbrev(&cmd->new_oid, DEFAULT_ABBREV), dst_cmd->ref_name, - find_unique_abbrev(dst_cmd->old_oid.hash, DEFAULT_ABBREV), - find_unique_abbrev(dst_cmd->new_oid.hash, DEFAULT_ABBREV)); + find_unique_abbrev(&dst_cmd->old_oid, DEFAULT_ABBREV), + find_unique_abbrev(&dst_cmd->new_oid, DEFAULT_ABBREV)); cmd->error_string = dst_cmd->error_string = "inconsistent aliased update"; @@@ -1778,7 -1778,7 +1779,7 @@@ static const char *unpack(int err_fd, s status = finish_command(&child); if (status) return "index-pack abnormal exit"; - reprepare_packed_git(); + reprepare_packed_git(the_repository); } return NULL; } @@@ -1964,12 -1964,6 +1965,12 @@@ int cmd_receive_pack(int argc, const ch unpack_limit = receive_unpack_limit; switch (determine_protocol_version_server()) { + case protocol_v2: + /* + * push support for protocol v2 has not been implemented yet, + * so ignore the request to use v2 and fallback to using v0. + */ + break; case protocol_v1: /* * v1 is just the original protocol with a version string, diff --combined bulk-checkin.c index e5ce2a7954,eadc2d5172..de1f4040c7 --- a/bulk-checkin.c +++ b/bulk-checkin.c @@@ -3,6 -3,7 +3,7 @@@ */ #include "cache.h" #include "bulk-checkin.h" + #include "repository.h" #include "csum-file.h" #include "pack.h" #include "strbuf.h" @@@ -12,7 -13,7 +13,7 @@@ static struct bulk_checkin_state unsigned plugged:1; char *pack_tmp_name; - struct sha1file *f; + struct hashfile *f; off_t offset; struct pack_idx_option pack_idx_opts; @@@ -35,9 -36,9 +36,9 @@@ static void finish_bulk_checkin(struct unlink(state->pack_tmp_name); goto clear_exit; } else if (state->nr_written == 1) { - sha1close(state->f, oid.hash, CSUM_FSYNC); + hashclose(state->f, oid.hash, CSUM_FSYNC); } else { - int fd = sha1close(state->f, oid.hash, 0); + int fd = hashclose(state->f, oid.hash, 0); fixup_pack_header_footer(fd, oid.hash, state->pack_tmp_name, state->nr_written, oid.hash, state->offset); @@@ -57,20 -58,20 +58,20 @@@ clear_exit strbuf_release(&packname); /* Make objects we just wrote available to ourselves */ - reprepare_packed_git(); + reprepare_packed_git(the_repository); } -static int already_written(struct bulk_checkin_state *state, unsigned char sha1[]) +static int already_written(struct bulk_checkin_state *state, struct object_id *oid) { int i; /* The object may already exist in the repository */ - if (has_sha1_file(sha1)) + if (has_sha1_file(oid->hash)) return 1; /* Might want to keep the list sorted */ for (i = 0; i < state->nr_written; i++) - if (!hashcmp(state->written[i]->oid.hash, sha1)) + if (!oidcmp(&state->written[i]->oid, oid)) return 1; /* This is a new object we need to keep */ @@@ -93,7 -94,7 +94,7 @@@ * with a new pack. */ static int stream_to_pack(struct bulk_checkin_state *state, - git_SHA_CTX *ctx, off_t *already_hashed_to, + git_hash_ctx *ctx, off_t *already_hashed_to, int fd, size_t size, enum object_type type, const char *path, unsigned flags) { @@@ -127,7 -128,7 +128,7 @@@ if (rsize < hsize) hsize = rsize; if (hsize) - git_SHA1_Update(ctx, ibuf, hsize); + the_hash_algo->update_fn(ctx, ibuf, hsize); *already_hashed_to = offset; } s.next_in = ibuf; @@@ -149,7 -150,7 +150,7 @@@ return -1; } - sha1write(state->f, obuf, written); + hashwrite(state->f, obuf, written); state->offset += written; } s.next_out = obuf; @@@ -186,16 -187,16 +187,16 @@@ static void prepare_to_stream(struct bu } static int deflate_to_pack(struct bulk_checkin_state *state, - unsigned char result_sha1[], + struct object_id *result_oid, int fd, size_t size, enum object_type type, const char *path, unsigned flags) { off_t seekback, already_hashed_to; - git_SHA_CTX ctx; + git_hash_ctx ctx; unsigned char obuf[16384]; unsigned header_len; - struct sha1file_checkpoint checkpoint; + struct hashfile_checkpoint checkpoint; struct pack_idx_entry *idx = NULL; seekback = lseek(fd, 0, SEEK_CUR); @@@ -203,9 -204,9 +204,9 @@@ return error("cannot find the current offset"); header_len = xsnprintf((char *)obuf, sizeof(obuf), "%s %" PRIuMAX, - typename(type), (uintmax_t)size) + 1; - git_SHA1_Init(&ctx); - git_SHA1_Update(&ctx, obuf, header_len); + type_name(type), (uintmax_t)size) + 1; + the_hash_algo->init_fn(&ctx); + the_hash_algo->update_fn(&ctx, obuf, header_len); /* Note: idx is non-NULL when we are writing */ if ((flags & HASH_WRITE_OBJECT) != 0) @@@ -216,7 -217,7 +217,7 @@@ while (1) { prepare_to_stream(state, flags); if (idx) { - sha1file_checkpoint(state->f, &checkpoint); + hashfile_checkpoint(state->f, &checkpoint); idx->offset = state->offset; crc32_begin(state->f); } @@@ -230,23 -231,23 +231,23 @@@ */ if (!idx) die("BUG: should not happen"); - sha1file_truncate(state->f, &checkpoint); + hashfile_truncate(state->f, &checkpoint); state->offset = checkpoint.offset; finish_bulk_checkin(state); if (lseek(fd, seekback, SEEK_SET) == (off_t) -1) return error("cannot seek back"); } - git_SHA1_Final(result_sha1, &ctx); + the_hash_algo->final_fn(result_oid->hash, &ctx); if (!idx) return 0; idx->crc32 = crc32_end(state->f); - if (already_written(state, result_sha1)) { - sha1file_truncate(state->f, &checkpoint); + if (already_written(state, result_oid)) { + hashfile_truncate(state->f, &checkpoint); state->offset = checkpoint.offset; free(idx); } else { - hashcpy(idx->oid.hash, result_sha1); + oidcpy(&idx->oid, result_oid); ALLOC_GROW(state->written, state->nr_written + 1, state->alloc_written); @@@ -255,11 -256,11 +256,11 @@@ return 0; } -int index_bulk_checkin(unsigned char *sha1, +int index_bulk_checkin(struct object_id *oid, int fd, size_t size, enum object_type type, const char *path, unsigned flags) { - int status = deflate_to_pack(&state, sha1, fd, size, type, + int status = deflate_to_pack(&state, oid, fd, size, type, path, flags); if (!state.plugged) finish_bulk_checkin(&state); diff --combined fast-import.c index 5eea3cc9d2,37a44752a8..fc4e885bcc --- a/fast-import.c +++ b/fast-import.c @@@ -170,7 -170,6 +170,7 @@@ Format of STDIN stream #include "run-command.h" #include "packfile.h" #include "object-store.h" +#include "mem-pool.h" #define PACK_ID_BITS 16 #define MAX_PACK_ID ((1<next_pool) - if ((p->end - p->next_free >= len)) - break; - - if (!p) { - if (len >= (mem_pool_alloc/2)) { - total_allocd += len; - return xmalloc(len); - } - total_allocd += sizeof(struct mem_pool) + mem_pool_alloc; - p = xmalloc(st_add(sizeof(struct mem_pool), mem_pool_alloc)); - p->next_pool = mem_pool; - p->next_free = (char *) p->space; - p->end = p->next_free + mem_pool_alloc; - mem_pool = p; - } - - r = p->next_free; - p->next_free += len; - return r; -} - -static void *pool_calloc(size_t count, size_t size) -{ - size_t len = count * size; - void *r = pool_alloc(len); - memset(r, 0, len); - return r; -} - static char *pool_strdup(const char *s) { size_t len = strlen(s) + 1; - char *r = pool_alloc(len); + char *r = mem_pool_alloc(&fi_mem_pool, len); memcpy(r, s, len); return r; } @@@ -641,7 -687,7 +641,7 @@@ static void insert_mark(uintmax_t idnum { struct mark_set *s = marks; while ((idnum >> s->shift) >= 1024) { - s = pool_calloc(1, sizeof(struct mark_set)); + s = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct mark_set)); s->shift = marks->shift + 10; s->data.sets[0] = marks; marks = s; @@@ -650,7 -696,7 +650,7 @@@ uintmax_t i = idnum >> s->shift; idnum -= i << s->shift; if (!s->data.sets[i]) { - s->data.sets[i] = pool_calloc(1, sizeof(struct mark_set)); + s->data.sets[i] = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct mark_set)); s->data.sets[i]->shift = s->shift - 10; } s = s->data.sets[i]; @@@ -688,7 -734,7 +688,7 @@@ static struct atom_str *to_atom(const c if (c->str_len == len && !strncmp(s, c->str_dat, len)) return c; - c = pool_alloc(sizeof(struct atom_str) + len + 1); + c = mem_pool_alloc(&fi_mem_pool, sizeof(struct atom_str) + len + 1); c->str_len = len; memcpy(c->str_dat, s, len); c->str_dat[len] = 0; @@@ -719,7 -765,7 +719,7 @@@ static struct branch *new_branch(const if (check_refname_format(name, REFNAME_ALLOW_ONELEVEL)) die("Branch name doesn't conform to GIT standards: %s", name); - b = pool_calloc(1, sizeof(struct branch)); + b = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct branch)); b->name = pool_strdup(name); b->table_next_branch = branch_table[hc]; b->branch_tree.versions[0].mode = S_IFDIR; @@@ -755,7 -801,7 +755,7 @@@ static struct tree_content *new_tree_co avail_tree_table[hc] = f->next_avail; } else { cnt = cnt & 7 ? ((cnt / 8) + 1) * 8 : cnt; - f = pool_alloc(sizeof(*t) + sizeof(t->entries[0]) * cnt); + f = mem_pool_alloc(&fi_mem_pool, sizeof(*t) + sizeof(t->entries[0]) * cnt); f->entry_capacity = cnt; } @@@ -861,12 -907,12 +861,12 @@@ static void start_packfile(void p->pack_fd = pack_fd; p->do_not_close = 1; - pack_file = sha1fd(pack_fd, p->pack_name); + pack_file = hashfd(pack_fd, p->pack_name); hdr.hdr_signature = htonl(PACK_SIGNATURE); hdr.hdr_version = htonl(2); hdr.hdr_entries = 0; - sha1write(pack_file, &hdr, sizeof(hdr)); + hashwrite(pack_file, &hdr, sizeof(hdr)); pack_data = p; pack_size = sizeof(hdr); @@@ -972,7 -1018,7 +972,7 @@@ static void end_packfile(void struct tag *t; close_pack_windows(pack_data); - sha1close(pack_file, cur_pack_oid.hash, 0); + hashclose(pack_file, cur_pack_oid.hash, 0); fixup_pack_header_footer(pack_data->pack_fd, pack_data->sha1, pack_data->pack_name, object_count, cur_pack_oid.hash, pack_size); @@@ -992,7 -1038,7 +992,7 @@@ if (!new_p) die("core git rejected index %s", idx_name); all_packs[pack_id] = new_p; - install_packed_git(new_p); + install_packed_git(the_repository, new_p); free(idx_name); /* Print the boundary */ @@@ -1048,15 -1094,15 +1048,15 @@@ static int store_object unsigned char hdr[96]; struct object_id oid; unsigned long hdrlen, deltalen; - git_SHA_CTX c; + git_hash_ctx c; git_zstream s; hdrlen = xsnprintf((char *)hdr, sizeof(hdr), "%s %lu", - typename(type), (unsigned long)dat->len) + 1; - git_SHA1_Init(&c); - git_SHA1_Update(&c, hdr, hdrlen); - git_SHA1_Update(&c, dat->buf, dat->len); - git_SHA1_Final(oid.hash, &c); + type_name(type), (unsigned long)dat->len) + 1; + the_hash_algo->init_fn(&c); + the_hash_algo->update_fn(&c, hdr, hdrlen); + the_hash_algo->update_fn(&c, dat->buf, dat->len); + the_hash_algo->final_fn(oid.hash, &c); if (oidout) oidcpy(oidout, &oid); @@@ -1075,13 -1121,11 +1075,13 @@@ return 1; } - if (last && last->data.buf && last->depth < max_depth && dat->len > 20) { + if (last && last->data.buf && last->depth < max_depth + && dat->len > the_hash_algo->rawsz) { + delta_count_attempts_by_type[type]++; delta = diff_delta(last->data.buf, last->data.len, dat->buf, dat->len, - &deltalen, dat->len - 20); + &deltalen, dat->len - the_hash_algo->rawsz); } else delta = NULL; @@@ -1139,23 -1183,23 +1139,23 @@@ hdrlen = encode_in_pack_object_header(hdr, sizeof(hdr), OBJ_OFS_DELTA, deltalen); - sha1write(pack_file, hdr, hdrlen); + hashwrite(pack_file, hdr, hdrlen); pack_size += hdrlen; hdr[pos] = ofs & 127; while (ofs >>= 7) hdr[--pos] = 128 | (--ofs & 127); - sha1write(pack_file, hdr + pos, sizeof(hdr) - pos); + hashwrite(pack_file, hdr + pos, sizeof(hdr) - pos); pack_size += sizeof(hdr) - pos; } else { e->depth = 0; hdrlen = encode_in_pack_object_header(hdr, sizeof(hdr), type, dat->len); - sha1write(pack_file, hdr, hdrlen); + hashwrite(pack_file, hdr, hdrlen); pack_size += hdrlen; } - sha1write(pack_file, out, s.total_out); + hashwrite(pack_file, out, s.total_out); pack_size += s.total_out; e->idx.crc32 = crc32_end(pack_file); @@@ -1174,9 -1218,9 +1174,9 @@@ return 0; } -static void truncate_pack(struct sha1file_checkpoint *checkpoint) +static void truncate_pack(struct hashfile_checkpoint *checkpoint) { - if (sha1file_truncate(pack_file, checkpoint)) + if (hashfile_truncate(pack_file, checkpoint)) die_errno("cannot truncate pack to skip duplicate"); pack_size = checkpoint->offset; } @@@ -1190,9 -1234,9 +1190,9 @@@ static void stream_blob(uintmax_t len, struct object_id oid; unsigned long hdrlen; off_t offset; - git_SHA_CTX c; + git_hash_ctx c; git_zstream s; - struct sha1file_checkpoint checkpoint; + struct hashfile_checkpoint checkpoint; int status = Z_OK; /* Determine if we should auto-checkpoint. */ @@@ -1200,13 -1244,13 +1200,13 @@@ || (pack_size + 60 + len) < pack_size) cycle_packfile(); - sha1file_checkpoint(pack_file, &checkpoint); + hashfile_checkpoint(pack_file, &checkpoint); offset = checkpoint.offset; hdrlen = xsnprintf((char *)out_buf, out_sz, "blob %" PRIuMAX, len) + 1; - git_SHA1_Init(&c); - git_SHA1_Update(&c, out_buf, hdrlen); + the_hash_algo->init_fn(&c); + the_hash_algo->update_fn(&c, out_buf, hdrlen); crc32_begin(pack_file); @@@ -1224,7 -1268,7 +1224,7 @@@ if (!n && feof(stdin)) die("EOF in data (%" PRIuMAX " bytes remaining)", len); - git_SHA1_Update(&c, in_buf, n); + the_hash_algo->update_fn(&c, in_buf, n); s.next_in = in_buf; s.avail_in = n; len -= n; @@@ -1234,7 -1278,7 +1234,7 @@@ if (!s.avail_out || status == Z_STREAM_END) { size_t n = s.next_out - out_buf; - sha1write(pack_file, out_buf, n); + hashwrite(pack_file, out_buf, n); pack_size += n; s.next_out = out_buf; s.avail_out = out_sz; @@@ -1250,7 -1294,7 +1250,7 @@@ } } git_deflate_end(&s); - git_SHA1_Final(oid.hash, &c); + the_hash_algo->final_fn(oid.hash, &c); if (oidout) oidcpy(oidout, &oid); @@@ -1310,25 -1354,25 +1310,25 @@@ static void *gfi_unpack_entry { enum object_type type; struct packed_git *p = all_packs[oe->pack_id]; - if (p == pack_data && p->pack_size < (pack_size + 20)) { + if (p == pack_data && p->pack_size < (pack_size + the_hash_algo->rawsz)) { /* The object is stored in the packfile we are writing to * and we have modified it since the last time we scanned * back to read a previously written object. If an old - * window covered [p->pack_size, p->pack_size + 20) its + * window covered [p->pack_size, p->pack_size + rawsz) its * data is stale and is not valid. Closing all windows * and updating the packfile length ensures we can read * the newly written data. */ close_pack_windows(p); - sha1flush(pack_file); + hashflush(pack_file); - /* We have to offer 20 bytes additional on the end of + /* We have to offer rawsz bytes additional on the end of * the packfile as the core unpacker code assumes the * footer is present at the file end and must promise - * at least 20 bytes within any window it maps. But + * at least rawsz bytes within any window it maps. But * we don't actually create the footer here. */ - p->pack_size = pack_size + 20; + p->pack_size = pack_size + the_hash_algo->rawsz; } return unpack_entry(p, oe->idx.offset, &type, sizep); } @@@ -1370,7 -1414,7 +1370,7 @@@ static void load_tree(struct tree_entr die("Can't load tree %s", oid_to_hex(oid)); } else { enum object_type type; - buf = read_sha1_file(oid->hash, &type, &size); + buf = read_object_file(oid, &type, &size); if (!buf || type != OBJ_TREE) die("Can't load tree %s", oid_to_hex(oid)); } @@@ -1871,7 -1915,7 +1871,7 @@@ static void read_marks(void die("corrupt mark line: %s", line); e = find_object(&oid); if (!e) { - enum object_type type = sha1_object_info(oid.hash, NULL); + enum object_type type = oid_object_info(&oid, NULL); if (type < 0) die("object not found: %s", oid_to_hex(&oid)); e = insert_object(&oid); @@@ -2164,7 -2208,7 +2164,7 @@@ static void construct_path_with_fanout( unsigned char fanout, char *path) { unsigned int i = 0, j = 0; - if (fanout >= 20) + if (fanout >= the_hash_algo->rawsz) die("Too large fanout (%u)", fanout); while (fanout) { path[i++] = hex_sha1[j++]; @@@ -2172,8 -2216,8 +2172,8 @@@ path[i++] = '/'; fanout--; } - memcpy(path + i, hex_sha1 + j, GIT_SHA1_HEXSZ - j); - path[i + GIT_SHA1_HEXSZ - j] = '\0'; + memcpy(path + i, hex_sha1 + j, the_hash_algo->hexsz - j); + path[i + the_hash_algo->hexsz - j] = '\0'; } static uintmax_t do_change_note_fanout( @@@ -2381,7 -2425,7 +2381,7 @@@ static void file_change_m(const char *p else if (oe) { if (oe->type != OBJ_COMMIT) die("Not a commit (actually a %s): %s", - typename(oe->type), command_buf.buf); + type_name(oe->type), command_buf.buf); } /* * Accept the sha1 without checking; it expected to be in @@@ -2401,14 -2445,14 +2401,14 @@@ enum object_type expected = S_ISDIR(mode) ? OBJ_TREE: OBJ_BLOB; enum object_type type = oe ? oe->type : - sha1_object_info(oid.hash, NULL); + oid_object_info(&oid, NULL); if (type < 0) die("%s not found: %s", S_ISDIR(mode) ? "Tree" : "Blob", command_buf.buf); if (type != expected) die("Not a %s (actually a %s): %s", - typename(expected), typename(type), + type_name(expected), type_name(type), command_buf.buf); } @@@ -2541,9 -2585,8 +2541,9 @@@ static void note_change_n(const char *p oidcpy(&commit_oid, &commit_oe->idx.oid); } else if (!get_oid(p, &commit_oid)) { unsigned long size; - char *buf = read_object_with_reference(commit_oid.hash, - commit_type, &size, commit_oid.hash); + char *buf = read_object_with_reference(&commit_oid, + commit_type, &size, + &commit_oid); if (!buf || size < 46) die("Not a valid commit: %s", p); free(buf); @@@ -2560,14 -2603,14 +2560,14 @@@ } else if (oe) { if (oe->type != OBJ_BLOB) die("Not a blob (actually a %s): %s", - typename(oe->type), command_buf.buf); + type_name(oe->type), command_buf.buf); } else if (!is_null_oid(&oid)) { - enum object_type type = sha1_object_info(oid.hash, NULL); + enum object_type type = oid_object_info(&oid, NULL); if (type < 0) die("Blob not found: %s", command_buf.buf); if (type != OBJ_BLOB) die("Not a blob (actually a %s): %s", - typename(type), command_buf.buf); + type_name(type), command_buf.buf); } construct_path_with_fanout(oid_to_hex(&commit_oid), *old_fanout, path); @@@ -2612,8 -2655,9 +2612,8 @@@ static void parse_from_existing(struct unsigned long size; char *buf; - buf = read_object_with_reference(b->oid.hash, - commit_type, &size, - b->oid.hash); + buf = read_object_with_reference(&b->oid, commit_type, &size, + &b->oid); parse_from_commit(b, buf, size); free(buf); } @@@ -2690,9 -2734,8 +2690,9 @@@ static struct hash_list *parse_merge(un oidcpy(&n->oid, &oe->idx.oid); } else if (!get_oid(from, &n->oid)) { unsigned long size; - char *buf = read_object_with_reference(n->oid.hash, - commit_type, &size, n->oid.hash); + char *buf = read_object_with_reference(&n->oid, + commit_type, + &size, &n->oid); if (!buf || size < 46) die("Not a valid commit: %s", from); free(buf); @@@ -2821,7 -2864,7 +2821,7 @@@ static void parse_new_tag(const char *a enum object_type type; const char *v; - t = pool_alloc(sizeof(struct tag)); + t = mem_pool_alloc(&fi_mem_pool, sizeof(struct tag)); memset(t, 0, sizeof(struct tag)); t->name = pool_strdup(arg); if (last_tag) @@@ -2849,7 -2892,7 +2849,7 @@@ } else if (!get_oid(from, &oid)) { struct object_entry *oe = find_object(&oid); if (!oe) { - type = sha1_object_info(oid.hash, NULL); + type = oid_object_info(&oid, NULL); if (type < 0) die("Not a valid object: %s", from); } else @@@ -2875,7 -2918,7 +2875,7 @@@ "object %s\n" "type %s\n" "tag %s\n", - oid_to_hex(&oid), typename(type), t->name); + oid_to_hex(&oid), type_name(type), t->name); if (tagger) strbuf_addf(&new_data, "tagger %s\n", tagger); @@@ -2925,7 -2968,7 +2925,7 @@@ static void cat_blob(struct object_entr char *buf; if (!oe || oe->pack_id == MAX_PACK_ID) { - buf = read_sha1_file(oid->hash, &type, &size); + buf = read_object_file(oid, &type, &size); } else { type = oe->type; buf = gfi_unpack_entry(oe, &size); @@@ -2946,10 -2989,10 +2946,10 @@@ die("Can't read object %s", oid_to_hex(oid)); if (type != OBJ_BLOB) die("Object %s is a %s but a blob was expected.", - oid_to_hex(oid), typename(type)); + oid_to_hex(oid), type_name(type)); strbuf_reset(&line); strbuf_addf(&line, "%s %s %lu\n", oid_to_hex(oid), - typename(type), size); + type_name(type), size); cat_blob_write(line.buf, line.len); strbuf_release(&line); cat_blob_write(buf, size); @@@ -2964,7 -3007,7 +2964,7 @@@ static void parse_get_mark(const char *p) { - struct object_entry *oe = oe; + struct object_entry *oe; char output[GIT_MAX_HEXSZ + 2]; /* get-mark SP LF */ @@@ -2981,7 -3024,7 +2981,7 @@@ static void parse_cat_blob(const char *p) { - struct object_entry *oe = oe; + struct object_entry *oe; struct object_id oid; /* cat-blob SP LF */ @@@ -3007,7 -3050,7 +3007,7 @@@ static struct object_entry *dereference unsigned long size; char *buf = NULL; if (!oe) { - enum object_type type = sha1_object_info(oid->hash, NULL); + enum object_type type = oid_object_info(oid, NULL); if (type < 0) die("object not found: %s", oid_to_hex(oid)); /* cache it! */ @@@ -3030,7 -3073,7 +3030,7 @@@ buf = gfi_unpack_entry(oe, &size); } else { enum object_type unused; - buf = read_sha1_file(oid->hash, &unused, &size); + buf = read_object_file(oid, &unused, &size); } if (!buf) die("Can't load object %s", oid_to_hex(oid)); @@@ -3420,17 -3463,16 +3420,16 @@@ int cmd_main(int argc, const char **arg atom_table = xcalloc(atom_table_sz, sizeof(struct atom_str*)); branch_table = xcalloc(branch_table_sz, sizeof(struct branch*)); avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*)); - marks = pool_calloc(1, sizeof(struct mark_set)); + marks = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct mark_set)); global_argc = argc; global_argv = argv; - rc_free = pool_alloc(cmd_save * sizeof(*rc_free)); + rc_free = mem_pool_alloc(&fi_mem_pool, cmd_save * sizeof(*rc_free)); for (i = 0; i < (cmd_save - 1); i++) rc_free[i].next = &rc_free[i + 1]; rc_free[cmd_save - 1].next = NULL; - prepare_packed_git(); start_packfile(); set_die_routine(die_nicely); set_checkpoint_signal(); @@@ -3500,8 -3542,8 +3499,8 @@@ fprintf(stderr, "Total branches: %10lu (%10lu loads )\n", branch_count, branch_load_count); fprintf(stderr, " marks: %10" PRIuMAX " (%10" PRIuMAX " unique )\n", (((uintmax_t)1) << marks->shift) * 1024, marks_set_count); fprintf(stderr, " atoms: %10u\n", atom_cnt); - fprintf(stderr, "Memory total: %10" PRIuMAX " KiB\n", (total_allocd + alloc_count*sizeof(struct object_entry))/1024); - fprintf(stderr, " pools: %10lu KiB\n", (unsigned long)(total_allocd/1024)); + fprintf(stderr, "Memory total: %10" PRIuMAX " KiB\n", (total_allocd + fi_mem_pool.pool_alloc + alloc_count*sizeof(struct object_entry))/1024); + fprintf(stderr, " pools: %10lu KiB\n", (unsigned long)((total_allocd + fi_mem_pool.pool_alloc) /1024)); fprintf(stderr, " objects: %10" PRIuMAX " KiB\n", (alloc_count*sizeof(struct object_entry))/1024); fprintf(stderr, "---------------------------------------------------------------------\n"); pack_report(); diff --combined fetch-pack.c index 373dc90bbe,eac5928a27..216d1368be --- a/fetch-pack.c +++ b/fetch-pack.c @@@ -1,4 -1,5 +1,5 @@@ #include "cache.h" + #include "repository.h" #include "config.h" #include "lockfile.h" #include "refs.h" @@@ -261,8 -262,8 +262,8 @@@ static enum ack_type get_ack(int fd, st char *line = packet_read_line(fd, &len); const char *arg; - if (!len) - die(_("git fetch-pack: expected ACK/NAK, got EOF")); + if (!line) + die(_("git fetch-pack: expected ACK/NAK, got a flush packet")); if (!strcmp(line, "NAK")) return NAK; if (skip_prefix(line, "ACK ", &arg)) { @@@ -304,9 -305,9 +305,9 @@@ static void insert_one_alternate_object #define PIPESAFE_FLUSH 32 #define LARGE_FLUSH 16384 -static int next_flush(struct fetch_pack_args *args, int count) +static int next_flush(int stateless_rpc, int count) { - if (args->stateless_rpc) { + if (stateless_rpc) { if (count < LARGE_FLUSH) count <<= 1; else @@@ -469,7 -470,7 +470,7 @@@ static int find_common(struct fetch_pac send_request(args, fd[1], &req_buf); strbuf_setlen(&req_buf, state_len); flushes++; - flush_at = next_flush(args, count); + flush_at = next_flush(args->stateless_rpc, count); /* * We keep one window "ahead" of the other side, and @@@ -711,28 -712,6 +712,28 @@@ static void mark_alternate_complete(str mark_complete(&obj->oid); } +struct loose_object_iter { + struct oidset *loose_object_set; + struct ref *refs; +}; + +/* + * If the number of refs is not larger than the number of loose objects, + * this function stops inserting. + */ +static int add_loose_objects_to_set(const struct object_id *oid, + const char *path, + void *data) +{ + struct loose_object_iter *iter = data; + oidset_insert(iter->loose_object_set, oid); + if (iter->refs == NULL) + return 1; + + iter->refs = iter->refs->next; + return 0; +} + static int everything_local(struct fetch_pack_args *args, struct ref **refs, struct ref **sought, int nr_sought) @@@ -741,31 -720,16 +742,31 @@@ int retval; int old_save_commit_buffer = save_commit_buffer; timestamp_t cutoff = 0; + struct oidset loose_oid_set = OIDSET_INIT; + int use_oidset = 0; + struct loose_object_iter iter = {&loose_oid_set, *refs}; + + /* Enumerate all loose objects or know refs are not so many. */ + use_oidset = !for_each_loose_object(add_loose_objects_to_set, + &iter, 0); save_commit_buffer = 0; for (ref = *refs; ref; ref = ref->next) { struct object *o; + unsigned int flags = OBJECT_INFO_QUICK; - if (!has_object_file_with_flags(&ref->old_oid, - OBJECT_INFO_QUICK)) - continue; + if (use_oidset && + !oidset_contains(&loose_oid_set, &ref->old_oid)) { + /* + * I know this does not exist in the loose form, + * so check if it exists in a non-loose form. + */ + flags |= OBJECT_INFO_IGNORE_LOOSE; + } + if (!has_object_file_with_flags(&ref->old_oid, flags)) + continue; o = parse_object(&ref->old_oid); if (!o) continue; @@@ -781,8 -745,6 +782,8 @@@ } } + oidset_clear(&loose_oid_set); + if (!args->no_dependents) { if (!args->deepen) { for_each_ref(mark_complete_oid, NULL); @@@ -925,17 -887,8 +926,17 @@@ static int get_pack(struct fetch_pack_a ? fetch_fsck_objects : transfer_fsck_objects >= 0 ? transfer_fsck_objects - : 0) - argv_array_push(&cmd.args, "--strict"); + : 0) { + if (args->from_promisor) + /* + * We cannot use --strict in index-pack because it + * checks both broken objects and links, but we only + * want to check for broken objects. + */ + argv_array_push(&cmd.args, "--fsck-objects"); + else + argv_array_push(&cmd.args, "--strict"); + } cmd.in = demux.out; cmd.git_cmd = 1; @@@ -1079,328 -1032,6 +1080,328 @@@ static struct ref *do_fetch_pack(struc return ref; } +static void add_shallow_requests(struct strbuf *req_buf, + const struct fetch_pack_args *args) +{ + if (is_repository_shallow()) + write_shallow_commits(req_buf, 1, NULL); + if (args->depth > 0) + packet_buf_write(req_buf, "deepen %d", args->depth); + if (args->deepen_since) { + timestamp_t max_age = approxidate(args->deepen_since); + packet_buf_write(req_buf, "deepen-since %"PRItime, max_age); + } + if (args->deepen_not) { + int i; + for (i = 0; i < args->deepen_not->nr; i++) { + struct string_list_item *s = args->deepen_not->items + i; + packet_buf_write(req_buf, "deepen-not %s", s->string); + } + } +} + +static void add_wants(const struct ref *wants, struct strbuf *req_buf) +{ + for ( ; wants ; wants = wants->next) { + const struct object_id *remote = &wants->old_oid; + const char *remote_hex; + struct object *o; + + /* + * If that object is complete (i.e. it is an ancestor of a + * local ref), we tell them we have it but do not have to + * tell them about its ancestors, which they already know + * about. + * + * We use lookup_object here because we are only + * interested in the case we *know* the object is + * reachable and we have already scanned it. + */ + if (((o = lookup_object(remote->hash)) != NULL) && + (o->flags & COMPLETE)) { + continue; + } + + remote_hex = oid_to_hex(remote); + packet_buf_write(req_buf, "want %s\n", remote_hex); + } +} + +static void add_common(struct strbuf *req_buf, struct oidset *common) +{ + struct oidset_iter iter; + const struct object_id *oid; + oidset_iter_init(common, &iter); + + while ((oid = oidset_iter_next(&iter))) { + packet_buf_write(req_buf, "have %s\n", oid_to_hex(oid)); + } +} + +static int add_haves(struct strbuf *req_buf, int *haves_to_send, int *in_vain) +{ + int ret = 0; + int haves_added = 0; + const struct object_id *oid; + + while ((oid = get_rev())) { + packet_buf_write(req_buf, "have %s\n", oid_to_hex(oid)); + if (++haves_added >= *haves_to_send) + break; + } + + *in_vain += haves_added; + if (!haves_added || *in_vain >= MAX_IN_VAIN) { + /* Send Done */ + packet_buf_write(req_buf, "done\n"); + ret = 1; + } + + /* Increase haves to send on next round */ + *haves_to_send = next_flush(1, *haves_to_send); + + return ret; +} + +static int send_fetch_request(int fd_out, const struct fetch_pack_args *args, + const struct ref *wants, struct oidset *common, + int *haves_to_send, int *in_vain) +{ + int ret = 0; + struct strbuf req_buf = STRBUF_INIT; + + if (server_supports_v2("fetch", 1)) + packet_buf_write(&req_buf, "command=fetch"); + if (server_supports_v2("agent", 0)) + packet_buf_write(&req_buf, "agent=%s", git_user_agent_sanitized()); + + packet_buf_delim(&req_buf); + if (args->use_thin_pack) + packet_buf_write(&req_buf, "thin-pack"); + if (args->no_progress) + packet_buf_write(&req_buf, "no-progress"); + if (args->include_tag) + packet_buf_write(&req_buf, "include-tag"); + if (prefer_ofs_delta) + packet_buf_write(&req_buf, "ofs-delta"); + + /* Add shallow-info and deepen request */ + if (server_supports_feature("fetch", "shallow", 0)) + add_shallow_requests(&req_buf, args); + else if (is_repository_shallow() || args->deepen) + die(_("Server does not support shallow requests")); + + /* add wants */ + add_wants(wants, &req_buf); + + /* Add all of the common commits we've found in previous rounds */ + add_common(&req_buf, common); + + /* Add initial haves */ + ret = add_haves(&req_buf, haves_to_send, in_vain); + + /* Send request */ + packet_buf_flush(&req_buf); + write_or_die(fd_out, req_buf.buf, req_buf.len); + + strbuf_release(&req_buf); + return ret; +} + +/* + * Processes a section header in a server's response and checks if it matches + * `section`. If the value of `peek` is 1, the header line will be peeked (and + * not consumed); if 0, the line will be consumed and the function will die if + * the section header doesn't match what was expected. + */ +static int process_section_header(struct packet_reader *reader, + const char *section, int peek) +{ + int ret; + + if (packet_reader_peek(reader) != PACKET_READ_NORMAL) + die("error reading section header '%s'", section); + + ret = !strcmp(reader->line, section); + + if (!peek) { + if (!ret) + die("expected '%s', received '%s'", + section, reader->line); + packet_reader_read(reader); + } + + return ret; +} + +static int process_acks(struct packet_reader *reader, struct oidset *common) +{ + /* received */ + int received_ready = 0; + int received_ack = 0; + + process_section_header(reader, "acknowledgments", 0); + while (packet_reader_read(reader) == PACKET_READ_NORMAL) { + const char *arg; + + if (!strcmp(reader->line, "NAK")) + continue; + + if (skip_prefix(reader->line, "ACK ", &arg)) { + struct object_id oid; + if (!get_oid_hex(arg, &oid)) { + struct commit *commit; + oidset_insert(common, &oid); + commit = lookup_commit(&oid); + mark_common(commit, 0, 1); + } + continue; + } + + if (!strcmp(reader->line, "ready")) { + clear_prio_queue(&rev_list); + received_ready = 1; + continue; + } + + die("unexpected acknowledgment line: '%s'", reader->line); + } + + if (reader->status != PACKET_READ_FLUSH && + reader->status != PACKET_READ_DELIM) + die("error processing acks: %d", reader->status); + + /* return 0 if no common, 1 if there are common, or 2 if ready */ + return received_ready ? 2 : (received_ack ? 1 : 0); +} + +static void receive_shallow_info(struct fetch_pack_args *args, + struct packet_reader *reader) +{ + process_section_header(reader, "shallow-info", 0); + while (packet_reader_read(reader) == PACKET_READ_NORMAL) { + const char *arg; + struct object_id oid; + + if (skip_prefix(reader->line, "shallow ", &arg)) { + if (get_oid_hex(arg, &oid)) + die(_("invalid shallow line: %s"), reader->line); + register_shallow(&oid); + continue; + } + if (skip_prefix(reader->line, "unshallow ", &arg)) { + if (get_oid_hex(arg, &oid)) + die(_("invalid unshallow line: %s"), reader->line); + if (!lookup_object(oid.hash)) + die(_("object not found: %s"), reader->line); + /* make sure that it is parsed as shallow */ + if (!parse_object(&oid)) + die(_("error in object: %s"), reader->line); + if (unregister_shallow(&oid)) + die(_("no shallow found: %s"), reader->line); + continue; + } + die(_("expected shallow/unshallow, got %s"), reader->line); + } + + if (reader->status != PACKET_READ_FLUSH && + reader->status != PACKET_READ_DELIM) + die("error processing shallow info: %d", reader->status); + + setup_alternate_shallow(&shallow_lock, &alternate_shallow_file, NULL); + args->deepen = 1; +} + +enum fetch_state { + FETCH_CHECK_LOCAL = 0, + FETCH_SEND_REQUEST, + FETCH_PROCESS_ACKS, + FETCH_GET_PACK, + FETCH_DONE, +}; + +static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, + int fd[2], + const struct ref *orig_ref, + struct ref **sought, int nr_sought, + char **pack_lockfile) +{ + struct ref *ref = copy_ref_list(orig_ref); + enum fetch_state state = FETCH_CHECK_LOCAL; + struct oidset common = OIDSET_INIT; + struct packet_reader reader; + int in_vain = 0; + int haves_to_send = INITIAL_FLUSH; + packet_reader_init(&reader, fd[0], NULL, 0, + PACKET_READ_CHOMP_NEWLINE); + + while (state != FETCH_DONE) { + switch (state) { + case FETCH_CHECK_LOCAL: + sort_ref_list(&ref, ref_compare_name); + QSORT(sought, nr_sought, cmp_ref_by_name); + + /* v2 supports these by default */ + allow_unadvertised_object_request |= ALLOW_REACHABLE_SHA1; + use_sideband = 2; + if (args->depth > 0 || args->deepen_since || args->deepen_not) + args->deepen = 1; + + if (marked) + for_each_ref(clear_marks, NULL); + marked = 1; + + for_each_ref(rev_list_insert_ref_oid, NULL); + for_each_cached_alternate(insert_one_alternate_object); + + /* Filter 'ref' by 'sought' and those that aren't local */ + if (everything_local(args, &ref, sought, nr_sought)) + state = FETCH_DONE; + else + state = FETCH_SEND_REQUEST; + break; + case FETCH_SEND_REQUEST: + if (send_fetch_request(fd[1], args, ref, &common, + &haves_to_send, &in_vain)) + state = FETCH_GET_PACK; + else + state = FETCH_PROCESS_ACKS; + break; + case FETCH_PROCESS_ACKS: + /* Process ACKs/NAKs */ + switch (process_acks(&reader, &common)) { + case 2: + state = FETCH_GET_PACK; + break; + case 1: + in_vain = 0; + /* fallthrough */ + default: + state = FETCH_SEND_REQUEST; + break; + } + break; + case FETCH_GET_PACK: + /* Check for shallow-info section */ + if (process_section_header(&reader, "shallow-info", 1)) + receive_shallow_info(args, &reader); + + /* get the pack */ + process_section_header(&reader, "packfile", 0); + if (get_pack(args, fd, pack_lockfile)) + die(_("git fetch-pack: fetch failed.")); + + state = FETCH_DONE; + break; + case FETCH_DONE: + continue; + } + } + + oidset_clear(&common); + return ref; +} + static void fetch_pack_config(void) { git_config_get_int("fetch.unpacklimit", &fetch_unpack_limit); @@@ -1546,8 -1177,7 +1547,8 @@@ struct ref *fetch_pack(struct fetch_pac const char *dest, struct ref **sought, int nr_sought, struct oid_array *shallow, - char **pack_lockfile) + char **pack_lockfile, + enum protocol_version version) { struct ref *ref_cpy; struct shallow_info si; @@@ -1561,13 -1191,9 +1562,13 @@@ die(_("no matching remote head")); } prepare_shallow_info(&si, shallow); - ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, - &si, pack_lockfile); + if (version == protocol_v2) + ref_cpy = do_fetch_pack_v2(args, fd, ref, sought, nr_sought, + pack_lockfile); + else + ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, + &si, pack_lockfile); - reprepare_packed_git(); + reprepare_packed_git(the_repository); update_shallow(args, sought, nr_sought, &si); clear_shallow_info(&si); return ref_cpy; diff --combined http-backend.c index 43c49fcce6,88d2a9bc40..bf9b9199e1 --- a/http-backend.c +++ b/http-backend.c @@@ -12,7 -12,6 +12,7 @@@ #include "argv-array.h" #include "packfile.h" #include "object-store.h" +#include "protocol.h" static const char content_type[] = "Content-Type"; static const char content_length[] = "Content-Length"; @@@ -469,11 -468,8 +469,11 @@@ static void get_info_refs(struct strbu hdr_str(hdr, content_type, buf.buf); end_headers(hdr); - packet_write_fmt(1, "# service=git-%s\n", svc->name); - packet_flush(1); + + if (determine_protocol_version_server() != protocol_v2) { + packet_write_fmt(1, "# service=git-%s\n", svc->name); + packet_flush(1); + } argv[0] = svc->name; run_service(argv, 0); @@@ -523,7 -519,6 +523,6 @@@ static void get_info_packs(struct strbu size_t cnt = 0; select_getanyfile(hdr); - prepare_packed_git(); for (p = get_packed_git(the_repository); p; p = p->next) { if (p->pack_local) cnt++; diff --combined http.c index 65f09b53dc,111e3c12c8..fed13b2169 --- a/http.c +++ b/http.c @@@ -63,9 -63,6 +63,9 @@@ static struct { "tlsv1.1", CURL_SSLVERSION_TLSv1_1 }, { "tlsv1.2", CURL_SSLVERSION_TLSv1_2 }, #endif +#if LIBCURL_VERSION_NUM >= 0x073400 + { "tlsv1.3", CURL_SSLVERSION_TLSv1_3 }, +#endif }; #if LIBCURL_VERSION_NUM >= 0x070903 static const char *ssl_key; @@@ -73,9 -70,6 +73,9 @@@ #if LIBCURL_VERSION_NUM >= 0x070908 static const char *ssl_capath; #endif +#if LIBCURL_VERSION_NUM >= 0x071304 +static const char *curl_no_proxy; +#endif #if LIBCURL_VERSION_NUM >= 0x072c00 static const char *ssl_pinnedkey; #endif @@@ -84,6 -78,7 +84,6 @@@ static long curl_low_speed_limit = -1 static long curl_low_speed_time = -1; static int curl_ftp_no_epsv; static const char *curl_http_proxy; -static const char *curl_no_proxy; static const char *http_proxy_authmethod; static struct { const char *name; @@@ -976,6 -971,21 +976,6 @@@ static void set_from_env(const char **v *var = val; } -static void protocol_http_header(void) -{ - if (get_protocol_version_config() > 0) { - struct strbuf protocol_header = STRBUF_INIT; - - strbuf_addf(&protocol_header, GIT_PROTOCOL_HEADER ": version=%d", - get_protocol_version_config()); - - - extra_http_headers = curl_slist_append(extra_http_headers, - protocol_header.buf); - strbuf_release(&protocol_header); - } -} - void http_init(struct remote *remote, const char *url, int proactive_auth) { char *low_speed_limit; @@@ -1006,6 -1016,8 +1006,6 @@@ if (remote) var_override(&http_proxy_authmethod, remote->http_proxy_authmethod); - protocol_http_header(); - pragma_header = curl_slist_append(http_copy_default_headers(), "Pragma: no-cache"); no_pragma_header = curl_slist_append(http_copy_default_headers(), @@@ -1249,14 -1261,14 +1249,14 @@@ static struct fill_chain *fill_cfg void add_fill_function(void *data, int (*fill)(void *)) { - struct fill_chain *new = xmalloc(sizeof(*new)); + struct fill_chain *new_fill = xmalloc(sizeof(*new_fill)); struct fill_chain **linkp = &fill_cfg; - new->data = data; - new->fill = fill; - new->next = NULL; + new_fill->data = data; + new_fill->fill = fill; + new_fill->next = NULL; while (*linkp) linkp = &(*linkp)->next; - *linkp = new; + *linkp = new_fill; } void fill_active_slots(void) @@@ -1778,14 -1790,6 +1778,14 @@@ static int http_request(const char *url headers = curl_slist_append(headers, buf.buf); + /* Add additional headers here */ + if (options && options->extra_headers) { + const struct string_list_item *item; + for_each_string_list_item(item, options->extra_headers) { + headers = curl_slist_append(headers, item->string); + } + } + curl_easy_setopt(slot->curl, CURLOPT_URL, url); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "gzip"); @@@ -2130,7 -2134,7 +2130,7 @@@ int finish_http_pack_request(struct htt return -1; } - install_packed_git(p); + install_packed_git(the_repository, p); free(tmp_idx); return 0; } diff --combined packfile.c index 8e8b743910,0906b8f741..0bc67d0e00 --- a/packfile.c +++ b/packfile.c @@@ -680,13 -680,13 +680,13 @@@ struct packed_git *add_packed_git(cons return p; } - void install_packed_git(struct packed_git *pack) + void install_packed_git(struct repository *r, struct packed_git *pack) { if (pack->pack_fd != -1) pack_open_fds++; - pack->next = the_repository->objects->packed_git; - the_repository->objects->packed_git = pack; + pack->next = r->objects->packed_git; + r->objects->packed_git = pack; } void (*report_garbage)(unsigned seen_bits, const char *path); @@@ -735,7 -735,7 +735,7 @@@ static void report_pack_garbage(struct report_helper(list, seen_bits, first, list->nr); } - static void prepare_packed_git_one(char *objdir, int local) + static void prepare_packed_git_one(struct repository *r, char *objdir, int local) { struct strbuf path = STRBUF_INIT; size_t dirnamelen; @@@ -768,7 -768,7 +768,7 @@@ base_len = path.len; if (strip_suffix_mem(path.buf, &base_len, ".idx")) { /* Don't reopen a pack we already have. */ - for (p = the_repository->objects->packed_git; p; + for (p = r->objects->packed_git; p; p = p->next) { size_t len; if (strip_suffix(p->pack_name, ".pack", &len) && @@@ -782,7 -782,7 +782,7 @@@ * corresponding .pack file that we can map. */ (p = add_packed_git(path.buf, path.len, local)) != NULL) - install_packed_git(p); + install_packed_git(r, p); } if (!report_garbage) @@@ -803,6 -803,7 +803,7 @@@ strbuf_release(&path); } + static void prepare_packed_git(struct repository *r); /* * Give a fast, rough count of the number of objects in the repository. This * ignores loose objects completely. If you have a lot of them, then either @@@ -816,7 -817,7 +817,7 @@@ unsigned long approximate_object_count( unsigned long count; struct packed_git *p; - prepare_packed_git(); + prepare_packed_git(the_repository); count = 0; for (p = the_repository->objects->packed_git; p; p = p->next) { if (open_pack_index(p)) @@@ -866,52 -867,54 +867,54 @@@ static int sort_pack(const void *a_, co return -1; } - static void rearrange_packed_git(void) + static void rearrange_packed_git(struct repository *r) { - the_repository->objects->packed_git = llist_mergesort( - the_repository->objects->packed_git, get_next_packed_git, + r->objects->packed_git = llist_mergesort( + r->objects->packed_git, get_next_packed_git, set_next_packed_git, sort_pack); } - static void prepare_packed_git_mru(void) + static void prepare_packed_git_mru(struct repository *r) { struct packed_git *p; - INIT_LIST_HEAD(&the_repository->objects->packed_git_mru); + INIT_LIST_HEAD(&r->objects->packed_git_mru); - for (p = the_repository->objects->packed_git; p; p = p->next) - list_add_tail(&p->mru, &the_repository->objects->packed_git_mru); + for (p = r->objects->packed_git; p; p = p->next) + list_add_tail(&p->mru, &r->objects->packed_git_mru); } - void prepare_packed_git(void) + static void prepare_packed_git(struct repository *r) { struct alternate_object_database *alt; - if (the_repository->objects->packed_git_initialized) + if (r->objects->packed_git_initialized) return; - prepare_packed_git_one(get_object_directory(), 1); - prepare_alt_odb(the_repository); - for (alt = the_repository->objects->alt_odb_list; alt; alt = alt->next) - prepare_packed_git_one(alt->path, 0); - rearrange_packed_git(); - prepare_packed_git_mru(); - the_repository->objects->packed_git_initialized = 1; + prepare_packed_git_one(r, r->objects->objectdir, 1); + prepare_alt_odb(r); + for (alt = r->objects->alt_odb_list; alt; alt = alt->next) + prepare_packed_git_one(r, alt->path, 0); + rearrange_packed_git(r); + prepare_packed_git_mru(r); + r->objects->packed_git_initialized = 1; } - void reprepare_packed_git(void) + void reprepare_packed_git(struct repository *r) { - the_repository->objects->approximate_object_count_valid = 0; - the_repository->objects->packed_git_initialized = 0; - prepare_packed_git(); + r->objects->approximate_object_count_valid = 0; + r->objects->packed_git_initialized = 0; + prepare_packed_git(r); } struct packed_git *get_packed_git(struct repository *r) { + prepare_packed_git(r); return r->objects->packed_git; } struct list_head *get_packed_git_mru(struct repository *r) { + prepare_packed_git(r); return &r->objects->packed_git_mru; } @@@ -1105,13 -1108,13 +1108,13 @@@ static int retry_bad_packed_offset(stru { int type; struct revindex_entry *revidx; - const unsigned char *sha1; + struct object_id oid; revidx = find_pack_revindex(p, obj_offset); if (!revidx) return OBJ_BAD; - sha1 = nth_packed_object_sha1(p, revidx->nr); - mark_bad_packed_object(p, sha1); - type = sha1_object_info(sha1, NULL); + nth_packed_object_oid(&oid, p, revidx->nr); + mark_bad_packed_object(p, oid.hash); + type = oid_object_info(&oid, NULL); if (type <= OBJ_NONE) return OBJ_BAD; return type; @@@ -1371,16 -1374,16 +1374,16 @@@ int packed_object_info(struct packed_gi *oi->disk_sizep = revidx[1].offset - obj_offset; } - if (oi->typep || oi->typename) { + if (oi->typep || oi->type_name) { enum object_type ptot; ptot = packed_to_object_type(p, obj_offset, type, &w_curs, curpos); if (oi->typep) *oi->typep = ptot; - if (oi->typename) { - const char *tn = typename(ptot); + if (oi->type_name) { + const char *tn = type_name(ptot); if (tn) - strbuf_addstr(oi->typename, tn); + strbuf_addstr(oi->type_name, tn); } if (ptot < 0) { type = OBJ_BAD; @@@ -1462,7 -1465,7 +1465,7 @@@ struct unpack_entry_stack_ent unsigned long size; }; -static void *read_object(const unsigned char *sha1, enum object_type *type, +static void *read_object(const struct object_id *oid, enum object_type *type, unsigned long *size) { struct object_info oi = OBJECT_INFO_INIT; @@@ -1471,7 -1474,7 +1474,7 @@@ oi.sizep = size; oi.contentp = &content; - if (sha1_object_info_extended(sha1, &oi, 0) < 0) + if (oid_object_info_extended(oid, &oi, 0) < 0) return NULL; return content; } @@@ -1511,11 -1514,11 +1514,11 @@@ void *unpack_entry(struct packed_git *p struct revindex_entry *revidx = find_pack_revindex(p, obj_offset); off_t len = revidx[1].offset - obj_offset; if (check_pack_crc(p, &w_curs, obj_offset, len, revidx->nr)) { - const unsigned char *sha1 = - nth_packed_object_sha1(p, revidx->nr); + struct object_id oid; + nth_packed_object_oid(&oid, p, revidx->nr); error("bad packed object CRC for %s", - sha1_to_hex(sha1)); - mark_bad_packed_object(p, sha1); + oid_to_hex(&oid)); + mark_bad_packed_object(p, oid.hash); data = NULL; goto out; } @@@ -1598,16 -1601,16 +1601,16 @@@ * of a corrupted pack, and is better than failing outright. */ struct revindex_entry *revidx; - const unsigned char *base_sha1; + struct object_id base_oid; revidx = find_pack_revindex(p, obj_offset); if (revidx) { - base_sha1 = nth_packed_object_sha1(p, revidx->nr); + nth_packed_object_oid(&base_oid, p, revidx->nr); error("failed to read delta base object %s" " at offset %"PRIuMAX" from %s", - sha1_to_hex(base_sha1), (uintmax_t)obj_offset, + oid_to_hex(&base_oid), (uintmax_t)obj_offset, p->pack_name); - mark_bad_packed_object(p, base_sha1); - base = read_object(base_sha1, &type, &base_size); + mark_bad_packed_object(p, base_oid.hash); + base = read_object(&base_oid, &type, &base_size); external_base = base; } } @@@ -1664,29 -1667,6 +1667,29 @@@ out return data; } +int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32_t *result) +{ + const unsigned char *index_fanout = p->index_data; + const unsigned char *index_lookup; + int index_lookup_width; + + if (!index_fanout) + BUG("bsearch_pack called without a valid pack-index"); + + index_lookup = index_fanout + 4 * 256; + if (p->index_version == 1) { + index_lookup_width = 24; + index_lookup += 4; + } else { + index_lookup_width = 20; + index_fanout += 8; + index_lookup += 8; + } + + return bsearch_hash(oid->hash, (const uint32_t*)index_fanout, + index_lookup, index_lookup_width, result); +} + const unsigned char *nth_packed_object_sha1(struct packed_git *p, uint32_t n) { @@@ -1753,18 -1733,52 +1756,18 @@@ off_t nth_packed_object_offset(const st off_t find_pack_entry_one(const unsigned char *sha1, struct packed_git *p) { - const uint32_t *level1_ofs = p->index_data; const unsigned char *index = p->index_data; - unsigned hi, lo, stride; - static int debug_lookup = -1; - - if (debug_lookup < 0) - debug_lookup = !!getenv("GIT_DEBUG_LOOKUP"); + struct object_id oid; + uint32_t result; if (!index) { if (open_pack_index(p)) return 0; - level1_ofs = p->index_data; - index = p->index_data; - } - if (p->index_version > 1) { - level1_ofs += 2; - index += 8; - } - index += 4 * 256; - hi = ntohl(level1_ofs[*sha1]); - lo = ((*sha1 == 0x0) ? 0 : ntohl(level1_ofs[*sha1 - 1])); - if (p->index_version > 1) { - stride = 20; - } else { - stride = 24; - index += 4; } - if (debug_lookup) - printf("%02x%02x%02x... lo %u hi %u nr %"PRIu32"\n", - sha1[0], sha1[1], sha1[2], lo, hi, p->num_objects); - - while (lo < hi) { - unsigned mi = lo + (hi - lo) / 2; - int cmp = hashcmp(index + mi * stride, sha1); - - if (debug_lookup) - printf("lo %u hi %u rg %u mi %u\n", - lo, hi, hi - lo, mi); - if (!cmp) - return nth_packed_object_offset(p, mi); - if (cmp > 0) - hi = mi; - else - lo = mi+1; - } + hashcpy(oid.hash, sha1); + if (bsearch_pack(&oid, p, &result)) + return nth_packed_object_offset(p, result); return 0; } @@@ -1834,23 -1848,18 +1837,18 @@@ static int fill_pack_entry(const unsign return 1; } - /* - * Iff a pack file contains the object named by sha1, return true and - * store its location to e. - */ - int find_pack_entry(const unsigned char *sha1, struct pack_entry *e) + int find_pack_entry(struct repository *r, const unsigned char *sha1, struct pack_entry *e) { struct list_head *pos; - prepare_packed_git(); - if (!the_repository->objects->packed_git) + prepare_packed_git(r); + if (!r->objects->packed_git) return 0; - list_for_each(pos, &the_repository->objects->packed_git_mru) { + list_for_each(pos, &r->objects->packed_git_mru) { struct packed_git *p = list_entry(pos, struct packed_git, mru); if (fill_pack_entry(sha1, e, p)) { - list_move(&p->mru, - &the_repository->objects->packed_git_mru); + list_move(&p->mru, &r->objects->packed_git_mru); return 1; } } @@@ -1860,7 -1869,7 +1858,7 @@@ int has_sha1_pack(const unsigned char *sha1) { struct pack_entry e; - return find_pack_entry(sha1, &e); + return find_pack_entry(the_repository, sha1, &e); } int has_pack_index(const unsigned char *sha1) @@@ -1896,7 -1905,7 +1894,7 @@@ int for_each_packed_object(each_packed_ int r = 0; int pack_errors = 0; - prepare_packed_git(); + prepare_packed_git(the_repository); for (p = the_repository->objects->packed_git; p; p = p->next) { if ((flags & FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local) continue; diff --combined packfile.h index a7abd602da,efda10329c..a92c0b241c --- a/packfile.h +++ b/packfile.h @@@ -34,9 -34,8 +34,8 @@@ extern struct packed_git *parse_pack_in #define PACKDIR_FILE_GARBAGE 4 extern void (*report_garbage)(unsigned seen_bits, const char *path); - extern void prepare_packed_git(void); - extern void reprepare_packed_git(void); - extern void install_packed_git(struct packed_git *pack); + extern void reprepare_packed_git(struct repository *r); + extern void install_packed_git(struct repository *r, struct packed_git *pack); struct packed_git *get_packed_git(struct repository *r); struct list_head *get_packed_git_mru(struct repository *r); @@@ -81,14 -80,6 +80,14 @@@ extern struct packed_git *add_packed_gi */ extern void check_pack_index_ptr(const struct packed_git *p, const void *ptr); +/* + * Perform binary search on a pack-index for a given oid. Packfile is expected to + * have a valid pack-index. + * + * See 'bsearch_hash' for more information. + */ +int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32_t *result); + /* * Return the SHA-1 of the nth object within the specified packfile. * Open the index if it is not already open. The return value points @@@ -131,7 -122,11 +130,11 @@@ extern int packed_object_info(struct pa extern void mark_bad_packed_object(struct packed_git *p, const unsigned char *sha1); extern const struct packed_git *has_packed_and_bad(const unsigned char *sha1); - extern int find_pack_entry(const unsigned char *sha1, struct pack_entry *e); + /* + * Iff a pack file in the given repository contains the object named by sha1, + * return true and store its location to e. + */ + extern int find_pack_entry(struct repository *r, const unsigned char *sha1, struct pack_entry *e); extern int has_sha1_pack(const unsigned char *sha1); diff --combined sha1_file.c index aab3b58e03,314ff55b47..77ccaab928 --- a/sha1_file.c +++ b/sha1_file.c @@@ -32,9 -32,6 +32,9 @@@ #include "fetch-object.h" #include "object-store.h" +/* The maximum size for an object header. */ +#define MAX_HEADER_LEN 32 + const unsigned char null_sha1[GIT_MAX_RAWSZ]; const struct object_id null_oid; const struct object_id empty_tree_oid = { @@@ -44,32 -41,32 +44,32 @@@ const struct object_id empty_blob_oid EMPTY_BLOB_SHA1_BIN_LITERAL }; -static void git_hash_sha1_init(void *ctx) +static void git_hash_sha1_init(git_hash_ctx *ctx) { - git_SHA1_Init((git_SHA_CTX *)ctx); + git_SHA1_Init(&ctx->sha1); } -static void git_hash_sha1_update(void *ctx, const void *data, size_t len) +static void git_hash_sha1_update(git_hash_ctx *ctx, const void *data, size_t len) { - git_SHA1_Update((git_SHA_CTX *)ctx, data, len); + git_SHA1_Update(&ctx->sha1, data, len); } -static void git_hash_sha1_final(unsigned char *hash, void *ctx) +static void git_hash_sha1_final(unsigned char *hash, git_hash_ctx *ctx) { - git_SHA1_Final(hash, (git_SHA_CTX *)ctx); + git_SHA1_Final(hash, &ctx->sha1); } -static void git_hash_unknown_init(void *ctx) +static void git_hash_unknown_init(git_hash_ctx *ctx) { die("trying to init unknown hash"); } -static void git_hash_unknown_update(void *ctx, const void *data, size_t len) +static void git_hash_unknown_update(git_hash_ctx *ctx, const void *data, size_t len) { die("trying to update unknown hash"); } -static void git_hash_unknown_final(unsigned char *hash, void *ctx) +static void git_hash_unknown_final(unsigned char *hash, git_hash_ctx *ctx) { die("trying to finalize unknown hash"); } @@@ -80,6 -77,7 +80,6 @@@ const struct git_hash_algo hash_algos[G 0x00000000, 0, 0, - 0, git_hash_unknown_init, git_hash_unknown_update, git_hash_unknown_final, @@@ -90,6 -88,7 +90,6 @@@ "sha-1", /* "sha1", big-endian */ 0x73686131, - sizeof(git_SHA_CTX), GIT_SHA1_RAWSZ, GIT_SHA1_HEXSZ, git_hash_sha1_init, @@@ -791,31 -790,31 +791,31 @@@ void *xmmap(void *start, size_t length * With "map" == NULL, try reading the object named with "sha1" using * the streaming interface and rehash it to do the same. */ -int check_sha1_signature(const unsigned char *sha1, void *map, - unsigned long size, const char *type) +int check_object_signature(const struct object_id *oid, void *map, + unsigned long size, const char *type) { - unsigned char real_sha1[20]; + struct object_id real_oid; enum object_type obj_type; struct git_istream *st; - git_SHA_CTX c; - char hdr[32]; + git_hash_ctx c; + char hdr[MAX_HEADER_LEN]; int hdrlen; if (map) { - hash_sha1_file(map, size, type, real_sha1); - return hashcmp(sha1, real_sha1) ? -1 : 0; + hash_object_file(map, size, type, &real_oid); + return oidcmp(oid, &real_oid) ? -1 : 0; } - st = open_istream(sha1, &obj_type, &size, NULL); + st = open_istream(oid, &obj_type, &size, NULL); if (!st) return -1; /* Generate the header */ - hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", typename(obj_type), size) + 1; + hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", type_name(obj_type), size) + 1; /* Sha1.. */ - git_SHA1_Init(&c); - git_SHA1_Update(&c, hdr, hdrlen); + the_hash_algo->init_fn(&c); + the_hash_algo->update_fn(&c, hdr, hdrlen); for (;;) { char buf[1024 * 16]; ssize_t readlen = read_istream(st, buf, sizeof(buf)); @@@ -826,11 -825,11 +826,11 @@@ } if (!readlen) break; - git_SHA1_Update(&c, buf, readlen); + the_hash_algo->update_fn(&c, buf, readlen); } - git_SHA1_Final(real_sha1, &c); + the_hash_algo->final_fn(real_oid.hash, &c); close_istream(st); - return hashcmp(sha1, real_sha1) ? -1 : 0; + return oidcmp(oid, &real_oid) ? -1 : 0; } int git_open_cloexec(const char *name, int flags) @@@ -1102,8 -1101,8 +1102,8 @@@ static int parse_sha1_header_extended(c } type = type_from_string_gently(type_buf, type_len, 1); - if (oi->typename) - strbuf_add(oi->typename, type_buf, type_len); + if (oi->type_name) + strbuf_add(oi->type_name, type_buf, type_len); /* * Set type to 0 if its an unknown object and * we're obtaining the type using '--allow-unknown-type' @@@ -1158,7 -1157,7 +1158,7 @@@ static int sha1_loose_object_info(struc unsigned long mapsize; void *map; git_zstream stream; - char hdr[32]; + char hdr[MAX_HEADER_LEN]; struct strbuf hdrbuf = STRBUF_INIT; unsigned long size_scratch; @@@ -1173,7 -1172,7 +1173,7 @@@ * return value implicitly indicates whether the * object even exists. */ - if (!oi->typep && !oi->typename && !oi->sizep && !oi->contentp) { + if (!oi->typep && !oi->type_name && !oi->sizep && !oi->contentp) { const char *path; struct stat st; if (stat_sha1_file(r, sha1, &st, &path) < 0) @@@ -1230,25 -1229,24 +1230,25 @@@ int fetch_if_missing = 1; -int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, unsigned flags) +int oid_object_info_extended(const struct object_id *oid, struct object_info *oi, unsigned flags) { static struct object_info blank_oi = OBJECT_INFO_INIT; struct pack_entry e; int rtype; - const unsigned char *real = (flags & OBJECT_INFO_LOOKUP_REPLACE) ? - lookup_replace_object(sha1) : - sha1; + const struct object_id *real = oid; int already_retried = 0; - if (is_null_sha1(real)) + if (flags & OBJECT_INFO_LOOKUP_REPLACE) + real = lookup_replace_object(oid); + + if (is_null_oid(real)) return -1; if (!oi) oi = &blank_oi; if (!(flags & OBJECT_INFO_SKIP_CACHED)) { - struct cached_object *co = find_cached_object(real); + struct cached_object *co = find_cached_object(real->hash); if (co) { if (oi->typep) *(oi->typep) = co->type; @@@ -1258,8 -1256,8 +1258,8 @@@ *(oi->disk_sizep) = 0; if (oi->delta_base_sha1) hashclr(oi->delta_base_sha1); - if (oi->typename) - strbuf_addstr(oi->typename, typename(co->type)); + if (oi->type_name) + strbuf_addstr(oi->type_name, type_name(co->type)); if (oi->contentp) *oi->contentp = xmemdupz(co->buf, co->size); oi->whence = OI_CACHED; @@@ -1268,22 -1266,17 +1268,22 @@@ } while (1) { - if (find_pack_entry(real->hash, &e)) - if (find_pack_entry(the_repository, real, &e)) ++ if (find_pack_entry(the_repository, real->hash, &e)) break; + if (flags & OBJECT_INFO_IGNORE_LOOSE) + return -1; + /* Most likely it's a loose object. */ - if (!sha1_loose_object_info(the_repository, real, oi, flags)) + if (!sha1_loose_object_info(the_repository, real->hash, oi, flags)) return 0; /* Not a loose object; someone else may have just packed it. */ - reprepare_packed_git(the_repository); - if (find_pack_entry(the_repository, real, &e)) - break; + if (!(flags & OBJECT_INFO_QUICK)) { - reprepare_packed_git(); - if (find_pack_entry(real->hash, &e)) ++ reprepare_packed_git(the_repository); ++ if (find_pack_entry(the_repository, real->hash, &e)) + break; + } /* Check if it is a missing object */ if (fetch_if_missing && repository_format_partial_clone && @@@ -1292,7 -1285,7 +1292,7 @@@ * TODO Investigate haveing fetch_object() return * TODO error/success and stopping the music here. */ - fetch_object(repository_format_partial_clone, real); + fetch_object(repository_format_partial_clone, real->hash); already_retried = 1; continue; } @@@ -1308,8 -1301,8 +1308,8 @@@ return 0; rtype = packed_object_info(e.p, e.offset, oi); if (rtype < 0) { - mark_bad_packed_object(e.p, real); - return sha1_object_info_extended(real, oi, 0); + mark_bad_packed_object(e.p, real->hash); + return oid_object_info_extended(real, oi, 0); } else if (oi->whence == OI_PACKED) { oi->u.packed.offset = e.offset; oi->u.packed.pack = e.p; @@@ -1321,15 -1314,15 +1321,15 @@@ } /* returns enum object_type or negative */ -int sha1_object_info(const unsigned char *sha1, unsigned long *sizep) +int oid_object_info(const struct object_id *oid, unsigned long *sizep) { enum object_type type; struct object_info oi = OBJECT_INFO_INIT; oi.typep = &type; oi.sizep = sizep; - if (sha1_object_info_extended(sha1, &oi, - OBJECT_INFO_LOOKUP_REPLACE) < 0) + if (oid_object_info_extended(oid, &oi, + OBJECT_INFO_LOOKUP_REPLACE) < 0) return -1; return type; } @@@ -1337,27 -1330,24 +1337,27 @@@ static void *read_object(const unsigned char *sha1, enum object_type *type, unsigned long *size) { + struct object_id oid; struct object_info oi = OBJECT_INFO_INIT; void *content; oi.typep = type; oi.sizep = size; oi.contentp = &content; - if (sha1_object_info_extended(sha1, &oi, 0) < 0) + hashcpy(oid.hash, sha1); + + if (oid_object_info_extended(&oid, &oi, 0) < 0) return NULL; return content; } -int pretend_sha1_file(void *buf, unsigned long len, enum object_type type, - unsigned char *sha1) +int pretend_object_file(void *buf, unsigned long len, enum object_type type, + struct object_id *oid) { struct cached_object *co; - hash_sha1_file(buf, len, typename(type), sha1); - if (has_sha1_file(sha1) || find_cached_object(sha1)) + hash_object_file(buf, len, type_name(type), oid); + if (has_sha1_file(oid->hash) || find_cached_object(oid->hash)) return 0; ALLOC_GROW(cached_objects, cached_object_nr + 1, cached_object_alloc); co = &cached_objects[cached_object_nr++]; @@@ -1365,7 -1355,7 +1365,7 @@@ co->type = type; co->buf = xmalloc(len); memcpy(co->buf, buf, len); - hashcpy(co->sha1, sha1); + hashcpy(co->sha1, oid->hash); return 0; } @@@ -1374,65 -1364,65 +1374,65 @@@ * deal with them should arrange to call read_object() and give error * messages themselves. */ -void *read_sha1_file_extended(const unsigned char *sha1, - enum object_type *type, - unsigned long *size, - int lookup_replace) +void *read_object_file_extended(const struct object_id *oid, + enum object_type *type, + unsigned long *size, + int lookup_replace) { void *data; const struct packed_git *p; const char *path; struct stat st; - const unsigned char *repl = lookup_replace ? lookup_replace_object(sha1) - : sha1; + const struct object_id *repl = lookup_replace ? lookup_replace_object(oid) + : oid; errno = 0; - data = read_object(repl, type, size); + data = read_object(repl->hash, type, size); if (data) return data; if (errno && errno != ENOENT) - die_errno("failed to read object %s", sha1_to_hex(sha1)); + die_errno("failed to read object %s", oid_to_hex(oid)); /* die if we replaced an object with one that does not exist */ - if (repl != sha1) + if (repl != oid) die("replacement %s not found for %s", - sha1_to_hex(repl), sha1_to_hex(sha1)); + oid_to_hex(repl), oid_to_hex(oid)); - if (!stat_sha1_file(the_repository, repl, &st, &path)) + if (!stat_sha1_file(the_repository, repl->hash, &st, &path)) die("loose object %s (stored in %s) is corrupt", - sha1_to_hex(repl), path); + oid_to_hex(repl), path); - if ((p = has_packed_and_bad(repl)) != NULL) + if ((p = has_packed_and_bad(repl->hash)) != NULL) die("packed object %s (stored in %s) is corrupt", - sha1_to_hex(repl), p->pack_name); + oid_to_hex(repl), p->pack_name); return NULL; } -void *read_object_with_reference(const unsigned char *sha1, +void *read_object_with_reference(const struct object_id *oid, const char *required_type_name, unsigned long *size, - unsigned char *actual_sha1_return) + struct object_id *actual_oid_return) { enum object_type type, required_type; void *buffer; unsigned long isize; - unsigned char actual_sha1[20]; + struct object_id actual_oid; required_type = type_from_string(required_type_name); - hashcpy(actual_sha1, sha1); + oidcpy(&actual_oid, oid); while (1) { int ref_length = -1; const char *ref_type = NULL; - buffer = read_sha1_file(actual_sha1, &type, &isize); + buffer = read_object_file(&actual_oid, &type, &isize); if (!buffer) return NULL; if (type == required_type) { *size = isize; - if (actual_sha1_return) - hashcpy(actual_sha1_return, actual_sha1); + if (actual_oid_return) + oidcpy(actual_oid_return, &actual_oid); return buffer; } /* Handle references */ @@@ -1446,32 -1436,32 +1446,32 @@@ } ref_length = strlen(ref_type); - if (ref_length + 40 > isize || + if (ref_length + GIT_SHA1_HEXSZ > isize || memcmp(buffer, ref_type, ref_length) || - get_sha1_hex((char *) buffer + ref_length, actual_sha1)) { + get_oid_hex((char *) buffer + ref_length, &actual_oid)) { free(buffer); return NULL; } free(buffer); /* Now we have the ID of the referred-to object in - * actual_sha1. Check again. */ + * actual_oid. Check again. */ } } -static void write_sha1_file_prepare(const void *buf, unsigned long len, - const char *type, unsigned char *sha1, - char *hdr, int *hdrlen) +static void write_object_file_prepare(const void *buf, unsigned long len, + const char *type, struct object_id *oid, + char *hdr, int *hdrlen) { - git_SHA_CTX c; + git_hash_ctx c; /* Generate the header */ *hdrlen = xsnprintf(hdr, *hdrlen, "%s %lu", type, len)+1; /* Sha1.. */ - git_SHA1_Init(&c); - git_SHA1_Update(&c, hdr, *hdrlen); - git_SHA1_Update(&c, buf, len); - git_SHA1_Final(sha1, &c); + the_hash_algo->init_fn(&c); + the_hash_algo->update_fn(&c, hdr, *hdrlen); + the_hash_algo->update_fn(&c, buf, len); + the_hash_algo->final_fn(oid->hash, &c); } /* @@@ -1524,12 -1514,12 +1524,12 @@@ static int write_buffer(int fd, const v return 0; } -int hash_sha1_file(const void *buf, unsigned long len, const char *type, - unsigned char *sha1) +int hash_object_file(const void *buf, unsigned long len, const char *type, + struct object_id *oid) { - char hdr[32]; + char hdr[MAX_HEADER_LEN]; int hdrlen = sizeof(hdr); - write_sha1_file_prepare(buf, len, type, sha1, hdr, &hdrlen); + write_object_file_prepare(buf, len, type, oid, hdr, &hdrlen); return 0; } @@@ -1587,20 -1577,19 +1587,20 @@@ static int create_tmpfile(struct strbu return fd; } -static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen, - const void *buf, unsigned long len, time_t mtime) +static int write_loose_object(const struct object_id *oid, char *hdr, + int hdrlen, const void *buf, unsigned long len, + time_t mtime) { int fd, ret; unsigned char compressed[4096]; git_zstream stream; - git_SHA_CTX c; - unsigned char parano_sha1[20]; + git_hash_ctx c; + struct object_id parano_oid; static struct strbuf tmp_file = STRBUF_INIT; static struct strbuf filename = STRBUF_INIT; strbuf_reset(&filename); - sha1_file_name(the_repository, &filename, sha1); + sha1_file_name(the_repository, &filename, oid->hash); fd = create_tmpfile(&tmp_file, filename.buf); if (fd < 0) { @@@ -1614,14 -1603,14 +1614,14 @@@ git_deflate_init(&stream, zlib_compression_level); stream.next_out = compressed; stream.avail_out = sizeof(compressed); - git_SHA1_Init(&c); + the_hash_algo->init_fn(&c); /* First header.. */ stream.next_in = (unsigned char *)hdr; stream.avail_in = hdrlen; while (git_deflate(&stream, 0) == Z_OK) ; /* nothing */ - git_SHA1_Update(&c, hdr, hdrlen); + the_hash_algo->update_fn(&c, hdr, hdrlen); /* Then the data itself.. */ stream.next_in = (void *)buf; @@@ -1629,7 -1618,7 +1629,7 @@@ do { unsigned char *in0 = stream.next_in; ret = git_deflate(&stream, Z_FINISH); - git_SHA1_Update(&c, in0, stream.next_in - in0); + the_hash_algo->update_fn(&c, in0, stream.next_in - in0); if (write_buffer(fd, compressed, stream.next_out - compressed) < 0) die("unable to write sha1 file"); stream.next_out = compressed; @@@ -1637,16 -1626,13 +1637,16 @@@ } while (ret == Z_OK); if (ret != Z_STREAM_END) - die("unable to deflate new object %s (%d)", sha1_to_hex(sha1), ret); + die("unable to deflate new object %s (%d)", oid_to_hex(oid), + ret); ret = git_deflate_end_gently(&stream); if (ret != Z_OK) - die("deflateEnd on object %s failed (%d)", sha1_to_hex(sha1), ret); - git_SHA1_Final(parano_sha1, &c); - if (hashcmp(sha1, parano_sha1) != 0) - die("confused by unstable object source data for %s", sha1_to_hex(sha1)); + die("deflateEnd on object %s failed (%d)", oid_to_hex(oid), + ret); + the_hash_algo->final_fn(parano_oid.hash, &c); + if (oidcmp(oid, ¶no_oid) != 0) + die("confused by unstable object source data for %s", + oid_to_hex(oid)); close_sha1_file(fd); @@@ -1669,7 -1655,7 +1669,7 @@@ static int freshen_loose_object(const u static int freshen_packed_object(const unsigned char *sha1) { struct pack_entry e; - if (!find_pack_entry(sha1, &e)) + if (!find_pack_entry(the_repository, sha1, &e)) return 0; if (e.p->freshened) return 1; @@@ -1679,60 -1665,58 +1679,60 @@@ return 1; } -int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1) +int write_object_file(const void *buf, unsigned long len, const char *type, + struct object_id *oid) { - char hdr[32]; + char hdr[MAX_HEADER_LEN]; int hdrlen = sizeof(hdr); /* Normally if we have it in the pack then we do not bother writing * it out into .git/objects/??/?{38} file. */ - write_sha1_file_prepare(buf, len, type, sha1, hdr, &hdrlen); - if (freshen_packed_object(sha1) || freshen_loose_object(sha1)) + write_object_file_prepare(buf, len, type, oid, hdr, &hdrlen); + if (freshen_packed_object(oid->hash) || freshen_loose_object(oid->hash)) return 0; - return write_loose_object(sha1, hdr, hdrlen, buf, len, 0); + return write_loose_object(oid, hdr, hdrlen, buf, len, 0); } -int hash_sha1_file_literally(const void *buf, unsigned long len, const char *type, - struct object_id *oid, unsigned flags) +int hash_object_file_literally(const void *buf, unsigned long len, + const char *type, struct object_id *oid, + unsigned flags) { char *header; int hdrlen, status = 0; /* type string, SP, %lu of the length plus NUL must fit this */ - hdrlen = strlen(type) + 32; + hdrlen = strlen(type) + MAX_HEADER_LEN; header = xmalloc(hdrlen); - write_sha1_file_prepare(buf, len, type, oid->hash, header, &hdrlen); + write_object_file_prepare(buf, len, type, oid, header, &hdrlen); if (!(flags & HASH_WRITE_OBJECT)) goto cleanup; if (freshen_packed_object(oid->hash) || freshen_loose_object(oid->hash)) goto cleanup; - status = write_loose_object(oid->hash, header, hdrlen, buf, len, 0); + status = write_loose_object(oid, header, hdrlen, buf, len, 0); cleanup: free(header); return status; } -int force_object_loose(const unsigned char *sha1, time_t mtime) +int force_object_loose(const struct object_id *oid, time_t mtime) { void *buf; unsigned long len; enum object_type type; - char hdr[32]; + char hdr[MAX_HEADER_LEN]; int hdrlen; int ret; - if (has_loose_object(sha1)) + if (has_loose_object(oid->hash)) return 0; - buf = read_object(sha1, &type, &len); + buf = read_object(oid->hash, &type, &len); if (!buf) - return error("cannot read sha1_file for %s", sha1_to_hex(sha1)); - hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", typename(type), len) + 1; - ret = write_loose_object(sha1, hdr, hdrlen, buf, len, mtime); + return error("cannot read sha1_file for %s", oid_to_hex(oid)); + hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", type_name(type), len) + 1; + ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime); free(buf); return ret; @@@ -1740,12 -1724,10 +1740,12 @@@ int has_sha1_file_with_flags(const unsigned char *sha1, int flags) { + struct object_id oid; if (!startup_info->have_repository) return 0; - return sha1_object_info_extended(sha1, NULL, - flags | OBJECT_INFO_SKIP_CACHED) >= 0; + hashcpy(oid.hash, sha1); + return oid_object_info_extended(&oid, NULL, + flags | OBJECT_INFO_SKIP_CACHED) >= 0; } int has_object_file(const struct object_id *oid) @@@ -1817,9 -1799,9 +1817,9 @@@ static int index_mem(struct object_id * } if (write_object) - ret = write_sha1_file(buf, size, typename(type), oid->hash); + ret = write_object_file(buf, size, type_name(type), oid); else - ret = hash_sha1_file(buf, size, typename(type), oid->hash); + ret = hash_object_file(buf, size, type_name(type), oid); if (re_allocated) free(buf); return ret; @@@ -1839,11 -1821,11 +1839,11 @@@ static int index_stream_convert_blob(st get_conv_flags(flags)); if (write_object) - ret = write_sha1_file(sbuf.buf, sbuf.len, typename(OBJ_BLOB), - oid->hash); + ret = write_object_file(sbuf.buf, sbuf.len, type_name(OBJ_BLOB), + oid); else - ret = hash_sha1_file(sbuf.buf, sbuf.len, typename(OBJ_BLOB), - oid->hash); + ret = hash_object_file(sbuf.buf, sbuf.len, type_name(OBJ_BLOB), + oid); strbuf_release(&sbuf); return ret; } @@@ -1911,7 -1893,7 +1911,7 @@@ static int index_stream(struct object_i enum object_type type, const char *path, unsigned flags) { - return index_bulk_checkin(oid->hash, fd, size, type, path, flags); + return index_bulk_checkin(oid, fd, size, type, path, flags); } int index_fd(struct object_id *oid, int fd, struct stat *st, @@@ -1957,8 -1939,8 +1957,8 @@@ int index_path(struct object_id *oid, c if (strbuf_readlink(&sb, path, st->st_size)) return error_errno("readlink(\"%s\")", path); if (!(flags & HASH_WRITE_OBJECT)) - hash_sha1_file(sb.buf, sb.len, blob_type, oid->hash); - else if (write_sha1_file(sb.buf, sb.len, blob_type, oid->hash)) + hash_object_file(sb.buf, sb.len, blob_type, oid); + else if (write_object_file(sb.buf, sb.len, blob_type, oid)) rc = error("%s: failed to insert into database", path); strbuf_release(&sb); break; @@@ -1985,14 -1967,14 +1985,14 @@@ int read_pack_header(int fd, struct pac return 0; } -void assert_sha1_type(const unsigned char *sha1, enum object_type expect) +void assert_oid_type(const struct object_id *oid, enum object_type expect) { - enum object_type type = sha1_object_info(sha1, NULL); + enum object_type type = oid_object_info(oid, NULL); if (type < 0) - die("%s is not a valid object", sha1_to_hex(sha1)); + die("%s is not a valid object", oid_to_hex(oid)); if (type != expect) - die("%s is not a valid '%s' object", sha1_to_hex(sha1), - typename(expect)); + die("%s is not a valid '%s' object", oid_to_hex(oid), + type_name(expect)); } int for_each_file_in_obj_subdir(unsigned int subdir_nr, @@@ -2143,14 -2125,14 +2143,14 @@@ static int check_stream_sha1(git_zstrea const char *path, const unsigned char *expected_sha1) { - git_SHA_CTX c; + git_hash_ctx c; unsigned char real_sha1[GIT_MAX_RAWSZ]; unsigned char buf[4096]; unsigned long total_read; int status = Z_OK; - git_SHA1_Init(&c); - git_SHA1_Update(&c, hdr, stream->total_out); + the_hash_algo->init_fn(&c); + the_hash_algo->update_fn(&c, hdr, stream->total_out); /* * We already read some bytes into hdr, but the ones up to the NUL @@@ -2169,7 -2151,7 +2169,7 @@@ if (size - total_read < stream->avail_out) stream->avail_out = size - total_read; status = git_inflate(stream, Z_FINISH); - git_SHA1_Update(&c, buf, stream->next_out - buf); + the_hash_algo->update_fn(&c, buf, stream->next_out - buf); total_read += stream->next_out - buf; } git_inflate_end(stream); @@@ -2184,7 -2166,7 +2184,7 @@@ return -1; } - git_SHA1_Final(real_sha1, &c); + the_hash_algo->final_fn(real_sha1, &c); if (hashcmp(expected_sha1, real_sha1)) { error("sha1 mismatch for %s (expected %s)", path, sha1_to_hex(expected_sha1)); @@@ -2195,7 -2177,7 +2195,7 @@@ } int read_loose_object(const char *path, - const unsigned char *expected_sha1, + const struct object_id *expected_oid, enum object_type *type, unsigned long *size, void **contents) @@@ -2204,7 -2186,7 +2204,7 @@@ void *map = NULL; unsigned long mapsize; git_zstream stream; - char hdr[32]; + char hdr[MAX_HEADER_LEN]; *contents = NULL; @@@ -2227,19 -2209,19 +2227,19 @@@ } if (*type == OBJ_BLOB) { - if (check_stream_sha1(&stream, hdr, *size, path, expected_sha1) < 0) + if (check_stream_sha1(&stream, hdr, *size, path, expected_oid->hash) < 0) goto out; } else { - *contents = unpack_sha1_rest(&stream, hdr, *size, expected_sha1); + *contents = unpack_sha1_rest(&stream, hdr, *size, expected_oid->hash); if (!*contents) { error("unable to unpack contents of %s", path); git_inflate_end(&stream); goto out; } - if (check_sha1_signature(expected_sha1, *contents, - *size, typename(*type))) { + if (check_object_signature(expected_oid, *contents, + *size, type_name(*type))) { error("sha1 mismatch for %s (expected %s)", path, - sha1_to_hex(expected_sha1)); + oid_to_hex(expected_oid)); free(*contents); goto out; } diff --combined sha1_name.c index 509a95f0cf,31c013ac7e..5b93bf8da3 --- a/sha1_name.c +++ b/sha1_name.c @@@ -152,14 -152,31 +152,14 @@@ static int match_sha(unsigned len, cons static void unique_in_pack(struct packed_git *p, struct disambiguate_state *ds) { - uint32_t num, last, i, first = 0; + uint32_t num, i, first = 0; const struct object_id *current = NULL; if (open_pack_index(p) || !p->num_objects) return; num = p->num_objects; - last = num; - while (first < last) { - uint32_t mid = first + (last - first) / 2; - const unsigned char *current; - int cmp; - - current = nth_packed_object_sha1(p, mid); - cmp = hashcmp(ds->bin_pfx.hash, current); - if (!cmp) { - first = mid; - break; - } - if (cmp > 0) { - first = mid+1; - continue; - } - last = mid; - } + bsearch_pack(&ds->bin_pfx, p, &first); /* * At this point, "first" is the location of the lowest object @@@ -179,7 -196,6 +179,6 @@@ static void find_short_packed_object(st { struct packed_git *p; - prepare_packed_git(); for (p = get_packed_git(the_repository); p && !ds->ambiguous; p = p->next) unique_in_pack(p, ds); @@@ -224,7 -240,7 +223,7 @@@ static int finish_object_disambiguation static int disambiguate_commit_only(const struct object_id *oid, void *cb_data_unused) { - int kind = sha1_object_info(oid->hash, NULL); + int kind = oid_object_info(oid, NULL); return kind == OBJ_COMMIT; } @@@ -233,7 -249,7 +232,7 @@@ static int disambiguate_committish_only struct object *obj; int kind; - kind = sha1_object_info(oid->hash, NULL); + kind = oid_object_info(oid, NULL); if (kind == OBJ_COMMIT) return 1; if (kind != OBJ_TAG) @@@ -248,7 -264,7 +247,7 @@@ static int disambiguate_tree_only(const struct object_id *oid, void *cb_data_unused) { - int kind = sha1_object_info(oid->hash, NULL); + int kind = oid_object_info(oid, NULL); return kind == OBJ_TREE; } @@@ -257,7 -273,7 +256,7 @@@ static int disambiguate_treeish_only(co struct object *obj; int kind; - kind = sha1_object_info(oid->hash, NULL); + kind = oid_object_info(oid, NULL); if (kind == OBJ_TREE || kind == OBJ_COMMIT) return 1; if (kind != OBJ_TAG) @@@ -272,7 -288,7 +271,7 @@@ static int disambiguate_blob_only(const struct object_id *oid, void *cb_data_unused) { - int kind = sha1_object_info(oid->hash, NULL); + int kind = oid_object_info(oid, NULL); return kind == OBJ_BLOB; } @@@ -351,7 -367,7 +350,7 @@@ static int show_ambiguous_object(const if (ds->fn && !ds->fn(oid, ds->cb_data)) return 0; - type = sha1_object_info(oid->hash, NULL); + type = oid_object_info(oid, NULL); if (type == OBJ_COMMIT) { struct commit *commit = lookup_commit(oid); if (commit) { @@@ -366,8 -382,8 +365,8 @@@ } advise(" %s %s%s", - find_unique_abbrev(oid->hash, DEFAULT_ABBREV), - typename(type) ? typename(type) : "unknown type", + find_unique_abbrev(oid, DEFAULT_ABBREV), + type_name(type) ? type_name(type) : "unknown type", desc.buf); strbuf_release(&desc); @@@ -466,7 -482,7 +465,7 @@@ struct min_abbrev_data unsigned int init_len; unsigned int cur_len; char *hex; - const unsigned char *hash; + const struct object_id *oid; }; static inline char get_hex_char_from_oid(const struct object_id *oid, @@@ -498,34 -514,50 +497,34 @@@ static void find_abbrev_len_for_pack(st struct min_abbrev_data *mad) { int match = 0; - uint32_t num, last, first = 0; + uint32_t num, first = 0; struct object_id oid; + const struct object_id *mad_oid; if (open_pack_index(p) || !p->num_objects) return; num = p->num_objects; - last = num; - while (first < last) { - uint32_t mid = first + (last - first) / 2; - const unsigned char *current; - int cmp; - - current = nth_packed_object_sha1(p, mid); - cmp = hashcmp(mad->hash, current); - if (!cmp) { - match = 1; - first = mid; - break; - } - if (cmp > 0) { - first = mid + 1; - continue; - } - last = mid; - } + mad_oid = mad->oid; + match = bsearch_pack(mad_oid, p, &first); /* * first is now the position in the packfile where we would insert * mad->hash if it does not exist (or the position of mad->hash if - * it does exist). Hence, we consider a maximum of three objects + * it does exist). Hence, we consider a maximum of two objects * nearby for the abbreviation length. */ mad->init_len = 0; if (!match) { - nth_packed_object_oid(&oid, p, first); - extend_abbrev_len(&oid, mad); + if (nth_packed_object_oid(&oid, p, first)) + extend_abbrev_len(&oid, mad); } else if (first < num - 1) { - nth_packed_object_oid(&oid, p, first + 1); - extend_abbrev_len(&oid, mad); + if (nth_packed_object_oid(&oid, p, first + 1)) + extend_abbrev_len(&oid, mad); } if (first > 0) { - nth_packed_object_oid(&oid, p, first - 1); - extend_abbrev_len(&oid, mad); + if (nth_packed_object_oid(&oid, p, first - 1)) + extend_abbrev_len(&oid, mad); } mad->init_len = mad->cur_len; } @@@ -534,12 -566,11 +533,11 @@@ static void find_abbrev_len_packed(stru { struct packed_git *p; - prepare_packed_git(); for (p = get_packed_git(the_repository); p; p = p->next) find_abbrev_len_for_pack(p, mad); } -int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len) +int find_unique_abbrev_r(char *hex, const struct object_id *oid, int len) { struct disambiguate_state ds; struct min_abbrev_data mad; @@@ -566,14 -597,14 +564,14 @@@ len = FALLBACK_DEFAULT_ABBREV; } - sha1_to_hex_r(hex, sha1); + oid_to_hex_r(hex, oid); if (len == GIT_SHA1_HEXSZ || !len) return GIT_SHA1_HEXSZ; mad.init_len = len; mad.cur_len = len; mad.hex = hex; - mad.hash = sha1; + mad.oid = oid; find_abbrev_len_packed(&mad); @@@ -591,13 -622,13 +589,13 @@@ return mad.cur_len; } -const char *find_unique_abbrev(const unsigned char *sha1, int len) +const char *find_unique_abbrev(const struct object_id *oid, int len) { static int bufno; static char hexbuffer[4][GIT_MAX_HEXSZ + 1]; char *hex = hexbuffer[bufno]; bufno = (bufno + 1) % ARRAY_SIZE(hexbuffer); - find_unique_abbrev_r(hex, sha1, len); + find_unique_abbrev_r(hex, oid, len); return hex; } @@@ -871,8 -902,8 +869,8 @@@ struct object *peel_to_type(const char if (name) error("%.*s: expected %s type, but the object " "dereferences to %s type", - namelen, name, typename(expected_type), - typename(o->type)); + namelen, name, type_name(expected_type), + type_name(o->type)); return NULL; } } @@@ -1499,7 -1530,8 +1497,7 @@@ static void diagnose_invalid_oid_path(c if (is_missing_file_error(errno)) { char *fullname = xstrfmt("%s%s", prefix, filename); - if (!get_tree_entry(tree_oid->hash, fullname, - oid.hash, &mode)) { + if (!get_tree_entry(tree_oid, fullname, &oid, &mode)) { die("Path '%s' exists, but not '%s'.\n" "Did you mean '%.*s:%s' aka '%.*s:./%s'?", fullname, @@@ -1691,8 -1723,8 +1689,8 @@@ static int get_oid_with_context_1(cons filename, oid->hash, &oc->symlink_path, &oc->mode); } else { - ret = get_tree_entry(tree_oid.hash, filename, - oid->hash, &oc->mode); + ret = get_tree_entry(&tree_oid, filename, oid, + &oc->mode); if (ret && only_to_die) { diagnose_invalid_oid_path(prefix, filename,