vendor/libgit2/src/pack-objects.c in rugged-0.17.0.b7 vs vendor/libgit2/src/pack-objects.c in rugged-0.18.0.b1

- old
+ new

@@ -1,7 +1,7 @@ /* - * Copyright (C) 2009-2012 the libgit2 contributors + * Copyright (C) the libgit2 contributors. All rights reserved. * * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. */ @@ -19,19 +19,22 @@ #include "git2/commit.h" #include "git2/tag.h" #include "git2/indexer.h" #include "git2/config.h" -GIT__USE_OIDMAP; - struct unpacked { git_pobject *object; void *data; struct git_delta_index *index; unsigned int depth; }; +struct tree_walk_context { + git_packbuilder *pb; + git_buf buf; +}; + #ifdef GIT_THREADS #define GIT_PACKBUILDER__MUTEX_OP(pb, mtx, op) do { \ int result = git_mutex_##op(&(pb)->mtx); \ assert(!result); \ @@ -71,20 +74,20 @@ static int packbuilder_config(git_packbuilder *pb) { git_config *config; int ret; + int64_t val; if (git_repository_config__weakptr(&config, pb->repo) < 0) return -1; -#define config_get(key, dst, default) \ - ret = git_config_get_int64((int64_t *)&dst, config, key); \ - if (ret == GIT_ENOTFOUND) \ - dst = default; \ - else if (ret < 0) \ - return -1; +#define config_get(KEY,DST,DFLT) do { \ + ret = git_config_get_int64(&val, config, KEY); \ + if (!ret) (DST) = val; \ + else if (ret == GIT_ENOTFOUND) (DST) = (DFLT); \ + else if (ret < 0) return -1; } while (0) config_get("pack.deltaCacheSize", pb->max_delta_cache_size, GIT_PACK_DELTA_CACHE_SIZE); config_get("pack.deltaCacheLimit", pb->cache_max_small_delta_size, GIT_PACK_DELTA_CACHE_LIMIT); @@ -101,23 +104,22 @@ { git_packbuilder *pb; *out = NULL; - pb = git__calloc(sizeof(*pb), 1); + pb = git__calloc(1, sizeof(*pb)); GITERR_CHECK_ALLOC(pb); pb->object_ix = git_oidmap_alloc(); if (!pb->object_ix) goto on_error; pb->repo = repo; pb->nr_threads = 1; /* do not spawn any thread by default */ - pb->ctx = git_hash_new_ctx(); - if (!pb->ctx || + if (git_hash_ctx_init(&pb->ctx) < 0 || git_repository_odb(&pb->odb, repo) < 0 || packbuilder_config(pb) < 0) goto on_error; #ifdef GIT_THREADS @@ -135,14 +137,22 @@ on_error: git_packbuilder_free(pb); return -1; } -void git_packbuilder_set_threads(git_packbuilder *pb, unsigned int n) +unsigned int git_packbuilder_set_threads(git_packbuilder *pb, unsigned int n) { assert(pb); + +#ifdef GIT_THREADS pb->nr_threads = n; +#else + GIT_UNUSED(n); + assert(1 == pb->nr_threads); +#endif + + return pb->nr_threads; } static void rehash(git_packbuilder *pb) { git_pobject *po; @@ -227,11 +237,11 @@ c = size & 0x7f; size >>= 7; } *hdr++ = c; - return hdr - hdr_base; + return (int)(hdr - hdr_base); } static int get_delta(void **out, git_odb *odb, git_pobject *po) { git_odb_object *src = NULL, *trg = NULL; @@ -242,13 +252,14 @@ if (git_odb_read(&src, odb, &po->delta->id) < 0 || git_odb_read(&trg, odb, &po->id) < 0) goto on_error; - delta_buf = git_delta(git_odb_object_data(src), git_odb_object_size(src), - git_odb_object_data(trg), git_odb_object_size(trg), - &delta_size, 0); + delta_buf = git_delta( + git_odb_object_data(src), (unsigned long)git_odb_object_size(src), + git_odb_object_data(trg), (unsigned long)git_odb_object_size(trg), + &delta_size, 0); if (!delta_buf || delta_size != po->delta_size) { giterr_set(GITERR_INVALID, "Delta size changed"); goto on_error; } @@ -285,28 +296,27 @@ } else { if (git_odb_read(&obj, pb->odb, &po->id)) goto on_error; data = (void *)git_odb_object_data(obj); - size = git_odb_object_size(obj); + size = (unsigned long)git_odb_object_size(obj); type = git_odb_object_type(obj); } /* Write header */ hdr_len = gen_pack_object_header(hdr, size, type); if (git_buf_put(buf, (char *)hdr, hdr_len) < 0) goto on_error; - git_hash_update(pb->ctx, hdr, hdr_len); + if (git_hash_update(&pb->ctx, hdr, hdr_len) < 0) + goto on_error; if (type == GIT_OBJ_REF_DELTA) { - if (git_buf_put(buf, (char *)po->delta->id.id, - GIT_OID_RAWSZ) < 0) + if (git_buf_put(buf, (char *)po->delta->id.id, GIT_OID_RAWSZ) < 0 || + git_hash_update(&pb->ctx, po->delta->id.id, GIT_OID_RAWSZ) < 0) goto on_error; - - git_hash_update(pb->ctx, po->delta->id.id, GIT_OID_RAWSZ); } /* Write data */ if (po->z_delta_size) size = po->z_delta_size; @@ -314,18 +324,17 @@ goto on_error; else { if (po->delta) git__free(data); data = zbuf.ptr; - size = zbuf.size; + size = (unsigned long)zbuf.size; } - if (git_buf_put(buf, data, size) < 0) + if (git_buf_put(buf, data, size) < 0 || + git_hash_update(&pb->ctx, data, size) < 0) goto on_error; - git_hash_update(pb->ctx, data, size); - if (po->delta_data) git__free(po->delta_data); git_odb_object_free(obj); git_buf_free(&zbuf); @@ -571,11 +580,12 @@ ph.hdr_entries = htonl(pb->nr_objects); if (cb(&ph, sizeof(ph), data) < 0) goto on_error; - git_hash_update(pb->ctx, &ph, sizeof(ph)); + if (git_hash_update(&pb->ctx, &ph, sizeof(ph)) < 0) + goto on_error; pb->nr_remaining = pb->nr_objects; do { pb->nr_written = 0; for ( ; i < pb->nr_objects; ++i) { @@ -590,26 +600,22 @@ pb->nr_remaining -= pb->nr_written; } while (pb->nr_remaining && i < pb->nr_objects); git__free(write_order); git_buf_free(&buf); - git_hash_final(&pb->pack_oid, pb->ctx); + if (git_hash_final(&pb->pack_oid, &pb->ctx) < 0) + goto on_error; + return cb(pb->pack_oid.id, GIT_OID_RAWSZ, data); on_error: git__free(write_order); git_buf_free(&buf); return -1; } -static int send_pack_file(void *buf, size_t size, void *data) -{ - git_transport *t = (git_transport *)data; - return gitno_send(t, buf, size, 0); -} - static int write_pack_buf(void *buf, size_t size, void *data) { git_buf *b = (git_buf *)data; return git_buf_put(b, buf, size); } @@ -704,11 +710,11 @@ /* Let's not bust the allowed depth. */ if (src->depth >= max_depth) return 0; /* Now some size filtering heuristics. */ - trg_size = trg_object->size; + trg_size = (unsigned long)trg_object->size; if (!trg_object->delta) { max_size = trg_size/2 - 20; ref_depth = 1; } else { max_size = trg_object->delta_size; @@ -718,11 +724,11 @@ max_size = (uint64_t)max_size * (max_depth - src->depth) / (max_depth - ref_depth + 1); if (max_size == 0) return 0; - src_size = src_object->size; + src_size = (unsigned long)src_object->size; sizediff = src_size < trg_size ? trg_size - src_size : 0; if (sizediff >= max_size) return 0; if (trg_size < src_size / 32) return 0; @@ -730,11 +736,11 @@ /* Load data if not already done */ if (!trg->data) { if (git_odb_read(&obj, pb->odb, &trg_object->id) < 0) return -1; - sz = git_odb_object_size(obj); + sz = (unsigned long)git_odb_object_size(obj); trg->data = git__malloc(sz); GITERR_CHECK_ALLOC(trg->data); memcpy(trg->data, git_odb_object_data(obj), sz); git_odb_object_free(obj); @@ -749,11 +755,11 @@ } if (!src->data) { if (git_odb_read(&obj, pb->odb, &src_object->id) < 0) return -1; - sz = git_odb_object_size(obj); + sz = (unsigned long)git_odb_object_size(obj); src->data = git__malloc(sz); GITERR_CHECK_ALLOC(src->data); memcpy(src->data, git_odb_object_data(obj), sz); git_odb_object_free(obj); @@ -832,11 +838,11 @@ { unsigned long freed_mem = git_delta_sizeof_index(n->index); git_delta_free_index(n->index); n->index = NULL; if (n->data) { - freed_mem += n->object->size; + freed_mem += (unsigned long)n->object->size; git__free(n->data); n->data = NULL; } n->object = NULL; n->depth = 0; @@ -938,11 +944,11 @@ git__free(po->delta_data); po->delta_data = git__malloc(zbuf.size); GITERR_CHECK_ALLOC(po->delta_data); memcpy(po->delta_data, zbuf.ptr, zbuf.size); - po->z_delta_size = zbuf.size; + po->z_delta_size = (unsigned long)zbuf.size; git_buf_clear(&zbuf); git_packbuilder__cache_lock(pb); pb->delta_cache_size -= po->delta_size; pb->delta_cache_size += po->z_delta_size; @@ -1027,21 +1033,26 @@ git_packbuilder__progress_lock(me->pb); me->working = 0; git_cond_signal(&me->pb->progress_cond); git_packbuilder__progress_unlock(me->pb); + if (git_mutex_lock(&me->mutex)) { + giterr_set(GITERR_THREAD, "unable to lock packfile condition mutex"); + return NULL; + } + + while (!me->data_ready) + git_cond_wait(&me->cond, &me->mutex); + /* * We must not set ->data_ready before we wait on the * condition because the main thread may have set it to 1 * before we get here. In order to be sure that new * work is available if we see 1 in ->data_ready, it * was initialized to 0 before this thread was spawned * and we reset it to 0 right away. */ - git_mutex_lock(&me->mutex); - while (!me->data_ready) - git_cond_wait(&me->cond, &me->mutex); me->data_ready = 0; git_mutex_unlock(&me->mutex); } /* leave ->working 1 so that this doesn't get more work assigned */ return NULL; @@ -1170,11 +1181,16 @@ target->list_size = sub_size; target->remaining = sub_size; target->working = 1; git_packbuilder__progress_unlock(pb); - git_mutex_lock(&target->mutex); + if (git_mutex_lock(&target->mutex)) { + giterr_set(GITERR_THREAD, "unable to lock packfile condition mutex"); + git__free(p); + return -1; + } + target->data_ready = 1; git_cond_signal(&target->cond); git_mutex_unlock(&target->mutex); if (!sub_size) { @@ -1229,14 +1245,14 @@ return 0; } #define PREPARE_PACK if (prepare_pack(pb) < 0) { return -1; } -int git_packbuilder_send(git_packbuilder *pb, git_transport *t) +int git_packbuilder_foreach(git_packbuilder *pb, int (*cb)(void *buf, size_t size, void *payload), void *payload) { PREPARE_PACK; - return write_pack(pb, &send_pack_file, t); + return write_pack(pb, cb, payload); } int git_packbuilder_write_buf(git_buf *buf, git_packbuilder *pb) { PREPARE_PACK; @@ -1251,43 +1267,55 @@ #undef PREPARE_PACK static int cb_tree_walk(const char *root, const git_tree_entry *entry, void *payload) { - git_packbuilder *pb = payload; - git_buf buf = GIT_BUF_INIT; + struct tree_walk_context *ctx = payload; - git_buf_puts(&buf, root); - git_buf_puts(&buf, git_tree_entry_name(entry)); + /* A commit inside a tree represents a submodule commit and should be skipped. */ + if (git_tree_entry_type(entry) == GIT_OBJ_COMMIT) + return 0; - if (git_packbuilder_insert(pb, git_tree_entry_id(entry), - git_buf_cstr(&buf)) < 0) { - git_buf_free(&buf); + if (git_buf_sets(&ctx->buf, root) < 0 || + git_buf_puts(&ctx->buf, git_tree_entry_name(entry)) < 0) return -1; - } - git_buf_free(&buf); - return 0; + return git_packbuilder_insert(ctx->pb, + git_tree_entry_id(entry), + git_buf_cstr(&ctx->buf)); } int git_packbuilder_insert_tree(git_packbuilder *pb, const git_oid *oid) { git_tree *tree; + struct tree_walk_context context = { pb, GIT_BUF_INIT }; if (git_tree_lookup(&tree, pb->repo, oid) < 0 || git_packbuilder_insert(pb, oid, NULL) < 0) return -1; - if (git_tree_walk(tree, cb_tree_walk, GIT_TREEWALK_PRE, pb) < 0) { + if (git_tree_walk(tree, GIT_TREEWALK_PRE, cb_tree_walk, &context) < 0) { git_tree_free(tree); + git_buf_free(&context.buf); return -1; } git_tree_free(tree); + git_buf_free(&context.buf); return 0; } +uint32_t git_packbuilder_object_count(git_packbuilder *pb) +{ + return pb->nr_objects; +} + +uint32_t git_packbuilder_written(git_packbuilder *pb) +{ + return pb->nr_written; +} + void git_packbuilder_free(git_packbuilder *pb) { if (pb == NULL) return; @@ -1300,16 +1328,15 @@ #endif if (pb->odb) git_odb_free(pb->odb); - if (pb->ctx) - git_hash_free_ctx(pb->ctx); - if (pb->object_ix) git_oidmap_free(pb->object_ix); if (pb->object_list) git__free(pb->object_list); + + git_hash_ctx_cleanup(&pb->ctx); git__free(pb); }