From a12e069a3e904728d55dc5c92094b0a5cee63da2 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Fri, 30 Aug 2013 16:31:52 +0200 Subject: [PATCH] odb: Honor the non refreshing capability of a backend --- src/odb.c | 6 +- tests-clar/odb/backend/nonrefreshing.c | 261 +++++++++++++++++++++++++ 2 files changed, 264 insertions(+), 3 deletions(-) create mode 100644 tests-clar/odb/backend/nonrefreshing.c diff --git a/src/odb.c b/src/odb.c index 21b46bf56..9785c74da 100644 --- a/src/odb.c +++ b/src/odb.c @@ -622,7 +622,7 @@ attempt_lookup: backend_internal *internal = git_vector_get(&db->backends, i); git_odb_backend *b = internal->backend; - if (b->exists != NULL) + if (b->exists != NULL && (!refreshed || b->refresh)) found = b->exists(b, id); } @@ -717,7 +717,7 @@ attempt_lookup: backend_internal *internal = git_vector_get(&db->backends, i); git_odb_backend *b = internal->backend; - if (b->read != NULL) { + if (b->read != NULL && (!refreshed || b->refresh)) { ++reads; error = b->read(&raw.data, &raw.len, &raw.type, b, id); } @@ -774,7 +774,7 @@ attempt_lookup: backend_internal *internal = git_vector_get(&db->backends, i); git_odb_backend *b = internal->backend; - if (b->read_prefix != NULL) { + if (b->read_prefix != NULL && (!refreshed || b->refresh)) { git_oid full_oid; error = b->read_prefix(&full_oid, &raw.data, &raw.len, &raw.type, b, short_id, len); if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH) diff --git a/tests-clar/odb/backend/nonrefreshing.c b/tests-clar/odb/backend/nonrefreshing.c new file mode 100644 index 000000000..abb824d4b --- /dev/null +++ b/tests-clar/odb/backend/nonrefreshing.c @@ -0,0 +1,261 @@ +#include "clar_libgit2.h" +#include "git2/sys/odb_backend.h" +#include "repository.h" + +typedef struct fake_backend { + git_odb_backend parent; + + git_error_code error_code; + + int exists_calls; + int read_calls; + int read_header_calls; + int read_prefix_calls; +} fake_backend; + +static git_repository *_repo; +static fake_backend *_fake; +static git_oid _oid; + +static int fake_backend__exists(git_odb_backend *backend, const git_oid *oid) +{ + fake_backend *fake; + + GIT_UNUSED(oid); + + fake = (fake_backend *)backend; + + fake->exists_calls++; + + return (fake->error_code == GIT_OK); +} + +static int fake_backend__read( + void **buffer_p, size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *oid) +{ + fake_backend *fake; + + GIT_UNUSED(buffer_p); + GIT_UNUSED(len_p); + GIT_UNUSED(type_p); + GIT_UNUSED(oid); + + fake = (fake_backend *)backend; + + fake->read_calls++; + + *len_p = 0; + *buffer_p = NULL; + *type_p = GIT_OBJ_BLOB; + + return fake->error_code; +} + +static int fake_backend__read_header( + size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *oid) +{ + fake_backend *fake; + + GIT_UNUSED(len_p); + GIT_UNUSED(type_p); + GIT_UNUSED(oid); + + fake = (fake_backend *)backend; + + fake->read_header_calls++; + + *len_p = 0; + *type_p = GIT_OBJ_BLOB; + + return fake->error_code; +} + +static int fake_backend__read_prefix( + git_oid *out_oid, void **buffer_p, size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *short_oid, size_t len) +{ + fake_backend *fake; + + GIT_UNUSED(out_oid); + GIT_UNUSED(buffer_p); + GIT_UNUSED(len_p); + GIT_UNUSED(type_p); + GIT_UNUSED(short_oid); + GIT_UNUSED(len); + + fake = (fake_backend *)backend; + + fake->read_prefix_calls++; + + *len_p = 0; + *buffer_p = NULL; + *type_p = GIT_OBJ_BLOB; + + return fake->error_code; +} + +static void fake_backend__free(git_odb_backend *_backend) +{ + fake_backend *backend; + + backend = (fake_backend *)_backend; + + git__free(backend); +} + +static int build_fake_backend( + git_odb_backend **out, + git_error_code error_code) +{ + fake_backend *backend; + + backend = git__calloc(1, sizeof(fake_backend)); + GITERR_CHECK_ALLOC(backend); + + backend->parent.version = GIT_ODB_BACKEND_VERSION; + + backend->parent.refresh = NULL; + backend->error_code = error_code; + + backend->parent.read = fake_backend__read; + backend->parent.read_prefix = fake_backend__read_prefix; + backend->parent.read_header = fake_backend__read_header; + backend->parent.exists = fake_backend__exists; + backend->parent.free = &fake_backend__free; + + *out = (git_odb_backend *)backend; + + return 0; +} + +static void setup_repository_and_backend(git_error_code error_code) +{ + git_odb *odb; + git_odb_backend *backend; + + _repo = cl_git_sandbox_init("testrepo.git"); + + cl_git_pass(build_fake_backend(&backend, error_code)); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_git_pass(git_odb_add_backend(odb, backend, 10)); + + _fake = (fake_backend *)backend; + + cl_git_pass(git_oid_fromstr(&_oid, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")); +} + +void test_odb_backend_nonrefreshing__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_odb_backend_nonrefreshing__exists_is_invoked_once_on_failure(void) +{ + git_odb *odb; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_assert_equal_b(false, git_odb_exists(odb, &_oid)); + + cl_assert_equal_i(1, _fake->exists_calls); +} + +void test_odb_backend_nonrefreshing__read_is_invoked_once_on_failure(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_fail_with( + git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY), + GIT_ENOTFOUND); + + cl_assert_equal_i(1, _fake->read_calls); +} + +void test_odb_backend_nonrefreshing__readprefix_is_invoked_once_on_failure(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_fail_with( + git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY), + GIT_ENOTFOUND); + + cl_assert_equal_i(1, _fake->read_prefix_calls); +} + +void test_odb_backend_nonrefreshing__readheader_is_invoked_once_on_failure(void) +{ + git_odb *odb; + size_t len; + git_otype type; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + + cl_git_fail_with( + git_odb_read_header(&len, &type, odb, &_oid), + GIT_ENOTFOUND); + + cl_assert_equal_i(1, _fake->read_header_calls); +} + +void test_odb_backend_nonrefreshing__exists_is_invoked_once_on_success(void) +{ + git_odb *odb; + + setup_repository_and_backend(GIT_OK); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_assert_equal_b(true, git_odb_exists(odb, &_oid)); + + cl_assert_equal_i(1, _fake->exists_calls); +} + +void test_odb_backend_nonrefreshing__read_is_invoked_once_on_success(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_OK); + + cl_git_pass(git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY)); + + cl_assert_equal_i(1, _fake->read_calls); + + git_object_free(obj); +} + +void test_odb_backend_nonrefreshing__readprefix_is_invoked_once_on_success(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_OK); + + cl_git_pass(git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY)); + + cl_assert_equal_i(1, _fake->read_prefix_calls); + + git_object_free(obj); +} + +void test_odb_backend_nonrefreshing__readheader_is_invoked_once_on_success(void) +{ + git_odb *odb; + size_t len; + git_otype type; + + setup_repository_and_backend(GIT_OK); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + + cl_git_pass(git_odb_read_header(&len, &type, odb, &_oid)); + + cl_assert_equal_i(1, _fake->read_header_calls); +}