From e47313da28cc0766e5aa37b9fd4adfcb04307a65 Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Wed, 26 Feb 2014 18:56:32 +0000 Subject: [PATCH 01/15] Allow a static build of redis --- redis/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/redis/CMakeLists.txt b/redis/CMakeLists.txt index e5ab30e..519daef 100644 --- a/redis/CMakeLists.txt +++ b/redis/CMakeLists.txt @@ -15,5 +15,12 @@ ENDIF () # Compile and link libgit2 INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDE_DIRS} ${LIBHIREDIS_INCLUDE_DIRS}) -ADD_LIBRARY(git2-redis hiredis.c) + +ADD_LIBRARY(core OBJECT hiredis.c) +IF (BUILD_SHARED_LIBS) + ADD_LIBRARY(git2-redis SHARED $) +ELSE () + ADD_LIBRARY(git2-redis STATIC $) +ENDIF () + TARGET_LINK_LIBRARIES(git2-redis ${LIBGIT2_LIBRARIES} ${LIBHIREDIS_LIBRARIES}) From cef209920e84dba89d3206fdfe2c03665869f067 Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Wed, 26 Feb 2014 18:57:11 +0000 Subject: [PATCH 02/15] Allow libgit2 location override for redis backend --- redis/CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/redis/CMakeLists.txt b/redis/CMakeLists.txt index 519daef..6296318 100644 --- a/redis/CMakeLists.txt +++ b/redis/CMakeLists.txt @@ -1,12 +1,21 @@ PROJECT(libgit2-redis C) CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -INCLUDE(../CMake/FindLibgit2.cmake) INCLUDE(../CMake/FindHiredis.cmake) # Build options OPTION (BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON) OPTION (BUILD_TESTS "Build Tests" ON) +SET (PC_LIBGIT2_LIBRARY_DIRS "" CACHE STRING "libgit2 path") +SET (PC_LIBGIT2_INCLUDE_DIRS "" CACHE STRING "libgit2 include directories") + +# Allow overriding to local libgit2. I'm pretty sure I'm doing this wrong. +IF (${PC_LIBGIT2_INCLUDE_DIRS} STREQUAL "") + INCLUDE(../CMake/FindLibgit2.cmake) +ELSE () + SET (LIBGIT2_LIBRARIES ${PC_LIBGIT2_LIBRARY_DIRS}) + SET (LIBGIT2_INCLUDE_DIRS ${PC_LIBGIT2_INCLUDE_DIRS}) +ENDIF () # Build Release by default IF (NOT CMAKE_BUILD_TYPE) From 77b1e712d813ac40bf74fc2df00c37328c934432 Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Wed, 26 Feb 2014 19:01:47 +0000 Subject: [PATCH 03/15] Updated odb backend to current libgit2 --- redis/hiredis.c | 278 ++++++++++++++++++++++++++---------------------- 1 file changed, 153 insertions(+), 125 deletions(-) diff --git a/redis/hiredis.c b/redis/hiredis.c index 2387ddd..b0f7fc7 100644 --- a/redis/hiredis.c +++ b/redis/hiredis.c @@ -26,180 +26,208 @@ #include #include #include -#include +#include #include typedef struct { - git_odb_backend parent; + git_odb_backend parent; - redisContext *db; -} hiredis_backend; + const char *prefix; + const char *repo_path; + redisContext *db; +} hiredis_odb_backend; -int hiredis_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) +int hiredis_odb_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) { - hiredis_backend *backend; - int error; - redisReply *reply; - - assert(len_p && type_p && _backend && oid); - - backend = (hiredis_backend *) _backend; - error = GIT_ERROR; - - reply = redisCommand(backend->db, "HMGET %b %s %s", oid->id, GIT_OID_RAWSZ, - "type", "size"); - - if (reply && reply->type == REDIS_REPLY_ARRAY) { - if (reply->element[0]->type != REDIS_REPLY_NIL && - reply->element[0]->type != REDIS_REPLY_NIL) { - *type_p = (git_otype) atoi(reply->element[0]->str); - *len_p = (size_t) atoi(reply->element[1]->str); - error = GIT_SUCCESS; - } else { - error = GIT_ENOTFOUND; - } - } else { - error = GIT_ERROR; - } - - freeReplyObject(reply); - return error; + hiredis_odb_backend *backend; + int error; + redisReply *reply; + char *str_id = calloc(GIT_OID_HEXSZ + 1, sizeof(char)); + + assert(len_p && type_p && _backend && oid); + + backend = (hiredis_odb_backend *) _backend; + error = GIT_ERROR; + + git_oid_tostr(str_id, GIT_OID_HEXSZ, oid); + + reply = redisCommand(backend->db, "HMGET %s:%s:odb:%s %s %s", backend->prefix, backend->repo_path, str_id, "type", "size"); + + if (reply && reply->type == REDIS_REPLY_ARRAY) { + if (reply->element[0]->type != REDIS_REPLY_NIL && + reply->element[0]->type != REDIS_REPLY_NIL) { + *type_p = (git_otype) atoi(reply->element[0]->str); + *len_p = (size_t) atoi(reply->element[1]->str); + error = GIT_OK; + } else { + giterr_set_str(GITERR_ODB, "Redis odb storage corrupted"); + error = GIT_ENOTFOUND; + } + } else { + giterr_set_str(GITERR_ODB, "Redis odb storage error"); + error = GIT_ERROR; + } + + free(str_id); + freeReplyObject(reply); + return error; } -int hiredis_backend__read(void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) +int hiredis_odb_backend__read(void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) { - hiredis_backend *backend; - int error; - redisReply *reply; - - assert(data_p && len_p && type_p && _backend && oid); - - backend = (hiredis_backend *) _backend; - error = GIT_ERROR; - - reply = redisCommand(backend->db, "HMGET %b %s %s %s", oid->id, GIT_OID_RAWSZ, - "type", "size", "data"); - - if (reply && reply->type == REDIS_REPLY_ARRAY) { - if (reply->element[0]->type != REDIS_REPLY_NIL && - reply->element[1]->type != REDIS_REPLY_NIL && - reply->element[2]->type != REDIS_REPLY_NIL) { - *type_p = (git_otype) atoi(reply->element[0]->str); - *len_p = (size_t) atoi(reply->element[1]->str); - *data_p = malloc(*len_p); - if (*data_p == NULL) { - error = GIT_ENOMEM; - } else { - memcpy(*data_p, reply->element[2]->str, *len_p); - error = GIT_SUCCESS; - } - } else { - error = GIT_ENOTFOUND; - } - } else { - error = GIT_ERROR; - } - - freeReplyObject(reply); - return error == GIT_SUCCESS; + hiredis_odb_backend *backend; + int error; + redisReply *reply; + char *str_id = calloc(GIT_OID_HEXSZ + 1, sizeof(char)); + + assert(data_p && len_p && type_p && _backend && oid); + + backend = (hiredis_odb_backend *) _backend; + error = GIT_ERROR; + + git_oid_tostr(str_id, GIT_OID_HEXSZ, oid); + + reply = redisCommand(backend->db, "HMGET %s:%s:odb:%s %s %s %s", backend->prefix, backend->repo_path, str_id, + "type", "size", "data"); + + if (reply && reply->type == REDIS_REPLY_ARRAY) { + if (reply->element[0]->type != REDIS_REPLY_NIL && + reply->element[1]->type != REDIS_REPLY_NIL && + reply->element[2]->type != REDIS_REPLY_NIL) { + *type_p = (git_otype) atoi(reply->element[0]->str); + *len_p = (size_t) atoi(reply->element[1]->str); + *data_p = malloc(*len_p); + if (*data_p == NULL) { + error = GITERR_NOMEMORY; + } else { + memcpy(*data_p, reply->element[2]->str, *len_p); + error = GIT_OK; + } + } else { + giterr_set_str(GITERR_ODB, "Redis odb couldn't find object"); + error = GIT_ENOTFOUND; + } + } else { + giterr_set_str(GITERR_ODB, "Redis odb storage error"); + error = GIT_ERROR; + } + + free(str_id); + freeReplyObject(reply); + return error; } -int hiredis_backend__read_prefix(git_oid *out_oid, +int hiredis_odb_backend__read_prefix(git_oid *out_oid, void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, - const git_oid *short_oid, unsigned int len) + const git_oid *short_oid, size_t len) { if (len >= GIT_OID_HEXSZ) { /* Just match the full identifier */ - int error = hiredis_backend__read(data_p, len_p, type_p, _backend, short_oid); - if (error == GIT_SUCCESS) + int error = hiredis_odb_backend__read(data_p, len_p, type_p, _backend, short_oid); + if (error == GIT_OK) git_oid_cpy(out_oid, short_oid); return error; - } else if (len < GIT_OID_HEXSZ) { - /* TODO */ - return GIT_ENOTIMPLEMENTED; } + + /* TODO prefix */ + giterr_set_str(GITERR_ODB, "Redis odb doesn't not implement oid prefix lookup"); + return GITERR_INVALID; } -int hiredis_backend__exists(git_odb_backend *_backend, const git_oid *oid) +int hiredis_odb_backend__exists(git_odb_backend *_backend, const git_oid *oid) { - hiredis_backend *backend; - int found; - redisReply *reply; + hiredis_odb_backend *backend; + int found; + redisReply *reply; + char *str_id = calloc(GIT_OID_HEXSZ + 1, sizeof(char)); + + assert(_backend && oid); - assert(_backend && oid); + backend = (hiredis_odb_backend *) _backend; + found = 0; - backend = (hiredis_backend *) _backend; - found = 0; + git_oid_tostr(str_id, GIT_OID_HEXSZ, oid); - reply = redisCommand(backend->db, "exists %b", oid->id, GIT_OID_RAWSZ); - if (reply && reply->type != REDIS_REPLY_NIL && reply->type != REDIS_REPLY_ERROR) - found = 1; + reply = redisCommand(backend->db, "exists %s:%s:odb:%s", backend->prefix, backend->repo_path, str_id); + if (reply->type == REDIS_REPLY_INTEGER) + found = reply->integer; - freeReplyObject(reply); - return found; + free(str_id); + freeReplyObject(reply); + return found; } -int hiredis_backend__write(git_oid *id, git_odb_backend *_backend, const void *data, size_t len, git_otype type) +int hiredis_odb_backend__write(git_odb_backend *_backend, const git_oid *oid, const void *data, size_t len, git_otype type) { - hiredis_backend *backend; - int error; - redisReply *reply; + hiredis_odb_backend *backend; + int error; + redisReply *reply; + char *str_id = calloc(GIT_OID_HEXSZ + 1, sizeof(char)); - assert(id && _backend && data); + assert(oid && _backend && data); - backend = (hiredis_backend *) _backend; - error = GIT_ERROR; + backend = (hiredis_odb_backend *) _backend; + error = GIT_ERROR; - if ((error = git_odb_hash(id, data, len, type)) < 0) - return error; + git_oid_tostr(str_id, GIT_OID_HEXSZ, oid); - reply = redisCommand(backend->db, "HMSET %b " - "type %d " - "size %d " - "data %b ", id->id, GIT_OID_RAWSZ, - (int) type, len, data, len); + reply = redisCommand(backend->db, "HMSET %s:%s:odb:%s " + "type %d " + "size %d " + "data %b ", backend->prefix, backend->repo_path, str_id, + (int) type, len, data, len); + free(str_id); - error = (reply == NULL || reply->type == REDIS_REPLY_ERROR) ? GIT_ERROR : GIT_SUCCESS; + error = (reply == NULL || reply->type == REDIS_REPLY_ERROR) ? GIT_ERROR : GIT_OK; - freeReplyObject(reply); - return error; + freeReplyObject(reply); + return error; } -void hiredis_backend__free(git_odb_backend *_backend) +void hiredis_odb_backend__free(git_odb_backend *_backend) { - hiredis_backend *backend; - assert(_backend); - backend = (hiredis_backend *) _backend; + hiredis_odb_backend *backend; - redisFree(backend->db); + assert(_backend); + backend = (hiredis_odb_backend *) _backend; - free(backend); + redisFree(backend->db); + + free(backend); } -int git_odb_backend_hiredis(git_odb_backend **backend_out, const char *host, int port) +int git_odb_backend_hiredis(git_odb_backend **backend_out, const char* prefix, const char* path, const char *host, int port) { - hiredis_backend *backend; + hiredis_odb_backend *backend; - backend = calloc(1, sizeof (hiredis_backend)); - if (backend == NULL) - return GIT_ENOMEM; + backend = calloc(1, sizeof (hiredis_odb_backend)); + if (backend == NULL) + return GITERR_NOMEMORY; - backend->db = redisConnect(host, port); - if (backend->db->err) { + backend->db = redisConnect(host, port); + if (backend->db->err) { free(backend); + giterr_set_str(GITERR_REFERENCE, "Redis refdb storage couldn't connect to redis server"); return GIT_ERROR; } - backend->parent.read = &hiredis_backend__read; - backend->parent.read_prefix = &hiredis_backend__read_prefix; - backend->parent.read_header = &hiredis_backend__read_header; - backend->parent.write = &hiredis_backend__write; - backend->parent.exists = &hiredis_backend__exists; - backend->parent.free = &hiredis_backend__free; + backend->prefix = prefix; + backend->repo_path = path; - *backend_out = (git_odb_backend *) backend; + backend->parent.version = 1; - return GIT_SUCCESS; -} + backend->parent.read = &hiredis_odb_backend__read; + backend->parent.write = &hiredis_odb_backend__write; + backend->parent.read_prefix = &hiredis_odb_backend__read_prefix; + backend->parent.read_header = &hiredis_odb_backend__read_header; + backend->parent.exists = &hiredis_odb_backend__exists; + backend->parent.free = &hiredis_odb_backend__free; + + backend->parent.writestream = NULL; + backend->parent.foreach = NULL; + *backend_out = (git_odb_backend *) backend; + + return GIT_OK; +} From d831e63fde85b076dc4f277e3c1508eed19d0659 Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Wed, 26 Feb 2014 19:02:19 +0000 Subject: [PATCH 04/15] Added redis refdb backend --- redis/hiredis.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) diff --git a/redis/hiredis.c b/redis/hiredis.c index b0f7fc7..aaea7e8 100644 --- a/redis/hiredis.c +++ b/redis/hiredis.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include typedef struct { @@ -37,6 +39,25 @@ typedef struct { redisContext *db; } hiredis_odb_backend; +typedef struct { + git_refdb_backend parent; + + const char *prefix; + const char *repo_path; + redisContext *db; +} hiredis_refdb_backend; + +typedef struct { + git_reference_iterator parent; + + size_t current; + redisReply *keys; + + hiredis_refdb_backend *backend; +} hiredis_refdb_iterator; + +/* Odb methods */ + int hiredis_odb_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) { hiredis_odb_backend *backend; @@ -197,6 +218,274 @@ void hiredis_odb_backend__free(git_odb_backend *_backend) free(backend); } +/* Refdb methods */ + +int hiredis_refdb_backend__exists(int *exists, git_refdb_backend *_backend, const char *ref_name) +{ + hiredis_refdb_backend *backend; + int error = GIT_OK; + redisReply *reply; + + assert(ref_name && _backend); + + backend = (hiredis_refdb_backend *) _backend; + + reply = redisCommand(backend->db, "EXISTS %s:%s:refdb:%s", backend->prefix, backend->repo_path, ref_name); + if (reply->type == REDIS_REPLY_INTEGER) { + *exists = reply->integer; + } else { + giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error"); + error = GIT_ERROR; + } + + freeReplyObject(reply); + return error; +} + +int hiredis_refdb_backend__lookup(git_reference **out, git_refdb_backend *_backend, const char *ref_name) +{ + hiredis_refdb_backend *backend; + int error = GIT_OK; + redisReply *reply; + git_oid oid; + + assert(ref_name && _backend); + + backend = (hiredis_refdb_backend *) _backend; + + reply = redisCommand(backend->db, "HMGET %s:%s:refdb:%s type target", backend->prefix, backend->repo_path, ref_name); + if(reply->type == REDIS_REPLY_ARRAY) { + if (reply->element[0]->type != REDIS_REPLY_NIL && reply->element[1]->type != REDIS_REPLY_NIL) { + git_ref_t type = (git_ref_t) atoi(reply->element[0]->str); + + if (type == GIT_REF_OID) { + git_oid_fromstr(&oid, reply->element[1]->str); + *out = git_reference__alloc(ref_name, &oid, NULL); + } else if (type == GIT_REF_SYMBOLIC) { + *out = git_reference__alloc_symbolic(ref_name, reply->element[1]->str); + } else { + giterr_set_str(GITERR_REFERENCE, "Redis refdb storage corrupted (unknown ref type returned)"); + error = GIT_ERROR; + } + + } else { + giterr_set_str(GITERR_REFERENCE, "Redis refdb couldn't find ref"); + error = GIT_ENOTFOUND; + } + } else { + giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error"); + error = GIT_ERROR; + } + + freeReplyObject(reply); + return error; +} + +int hiredis_refdb_backend__iterator_next(git_reference **ref, git_reference_iterator *_iter) { + hiredis_refdb_iterator *iter; + hiredis_refdb_backend *backend; + char* ref_name; + int error; + + assert(_iter); + iter = (hiredis_refdb_iterator *) _iter; + + if(iter->current < iter->keys->elements) { + ref_name = strstr(iter->keys->element[iter->current++]->str, ":refdb:") + 7; + error = hiredis_refdb_backend__lookup(ref, (git_refdb_backend *) iter->backend, ref_name); + + return error; + } else { + return GIT_ITEROVER; + } +} + +int hiredis_refdb_backend__iterator_next_name(const char **ref_name, git_reference_iterator *_iter) { + hiredis_refdb_iterator *iter; + + assert(_iter); + iter = (hiredis_refdb_iterator *) _iter; + + if(iter->current < iter->keys->elements) { + *ref_name = strdup(strstr(iter->keys->element[iter->current++]->str, ":refdb:") + 7); + + return GIT_OK; + } else { + return GIT_ITEROVER; + } +} + +void hiredis_refdb_backend__iterator_free(git_reference_iterator *_iter) { + hiredis_refdb_iterator *iter; + + assert(_iter); + iter = (hiredis_refdb_iterator *) _iter; + + freeReplyObject(iter->keys); + + free(iter); +} + +int hiredis_refdb_backend__iterator(git_reference_iterator **_iter, struct git_refdb_backend *_backend, const char *glob) +{ + hiredis_refdb_backend *backend; + hiredis_refdb_iterator *iterator; + int error = GIT_OK; + redisReply *reply; + + assert(_backend); + + backend = (hiredis_refdb_backend *) _backend; + + reply = redisCommand(backend->db, "KEYS %s:%s:refdb:%s", backend->prefix, backend->repo_path, (glob != NULL ? glob : "*")); + if(reply->type != REDIS_REPLY_ARRAY) { + freeReplyObject(reply); + giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error"); + return GIT_ERROR; + } + + iterator = calloc(1, sizeof(hiredis_refdb_iterator)); + + iterator->backend = backend; + iterator->keys = reply; + + iterator->parent.next = &hiredis_refdb_backend__iterator_next; + iterator->parent.next_name = &hiredis_refdb_backend__iterator_next_name; + iterator->parent.free = &hiredis_refdb_backend__iterator_free; + + *_iter = (git_reference_iterator *) iterator; + + return GIT_OK; +} + +int hiredis_refdb_backend__write(git_refdb_backend *_backend, const git_reference *ref, int force, const git_signature *who, + const char *message) // FIXME when rugged gets updated to the latest libgit2 update this to the latest backend API +{ + hiredis_refdb_backend *backend; + int error = GIT_OK; + redisReply *reply; + + const char *name = git_reference_name(ref); + const git_oid *target; + const char *symbolic_target; + char oid_str[GIT_OID_HEXSZ + 1]; + + assert(ref && _backend); + + backend = (hiredis_refdb_backend *) _backend; + + target = git_reference_target(ref); + symbolic_target = git_reference_symbolic_target(ref); + + /* FIXME handle force correctly */ + + if (target) { + git_oid_nfmt(oid_str, sizeof(oid_str), target); + reply = redisCommand(backend->db, "HMSET %s:%s:refdb:%s type %d target %s", backend->prefix, backend->repo_path, name, GIT_REF_OID, oid_str); + } else { + symbolic_target = git_reference_symbolic_target(ref); + reply = redisCommand(backend->db, "HMSET %s:%s:refdb:%s type %d target %s", backend->prefix, backend->repo_path, name, GIT_REF_SYMBOLIC, symbolic_target); + } + + if(reply->type == REDIS_REPLY_ERROR) { + giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error"); + error = GIT_ERROR; + } + + freeReplyObject(reply); + return error; +} + +int hiredis_refdb_backend__rename(git_reference **out, git_refdb_backend *_backend, const char *old_name, + const char *new_name, int force, const git_signature *who, const char *message) +{ + hiredis_refdb_backend *backend; + int error = GIT_OK; + redisReply *reply; + + assert(old_name && new_name && _backend); + + backend = (hiredis_refdb_backend *) _backend; + + reply = redisCommand(backend->db, "RENAME %s:%s:refdb:%s %s:%s:refdb:%s", + backend->prefix, backend->repo_path, old_name, backend->prefix, backend->repo_path, new_name); + if(reply->type == REDIS_REPLY_ERROR) { + freeReplyObject(reply); + + giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error"); + return GIT_ERROR; + } + + freeReplyObject(reply); + return hiredis_refdb_backend__lookup(out, _backend, new_name); +} + +int hiredis_refdb_backend__del(git_refdb_backend *_backend, const char *ref_name) // FIXME when rugged gets updated to the latest libgit2 update this to the latest backend API +{ + hiredis_refdb_backend *backend; + int error = GIT_OK; + redisReply *reply; + + assert(ref_name && _backend); + + backend = (hiredis_refdb_backend *) _backend; + + reply = redisCommand(backend->db, "DEL %s:%s:refdb:%s", backend->prefix, backend->repo_path, ref_name); + if(reply->type == REDIS_REPLY_ERROR) { + giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error"); + error = GIT_ERROR; + } + + freeReplyObject(reply); + return error; +} + +void hiredis_refdb_backend__free(git_refdb_backend *_backend) +{ + hiredis_refdb_backend *backend; + + assert(_backend); + backend = (hiredis_refdb_backend *) _backend; + + redisFree(backend->db); + + free(backend); +} + +/* reflog methods */ + +int hiredis_refdb_backend__has_log(git_refdb_backend *_backend, const char *refname) +{ + return 0; +} + +int hiredis_refdb_backend__ensure_log(git_refdb_backend *_backend, const char *refname) +{ + return GIT_ERROR; +} + +int hiredis_refdb_backend__reflog_read(git_reflog **out, git_refdb_backend *_backend, const char *name) +{ + return GIT_ERROR; +} + +int hiredis_refdb_backend__reflog_write(git_refdb_backend *_backend, git_reflog *reflog) +{ + return GIT_ERROR; +} + +int hiredis_refdb_backend__reflog_rename(git_refdb_backend *_backend, const char *old_name, const char *new_name) +{ + return GIT_ERROR; +} + +int hiredis_refdb_backend__reflog_delete(git_refdb_backend *_backend, const char *name) +{ + return GIT_ERROR; +} + +/* Constructors */ + int git_odb_backend_hiredis(git_odb_backend **backend_out, const char* prefix, const char* path, const char *host, int port) { hiredis_odb_backend *backend; @@ -231,3 +520,43 @@ int git_odb_backend_hiredis(git_odb_backend **backend_out, const char* prefix, c return GIT_OK; } + +int git_refdb_backend_hiredis(git_refdb_backend **backend_out, const char* prefix, const char* path, const char *host, int port) +{ + hiredis_refdb_backend *backend; + + backend = calloc(1, sizeof(hiredis_refdb_backend)); + if (backend == NULL) + return GITERR_NOMEMORY; + + backend-> db = redisConnect(host, port); + if (backend->db->err) { + free(backend); + giterr_set_str(GITERR_REFERENCE, "Redis refdb storage couldn't connect to redis server"); + return GIT_ERROR; + } + + backend->prefix = prefix; + backend->repo_path = path; + + backend->parent.exists = &hiredis_refdb_backend__exists; + backend->parent.lookup = &hiredis_refdb_backend__lookup; + backend->parent.iterator = &hiredis_refdb_backend__iterator; + backend->parent.write = &hiredis_refdb_backend__write; + backend->parent.del = &hiredis_refdb_backend__del; + backend->parent.rename = &hiredis_refdb_backend__rename; + backend->parent.compress = NULL; + backend->parent.free = &hiredis_refdb_backend__free; + + backend->parent.has_log = &hiredis_refdb_backend__has_log; + backend->parent.ensure_log = &hiredis_refdb_backend__ensure_log; + backend->parent.reflog_read = &hiredis_refdb_backend__reflog_read; + backend->parent.reflog_write = &hiredis_refdb_backend__reflog_write; + backend->parent.reflog_rename = &hiredis_refdb_backend__reflog_rename; + backend->parent.reflog_delete = &hiredis_refdb_backend__reflog_delete; + + *backend_out = (git_refdb_backend *) backend; + + return GIT_OK; +} + From 84b8d1b1f889f3f9359ff4a66955b66ccff61c72 Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Fri, 28 Feb 2014 17:47:27 +0000 Subject: [PATCH 05/15] Fix reference iteration mask --- redis/hiredis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redis/hiredis.c b/redis/hiredis.c index aaea7e8..0c6d3e9 100644 --- a/redis/hiredis.c +++ b/redis/hiredis.c @@ -337,7 +337,7 @@ int hiredis_refdb_backend__iterator(git_reference_iterator **_iter, struct git_r backend = (hiredis_refdb_backend *) _backend; - reply = redisCommand(backend->db, "KEYS %s:%s:refdb:%s", backend->prefix, backend->repo_path, (glob != NULL ? glob : "*")); + reply = redisCommand(backend->db, "KEYS %s:%s:refdb:refs/%s", backend->prefix, backend->repo_path, (glob != NULL ? glob : "*")); if(reply->type != REDIS_REPLY_ARRAY) { freeReplyObject(reply); giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error"); From d71769dd004d339939ebfeb4b56aecb253a69c8d Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Tue, 4 Mar 2014 09:26:09 +0000 Subject: [PATCH 06/15] Added authentication support for redis --- redis/hiredis.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/redis/hiredis.c b/redis/hiredis.c index 0c6d3e9..d6c772c 100644 --- a/redis/hiredis.c +++ b/redis/hiredis.c @@ -486,9 +486,10 @@ int hiredis_refdb_backend__reflog_delete(git_refdb_backend *_backend, const char /* Constructors */ -int git_odb_backend_hiredis(git_odb_backend **backend_out, const char* prefix, const char* path, const char *host, int port) +int git_odb_backend_hiredis(git_odb_backend **backend_out, const char* prefix, const char* path, const char *host, int port, char* password) { hiredis_odb_backend *backend; + redisReply *reply; backend = calloc(1, sizeof (hiredis_odb_backend)); if (backend == NULL) @@ -497,10 +498,19 @@ int git_odb_backend_hiredis(git_odb_backend **backend_out, const char* prefix, c backend->db = redisConnect(host, port); if (backend->db->err) { free(backend); - giterr_set_str(GITERR_REFERENCE, "Redis refdb storage couldn't connect to redis server"); + giterr_set_str(GITERR_REFERENCE, "Redis odb storage couldn't connect to redis server"); return GIT_ERROR; } + if(password != NULL) { + reply = redisCommand(backend->db, "AUTH %s", password); + if (reply->type == REDIS_REPLY_ERROR) { + giterr_set_str(GITERR_REFERENCE, "Redis odb storage authentication with redis server failed"); + return GIT_ERROR; + } + freeReplyObject(reply); + } + backend->prefix = prefix; backend->repo_path = path; @@ -521,9 +531,10 @@ int git_odb_backend_hiredis(git_odb_backend **backend_out, const char* prefix, c return GIT_OK; } -int git_refdb_backend_hiredis(git_refdb_backend **backend_out, const char* prefix, const char* path, const char *host, int port) +int git_refdb_backend_hiredis(git_refdb_backend **backend_out, const char* prefix, const char* path, const char *host, int port, char* password) { hiredis_refdb_backend *backend; + redisReply *reply; backend = calloc(1, sizeof(hiredis_refdb_backend)); if (backend == NULL) @@ -536,6 +547,15 @@ int git_refdb_backend_hiredis(git_refdb_backend **backend_out, const char* prefi return GIT_ERROR; } + if(password != NULL) { + reply = redisCommand(backend->db, "AUTH %s", password); + if (reply->type == REDIS_REPLY_ERROR) { + giterr_set_str(GITERR_REFERENCE, "Redis refdb storage authentication with redis server failed"); + return GIT_ERROR; + } + freeReplyObject(reply); + } + backend->prefix = prefix; backend->repo_path = path; From af7db20fefb1312091068ae076eed47a64dab4d3 Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Tue, 4 Mar 2014 13:47:43 +0000 Subject: [PATCH 07/15] Reuse a single redis connection --- redis/hiredis.c | 58 +++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/redis/hiredis.c b/redis/hiredis.c index d6c772c..59c6fa6 100644 --- a/redis/hiredis.c +++ b/redis/hiredis.c @@ -56,6 +56,8 @@ typedef struct { hiredis_refdb_backend *backend; } hiredis_refdb_iterator; +static redisContext *sharedConnection = NULL; + /* Odb methods */ int hiredis_odb_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) @@ -495,22 +497,26 @@ int git_odb_backend_hiredis(git_odb_backend **backend_out, const char* prefix, c if (backend == NULL) return GITERR_NOMEMORY; - backend->db = redisConnect(host, port); - if (backend->db->err) { - free(backend); - giterr_set_str(GITERR_REFERENCE, "Redis odb storage couldn't connect to redis server"); - return GIT_ERROR; - } - - if(password != NULL) { - reply = redisCommand(backend->db, "AUTH %s", password); - if (reply->type == REDIS_REPLY_ERROR) { - giterr_set_str(GITERR_REFERENCE, "Redis odb storage authentication with redis server failed"); + if (sharedConnection == NULL) { + sharedConnection = redisConnect(host, port); + if (sharedConnection->err) { + free(backend); + giterr_set_str(GITERR_REFERENCE, "Redis odb storage couldn't connect to redis server"); return GIT_ERROR; } - freeReplyObject(reply); + + if(password != NULL) { + reply = redisCommand(sharedConnection, "AUTH %s", password); + if (reply->type == REDIS_REPLY_ERROR) { + giterr_set_str(GITERR_REFERENCE, "Redis odb storage authentication with redis server failed"); + return GIT_ERROR; + } + freeReplyObject(reply); + } } + backend->db = sharedConnection; + backend->prefix = prefix; backend->repo_path = path; @@ -540,22 +546,26 @@ int git_refdb_backend_hiredis(git_refdb_backend **backend_out, const char* prefi if (backend == NULL) return GITERR_NOMEMORY; - backend-> db = redisConnect(host, port); - if (backend->db->err) { - free(backend); - giterr_set_str(GITERR_REFERENCE, "Redis refdb storage couldn't connect to redis server"); - return GIT_ERROR; - } - - if(password != NULL) { - reply = redisCommand(backend->db, "AUTH %s", password); - if (reply->type == REDIS_REPLY_ERROR) { - giterr_set_str(GITERR_REFERENCE, "Redis refdb storage authentication with redis server failed"); + if (sharedConnection == NULL) { + sharedConnection = redisConnect(host, port); + if (sharedConnection->err) { + free(backend); + giterr_set_str(GITERR_REFERENCE, "Redis refdb storage couldn't connect to redis server"); return GIT_ERROR; } - freeReplyObject(reply); + + if(password != NULL) { + reply = redisCommand(sharedConnection, "AUTH %s", password); + if (reply->type == REDIS_REPLY_ERROR) { + giterr_set_str(GITERR_REFERENCE, "Redis refdb storage authentication with redis server failed"); + return GIT_ERROR; + } + freeReplyObject(reply); + } } + backend->db = sharedConnection; + backend->prefix = prefix; backend->repo_path = path; From f56fbf5fabe300d5971c28d3e913eb3e484c3d9f Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Wed, 5 Mar 2014 16:02:14 +0000 Subject: [PATCH 08/15] Fix prefix and repo_path memory management --- redis/hiredis.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/redis/hiredis.c b/redis/hiredis.c index 59c6fa6..10d0550 100644 --- a/redis/hiredis.c +++ b/redis/hiredis.c @@ -34,16 +34,16 @@ typedef struct { git_odb_backend parent; - const char *prefix; - const char *repo_path; + char *prefix; + char *repo_path; redisContext *db; } hiredis_odb_backend; typedef struct { git_refdb_backend parent; - const char *prefix; - const char *repo_path; + char *prefix; + char *repo_path; redisContext *db; } hiredis_refdb_backend; @@ -215,6 +215,9 @@ void hiredis_odb_backend__free(git_odb_backend *_backend) assert(_backend); backend = (hiredis_odb_backend *) _backend; + free(backend->repo_path); + free(backend->prefix); + redisFree(backend->db); free(backend); @@ -449,6 +452,9 @@ void hiredis_refdb_backend__free(git_refdb_backend *_backend) assert(_backend); backend = (hiredis_refdb_backend *) _backend; + free(backend->repo_path); + free(backend->prefix); + redisFree(backend->db); free(backend); @@ -517,8 +523,8 @@ int git_odb_backend_hiredis(git_odb_backend **backend_out, const char* prefix, c backend->db = sharedConnection; - backend->prefix = prefix; - backend->repo_path = path; + backend->prefix = strdup(prefix); + backend->repo_path = strdup(path); backend->parent.version = 1; @@ -566,8 +572,8 @@ int git_refdb_backend_hiredis(git_refdb_backend **backend_out, const char* prefi backend->db = sharedConnection; - backend->prefix = prefix; - backend->repo_path = path; + backend->prefix = strdup(prefix); + backend->repo_path = strdup(path); backend->parent.exists = &hiredis_refdb_backend__exists; backend->parent.lookup = &hiredis_refdb_backend__lookup; From fffd4ac908cfb43c5df9e65d7ece38b1415e6cb3 Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Thu, 17 Apr 2014 19:31:32 +0100 Subject: [PATCH 09/15] fix reference iteration, take 2 --- redis/hiredis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redis/hiredis.c b/redis/hiredis.c index 10d0550..a15b098 100644 --- a/redis/hiredis.c +++ b/redis/hiredis.c @@ -342,7 +342,7 @@ int hiredis_refdb_backend__iterator(git_reference_iterator **_iter, struct git_r backend = (hiredis_refdb_backend *) _backend; - reply = redisCommand(backend->db, "KEYS %s:%s:refdb:refs/%s", backend->prefix, backend->repo_path, (glob != NULL ? glob : "*")); + reply = redisCommand(backend->db, "KEYS %s:%s:refdb:%s", backend->prefix, backend->repo_path, (glob != NULL ? glob : "*")); if(reply->type != REDIS_REPLY_ARRAY) { freeReplyObject(reply); giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error"); From f8b7daef4b268e9f99f1b2f04321d5c357809e86 Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Thu, 17 Apr 2014 19:31:51 +0100 Subject: [PATCH 10/15] Minor cmake fix --- redis/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redis/CMakeLists.txt b/redis/CMakeLists.txt index 6296318..4f06b2e 100644 --- a/redis/CMakeLists.txt +++ b/redis/CMakeLists.txt @@ -10,7 +10,7 @@ SET (PC_LIBGIT2_LIBRARY_DIRS "" CACHE STRING "libgit2 path") SET (PC_LIBGIT2_INCLUDE_DIRS "" CACHE STRING "libgit2 include directories") # Allow overriding to local libgit2. I'm pretty sure I'm doing this wrong. -IF (${PC_LIBGIT2_INCLUDE_DIRS} STREQUAL "") +IF (PC_LIBGIT2_INCLUDE_DIRS STREQUAL "") INCLUDE(../CMake/FindLibgit2.cmake) ELSE () SET (LIBGIT2_LIBRARIES ${PC_LIBGIT2_LIBRARY_DIRS}) From 34bcf9584309c4f79cfc6ca1b4b9963d433d3348 Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Tue, 22 Apr 2014 17:38:19 +0100 Subject: [PATCH 11/15] Don't use OBJECT in CMakeLists.txt --- redis/CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/redis/CMakeLists.txt b/redis/CMakeLists.txt index 4f06b2e..e7c619b 100644 --- a/redis/CMakeLists.txt +++ b/redis/CMakeLists.txt @@ -25,11 +25,10 @@ ENDIF () # Compile and link libgit2 INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDE_DIRS} ${LIBHIREDIS_INCLUDE_DIRS}) -ADD_LIBRARY(core OBJECT hiredis.c) IF (BUILD_SHARED_LIBS) - ADD_LIBRARY(git2-redis SHARED $) + ADD_LIBRARY(git2-redis SHARED hiredis.c) ELSE () - ADD_LIBRARY(git2-redis STATIC $) + ADD_LIBRARY(git2-redis STATIC hiredis.c) ENDIF () TARGET_LINK_LIBRARIES(git2-redis ${LIBGIT2_LIBRARIES} ${LIBHIREDIS_LIBRARIES}) From e484a63b2206e597702a47ed1c8f0d933a26e9b3 Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Wed, 23 Apr 2014 15:47:04 +0100 Subject: [PATCH 12/15] Reference iteration, take 3 Hopefully correct this time: - iterating with globs assumes the glob is a full name, e.g. 'refs/heads/test-*' or 'H*' - iterating without a glob uses a default glob of 'refs/*' --- redis/hiredis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redis/hiredis.c b/redis/hiredis.c index a15b098..2a2732a 100644 --- a/redis/hiredis.c +++ b/redis/hiredis.c @@ -342,7 +342,7 @@ int hiredis_refdb_backend__iterator(git_reference_iterator **_iter, struct git_r backend = (hiredis_refdb_backend *) _backend; - reply = redisCommand(backend->db, "KEYS %s:%s:refdb:%s", backend->prefix, backend->repo_path, (glob != NULL ? glob : "*")); + reply = redisCommand(backend->db, "KEYS %s:%s:refdb:%s", backend->prefix, backend->repo_path, (glob != NULL ? glob : "refs/*")); if(reply->type != REDIS_REPLY_ARRAY) { freeReplyObject(reply); giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error"); From aa6fbdbf53056b3d0e6e3217bd0d6e65c20c67e5 Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Thu, 24 Apr 2014 16:32:25 +0100 Subject: [PATCH 13/15] Remove awful useless cmake stuff --- redis/CMakeLists.txt | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/redis/CMakeLists.txt b/redis/CMakeLists.txt index e7c619b..1f1c098 100644 --- a/redis/CMakeLists.txt +++ b/redis/CMakeLists.txt @@ -1,21 +1,12 @@ PROJECT(libgit2-redis C) CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +INCLUDE(../CMake/FindLibgit2.cmake) INCLUDE(../CMake/FindHiredis.cmake) # Build options OPTION (BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON) OPTION (BUILD_TESTS "Build Tests" ON) -SET (PC_LIBGIT2_LIBRARY_DIRS "" CACHE STRING "libgit2 path") -SET (PC_LIBGIT2_INCLUDE_DIRS "" CACHE STRING "libgit2 include directories") - -# Allow overriding to local libgit2. I'm pretty sure I'm doing this wrong. -IF (PC_LIBGIT2_INCLUDE_DIRS STREQUAL "") - INCLUDE(../CMake/FindLibgit2.cmake) -ELSE () - SET (LIBGIT2_LIBRARIES ${PC_LIBGIT2_LIBRARY_DIRS}) - SET (LIBGIT2_INCLUDE_DIRS ${PC_LIBGIT2_INCLUDE_DIRS}) -ENDIF () # Build Release by default IF (NOT CMAKE_BUILD_TYPE) @@ -23,7 +14,7 @@ IF (NOT CMAKE_BUILD_TYPE) ENDIF () # Compile and link libgit2 -INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDE_DIRS} ${LIBHIREDIS_INCLUDE_DIRS}) +INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDE_DIR} ${LIBHIREDIS_INCLUDE_DIR}) IF (BUILD_SHARED_LIBS) ADD_LIBRARY(git2-redis SHARED hiredis.c) From 4d8f722ad569b575153135a9f624b7e506f6a636 Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Thu, 24 Apr 2014 16:38:08 +0100 Subject: [PATCH 14/15] Don't use pkg-config to find libgit2 This may be wrong, but turning off pkg-config in FindLibgit2.cmake makes cmake respect library paths given from the command line (with -D) --- CMake/FindLibgit2.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMake/FindLibgit2.cmake b/CMake/FindLibgit2.cmake index e33844a..7ea86b9 100644 --- a/CMake/FindLibgit2.cmake +++ b/CMake/FindLibgit2.cmake @@ -9,8 +9,8 @@ # use pkg-config to get the directories and then use these values # in the FIND_PATH() and FIND_LIBRARY() calls -FIND_PACKAGE(PkgConfig) -PKG_SEARCH_MODULE(PC_LIBGIT2 libgit2) +#FIND_PACKAGE(PkgConfig) +#PKG_SEARCH_MODULE(PC_LIBGIT2 libgit2) SET(LIBGIT2_DEFINITIONS ${PC_LIBGIT2_CFLAGS_OTHER}) From 3f72f8cdfdcfccf6e193e41973087c7f793486ea Mon Sep 17 00:00:00 2001 From: Viktor Charypar Date: Wed, 30 Apr 2014 10:48:43 +0100 Subject: [PATCH 15/15] Update refdb to new API --- redis/hiredis.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/redis/hiredis.c b/redis/hiredis.c index 2a2732a..28f83c9 100644 --- a/redis/hiredis.c +++ b/redis/hiredis.c @@ -364,7 +364,7 @@ int hiredis_refdb_backend__iterator(git_reference_iterator **_iter, struct git_r } int hiredis_refdb_backend__write(git_refdb_backend *_backend, const git_reference *ref, int force, const git_signature *who, - const char *message) // FIXME when rugged gets updated to the latest libgit2 update this to the latest backend API + const char *message, const git_oid *old, const char *old_target) { hiredis_refdb_backend *backend; int error = GIT_OK; @@ -425,7 +425,7 @@ int hiredis_refdb_backend__rename(git_reference **out, git_refdb_backend *_backe return hiredis_refdb_backend__lookup(out, _backend, new_name); } -int hiredis_refdb_backend__del(git_refdb_backend *_backend, const char *ref_name) // FIXME when rugged gets updated to the latest libgit2 update this to the latest backend API +int hiredis_refdb_backend__del(git_refdb_backend *_backend, const char *ref_name, const git_oid *old, const char *old_target) { hiredis_refdb_backend *backend; int error = GIT_OK;