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);
}