rugged-redis 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,598 @@
1
+ /*
2
+ * This file is free software; you can redistribute it and/or modify
3
+ * it under the terms of the GNU General Public License, version 2,
4
+ * as published by the Free Software Foundation.
5
+ *
6
+ * In addition to the permissions in the GNU General Public License,
7
+ * the authors give you unlimited permission to link the compiled
8
+ * version of this file into combinations with other programs,
9
+ * and to distribute those combinations without any restriction
10
+ * coming from the use of this file. (The General Public License
11
+ * restrictions do apply in other respects; for example, they cover
12
+ * modification of the file, and distribution when not linked into
13
+ * a combined executable.)
14
+ *
15
+ * This file is distributed in the hope that it will be useful, but
16
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
+ * General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License
21
+ * along with this program; see the file COPYING. If not, write to
22
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23
+ * Boston, MA 02110-1301, USA.
24
+ */
25
+
26
+ #include <assert.h>
27
+ #include <string.h>
28
+ #include <git2.h>
29
+ #include <git2/sys/odb_backend.h>
30
+ #include <git2/sys/refdb_backend.h>
31
+ #include <git2/sys/refs.h>
32
+ #include <hiredis/hiredis.h>
33
+
34
+ typedef struct {
35
+ git_odb_backend parent;
36
+
37
+ char *prefix;
38
+ char *repo_path;
39
+ redisContext *db;
40
+ } hiredis_odb_backend;
41
+
42
+ typedef struct {
43
+ git_refdb_backend parent;
44
+
45
+ char *prefix;
46
+ char *repo_path;
47
+ redisContext *db;
48
+ } hiredis_refdb_backend;
49
+
50
+ typedef struct {
51
+ git_reference_iterator parent;
52
+
53
+ size_t current;
54
+ redisReply *keys;
55
+
56
+ hiredis_refdb_backend *backend;
57
+ } hiredis_refdb_iterator;
58
+
59
+ static redisContext *sharedConnection = NULL;
60
+
61
+ /* Odb methods */
62
+
63
+ int hiredis_odb_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid)
64
+ {
65
+ hiredis_odb_backend *backend;
66
+ int error;
67
+ redisReply *reply;
68
+ char *str_id = calloc(GIT_OID_HEXSZ + 1, sizeof(char));
69
+
70
+ assert(len_p && type_p && _backend && oid);
71
+
72
+ backend = (hiredis_odb_backend *) _backend;
73
+ error = GIT_ERROR;
74
+
75
+ git_oid_tostr(str_id, GIT_OID_HEXSZ, oid);
76
+
77
+ reply = redisCommand(backend->db, "HMGET %s:%s:odb:%s %s %s", backend->prefix, backend->repo_path, str_id, "type", "size");
78
+
79
+ if (reply && reply->type == REDIS_REPLY_ARRAY) {
80
+ if (reply->element[0]->type != REDIS_REPLY_NIL &&
81
+ reply->element[0]->type != REDIS_REPLY_NIL) {
82
+ *type_p = (git_otype) atoi(reply->element[0]->str);
83
+ *len_p = (size_t) atoi(reply->element[1]->str);
84
+ error = GIT_OK;
85
+ } else {
86
+ giterr_set_str(GITERR_ODB, "Redis odb storage corrupted");
87
+ error = GIT_ENOTFOUND;
88
+ }
89
+ } else {
90
+ giterr_set_str(GITERR_ODB, "Redis odb storage error");
91
+ error = GIT_ERROR;
92
+ }
93
+
94
+ free(str_id);
95
+ freeReplyObject(reply);
96
+ return error;
97
+ }
98
+
99
+ int hiredis_odb_backend__read(void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid)
100
+ {
101
+ hiredis_odb_backend *backend;
102
+ int error;
103
+ redisReply *reply;
104
+ char *str_id = calloc(GIT_OID_HEXSZ + 1, sizeof(char));
105
+
106
+ assert(data_p && len_p && type_p && _backend && oid);
107
+
108
+ backend = (hiredis_odb_backend *) _backend;
109
+ error = GIT_ERROR;
110
+
111
+ git_oid_tostr(str_id, GIT_OID_HEXSZ, oid);
112
+
113
+ reply = redisCommand(backend->db, "HMGET %s:%s:odb:%s %s %s %s", backend->prefix, backend->repo_path, str_id,
114
+ "type", "size", "data");
115
+
116
+ if (reply && reply->type == REDIS_REPLY_ARRAY) {
117
+ if (reply->element[0]->type != REDIS_REPLY_NIL &&
118
+ reply->element[1]->type != REDIS_REPLY_NIL &&
119
+ reply->element[2]->type != REDIS_REPLY_NIL) {
120
+ *type_p = (git_otype) atoi(reply->element[0]->str);
121
+ *len_p = (size_t) atoi(reply->element[1]->str);
122
+ *data_p = malloc(*len_p);
123
+ if (*data_p == NULL) {
124
+ error = GITERR_NOMEMORY;
125
+ } else {
126
+ memcpy(*data_p, reply->element[2]->str, *len_p);
127
+ error = GIT_OK;
128
+ }
129
+ } else {
130
+ giterr_set_str(GITERR_ODB, "Redis odb couldn't find object");
131
+ error = GIT_ENOTFOUND;
132
+ }
133
+ } else {
134
+ giterr_set_str(GITERR_ODB, "Redis odb storage error");
135
+ error = GIT_ERROR;
136
+ }
137
+
138
+ free(str_id);
139
+ freeReplyObject(reply);
140
+ return error;
141
+ }
142
+
143
+ int hiredis_odb_backend__read_prefix(git_oid *out_oid,
144
+ void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend,
145
+ const git_oid *short_oid, size_t len)
146
+ {
147
+ if (len >= GIT_OID_HEXSZ) {
148
+ /* Just match the full identifier */
149
+ int error = hiredis_odb_backend__read(data_p, len_p, type_p, _backend, short_oid);
150
+ if (error == GIT_OK)
151
+ git_oid_cpy(out_oid, short_oid);
152
+
153
+ return error;
154
+ }
155
+
156
+ /* TODO prefix */
157
+ giterr_set_str(GITERR_ODB, "Redis odb doesn't not implement oid prefix lookup");
158
+ return GITERR_INVALID;
159
+ }
160
+
161
+ int hiredis_odb_backend__exists(git_odb_backend *_backend, const git_oid *oid)
162
+ {
163
+ hiredis_odb_backend *backend;
164
+ int found;
165
+ redisReply *reply;
166
+ char *str_id = calloc(GIT_OID_HEXSZ + 1, sizeof(char));
167
+
168
+ assert(_backend && oid);
169
+
170
+ backend = (hiredis_odb_backend *) _backend;
171
+ found = 0;
172
+
173
+ git_oid_tostr(str_id, GIT_OID_HEXSZ, oid);
174
+
175
+ reply = redisCommand(backend->db, "exists %s:%s:odb:%s", backend->prefix, backend->repo_path, str_id);
176
+ if (reply->type == REDIS_REPLY_INTEGER)
177
+ found = reply->integer;
178
+
179
+ free(str_id);
180
+ freeReplyObject(reply);
181
+ return found;
182
+ }
183
+
184
+ int hiredis_odb_backend__write(git_odb_backend *_backend, const git_oid *oid, const void *data, size_t len, git_otype type)
185
+ {
186
+ hiredis_odb_backend *backend;
187
+ int error;
188
+ redisReply *reply;
189
+ char *str_id = calloc(GIT_OID_HEXSZ + 1, sizeof(char));
190
+
191
+ assert(oid && _backend && data);
192
+
193
+ backend = (hiredis_odb_backend *) _backend;
194
+ error = GIT_ERROR;
195
+
196
+ git_oid_tostr(str_id, GIT_OID_HEXSZ, oid);
197
+
198
+ reply = redisCommand(backend->db, "HMSET %s:%s:odb:%s "
199
+ "type %d "
200
+ "size %d "
201
+ "data %b ", backend->prefix, backend->repo_path, str_id,
202
+ (int) type, len, data, len);
203
+ free(str_id);
204
+
205
+ error = (reply == NULL || reply->type == REDIS_REPLY_ERROR) ? GIT_ERROR : GIT_OK;
206
+
207
+ freeReplyObject(reply);
208
+ return error;
209
+ }
210
+
211
+ void hiredis_odb_backend__free(git_odb_backend *_backend)
212
+ {
213
+ hiredis_odb_backend *backend;
214
+
215
+ assert(_backend);
216
+ backend = (hiredis_odb_backend *) _backend;
217
+
218
+ free(backend->repo_path);
219
+ free(backend->prefix);
220
+
221
+ redisFree(backend->db);
222
+
223
+ free(backend);
224
+ }
225
+
226
+ /* Refdb methods */
227
+
228
+ int hiredis_refdb_backend__exists(int *exists, git_refdb_backend *_backend, const char *ref_name)
229
+ {
230
+ hiredis_refdb_backend *backend;
231
+ int error = GIT_OK;
232
+ redisReply *reply;
233
+
234
+ assert(ref_name && _backend);
235
+
236
+ backend = (hiredis_refdb_backend *) _backend;
237
+
238
+ reply = redisCommand(backend->db, "EXISTS %s:%s:refdb:%s", backend->prefix, backend->repo_path, ref_name);
239
+ if (reply->type == REDIS_REPLY_INTEGER) {
240
+ *exists = reply->integer;
241
+ } else {
242
+ giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error");
243
+ error = GIT_ERROR;
244
+ }
245
+
246
+ freeReplyObject(reply);
247
+ return error;
248
+ }
249
+
250
+ int hiredis_refdb_backend__lookup(git_reference **out, git_refdb_backend *_backend, const char *ref_name)
251
+ {
252
+ hiredis_refdb_backend *backend;
253
+ int error = GIT_OK;
254
+ redisReply *reply;
255
+ git_oid oid;
256
+
257
+ assert(ref_name && _backend);
258
+
259
+ backend = (hiredis_refdb_backend *) _backend;
260
+
261
+ reply = redisCommand(backend->db, "HMGET %s:%s:refdb:%s type target", backend->prefix, backend->repo_path, ref_name);
262
+ if(reply->type == REDIS_REPLY_ARRAY) {
263
+ if (reply->element[0]->type != REDIS_REPLY_NIL && reply->element[1]->type != REDIS_REPLY_NIL) {
264
+ git_ref_t type = (git_ref_t) atoi(reply->element[0]->str);
265
+
266
+ if (type == GIT_REF_OID) {
267
+ git_oid_fromstr(&oid, reply->element[1]->str);
268
+ *out = git_reference__alloc(ref_name, &oid, NULL);
269
+ } else if (type == GIT_REF_SYMBOLIC) {
270
+ *out = git_reference__alloc_symbolic(ref_name, reply->element[1]->str);
271
+ } else {
272
+ giterr_set_str(GITERR_REFERENCE, "Redis refdb storage corrupted (unknown ref type returned)");
273
+ error = GIT_ERROR;
274
+ }
275
+
276
+ } else {
277
+ giterr_set_str(GITERR_REFERENCE, "Redis refdb couldn't find ref");
278
+ error = GIT_ENOTFOUND;
279
+ }
280
+ } else {
281
+ giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error");
282
+ error = GIT_ERROR;
283
+ }
284
+
285
+ freeReplyObject(reply);
286
+ return error;
287
+ }
288
+
289
+ int hiredis_refdb_backend__iterator_next(git_reference **ref, git_reference_iterator *_iter) {
290
+ hiredis_refdb_iterator *iter;
291
+ hiredis_refdb_backend *backend;
292
+ char* ref_name;
293
+ int error;
294
+
295
+ assert(_iter);
296
+ iter = (hiredis_refdb_iterator *) _iter;
297
+
298
+ if(iter->current < iter->keys->elements) {
299
+ ref_name = strstr(iter->keys->element[iter->current++]->str, ":refdb:") + 7;
300
+ error = hiredis_refdb_backend__lookup(ref, (git_refdb_backend *) iter->backend, ref_name);
301
+
302
+ return error;
303
+ } else {
304
+ return GIT_ITEROVER;
305
+ }
306
+ }
307
+
308
+ int hiredis_refdb_backend__iterator_next_name(const char **ref_name, git_reference_iterator *_iter) {
309
+ hiredis_refdb_iterator *iter;
310
+
311
+ assert(_iter);
312
+ iter = (hiredis_refdb_iterator *) _iter;
313
+
314
+ if(iter->current < iter->keys->elements) {
315
+ *ref_name = strdup(strstr(iter->keys->element[iter->current++]->str, ":refdb:") + 7);
316
+
317
+ return GIT_OK;
318
+ } else {
319
+ return GIT_ITEROVER;
320
+ }
321
+ }
322
+
323
+ void hiredis_refdb_backend__iterator_free(git_reference_iterator *_iter) {
324
+ hiredis_refdb_iterator *iter;
325
+
326
+ assert(_iter);
327
+ iter = (hiredis_refdb_iterator *) _iter;
328
+
329
+ freeReplyObject(iter->keys);
330
+
331
+ free(iter);
332
+ }
333
+
334
+ int hiredis_refdb_backend__iterator(git_reference_iterator **_iter, struct git_refdb_backend *_backend, const char *glob)
335
+ {
336
+ hiredis_refdb_backend *backend;
337
+ hiredis_refdb_iterator *iterator;
338
+ int error = GIT_OK;
339
+ redisReply *reply;
340
+
341
+ assert(_backend);
342
+
343
+ backend = (hiredis_refdb_backend *) _backend;
344
+
345
+ reply = redisCommand(backend->db, "KEYS %s:%s:refdb:%s", backend->prefix, backend->repo_path, (glob != NULL ? glob : "refs/*"));
346
+ if(reply->type != REDIS_REPLY_ARRAY) {
347
+ freeReplyObject(reply);
348
+ giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error");
349
+ return GIT_ERROR;
350
+ }
351
+
352
+ iterator = calloc(1, sizeof(hiredis_refdb_iterator));
353
+
354
+ iterator->backend = backend;
355
+ iterator->keys = reply;
356
+
357
+ iterator->parent.next = &hiredis_refdb_backend__iterator_next;
358
+ iterator->parent.next_name = &hiredis_refdb_backend__iterator_next_name;
359
+ iterator->parent.free = &hiredis_refdb_backend__iterator_free;
360
+
361
+ *_iter = (git_reference_iterator *) iterator;
362
+
363
+ return GIT_OK;
364
+ }
365
+
366
+ int hiredis_refdb_backend__write(git_refdb_backend *_backend, const git_reference *ref, int force, const git_signature *who,
367
+ const char *message, const git_oid *old, const char *old_target)
368
+ {
369
+ hiredis_refdb_backend *backend;
370
+ int error = GIT_OK;
371
+ redisReply *reply;
372
+
373
+ const char *name = git_reference_name(ref);
374
+ const git_oid *target;
375
+ const char *symbolic_target;
376
+ char oid_str[GIT_OID_HEXSZ + 1];
377
+
378
+ assert(ref && _backend);
379
+
380
+ backend = (hiredis_refdb_backend *) _backend;
381
+
382
+ target = git_reference_target(ref);
383
+ symbolic_target = git_reference_symbolic_target(ref);
384
+
385
+ /* FIXME handle force correctly */
386
+
387
+ if (target) {
388
+ git_oid_nfmt(oid_str, sizeof(oid_str), target);
389
+ reply = redisCommand(backend->db, "HMSET %s:%s:refdb:%s type %d target %s", backend->prefix, backend->repo_path, name, GIT_REF_OID, oid_str);
390
+ } else {
391
+ symbolic_target = git_reference_symbolic_target(ref);
392
+ reply = redisCommand(backend->db, "HMSET %s:%s:refdb:%s type %d target %s", backend->prefix, backend->repo_path, name, GIT_REF_SYMBOLIC, symbolic_target);
393
+ }
394
+
395
+ if(reply->type == REDIS_REPLY_ERROR) {
396
+ giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error");
397
+ error = GIT_ERROR;
398
+ }
399
+
400
+ freeReplyObject(reply);
401
+ return error;
402
+ }
403
+
404
+ int hiredis_refdb_backend__rename(git_reference **out, git_refdb_backend *_backend, const char *old_name,
405
+ const char *new_name, int force, const git_signature *who, const char *message)
406
+ {
407
+ hiredis_refdb_backend *backend;
408
+ int error = GIT_OK;
409
+ redisReply *reply;
410
+
411
+ assert(old_name && new_name && _backend);
412
+
413
+ backend = (hiredis_refdb_backend *) _backend;
414
+
415
+ reply = redisCommand(backend->db, "RENAME %s:%s:refdb:%s %s:%s:refdb:%s",
416
+ backend->prefix, backend->repo_path, old_name, backend->prefix, backend->repo_path, new_name);
417
+ if(reply->type == REDIS_REPLY_ERROR) {
418
+ freeReplyObject(reply);
419
+
420
+ giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error");
421
+ return GIT_ERROR;
422
+ }
423
+
424
+ freeReplyObject(reply);
425
+ return hiredis_refdb_backend__lookup(out, _backend, new_name);
426
+ }
427
+
428
+ int hiredis_refdb_backend__del(git_refdb_backend *_backend, const char *ref_name, const git_oid *old, const char *old_target)
429
+ {
430
+ hiredis_refdb_backend *backend;
431
+ int error = GIT_OK;
432
+ redisReply *reply;
433
+
434
+ assert(ref_name && _backend);
435
+
436
+ backend = (hiredis_refdb_backend *) _backend;
437
+
438
+ reply = redisCommand(backend->db, "DEL %s:%s:refdb:%s", backend->prefix, backend->repo_path, ref_name);
439
+ if(reply->type == REDIS_REPLY_ERROR) {
440
+ giterr_set_str(GITERR_REFERENCE, "Redis refdb storage error");
441
+ error = GIT_ERROR;
442
+ }
443
+
444
+ freeReplyObject(reply);
445
+ return error;
446
+ }
447
+
448
+ void hiredis_refdb_backend__free(git_refdb_backend *_backend)
449
+ {
450
+ hiredis_refdb_backend *backend;
451
+
452
+ assert(_backend);
453
+ backend = (hiredis_refdb_backend *) _backend;
454
+
455
+ free(backend->repo_path);
456
+ free(backend->prefix);
457
+
458
+ redisFree(backend->db);
459
+
460
+ free(backend);
461
+ }
462
+
463
+ /* reflog methods */
464
+
465
+ int hiredis_refdb_backend__has_log(git_refdb_backend *_backend, const char *refname)
466
+ {
467
+ return 0;
468
+ }
469
+
470
+ int hiredis_refdb_backend__ensure_log(git_refdb_backend *_backend, const char *refname)
471
+ {
472
+ return GIT_ERROR;
473
+ }
474
+
475
+ int hiredis_refdb_backend__reflog_read(git_reflog **out, git_refdb_backend *_backend, const char *name)
476
+ {
477
+ return GIT_ERROR;
478
+ }
479
+
480
+ int hiredis_refdb_backend__reflog_write(git_refdb_backend *_backend, git_reflog *reflog)
481
+ {
482
+ return GIT_ERROR;
483
+ }
484
+
485
+ int hiredis_refdb_backend__reflog_rename(git_refdb_backend *_backend, const char *old_name, const char *new_name)
486
+ {
487
+ return GIT_ERROR;
488
+ }
489
+
490
+ int hiredis_refdb_backend__reflog_delete(git_refdb_backend *_backend, const char *name)
491
+ {
492
+ return GIT_ERROR;
493
+ }
494
+
495
+ /* Constructors */
496
+
497
+ int git_odb_backend_hiredis(git_odb_backend **backend_out, const char* prefix, const char* path, const char *host, int port, char* password)
498
+ {
499
+ hiredis_odb_backend *backend;
500
+ redisReply *reply;
501
+
502
+ backend = calloc(1, sizeof (hiredis_odb_backend));
503
+ if (backend == NULL)
504
+ return GITERR_NOMEMORY;
505
+
506
+ if (sharedConnection == NULL) {
507
+ sharedConnection = redisConnect(host, port);
508
+ if (sharedConnection->err) {
509
+ free(backend);
510
+ giterr_set_str(GITERR_REFERENCE, "Redis odb storage couldn't connect to redis server");
511
+ return GIT_ERROR;
512
+ }
513
+
514
+ if(password != NULL) {
515
+ reply = redisCommand(sharedConnection, "AUTH %s", password);
516
+ if (reply->type == REDIS_REPLY_ERROR) {
517
+ giterr_set_str(GITERR_REFERENCE, "Redis odb storage authentication with redis server failed");
518
+ return GIT_ERROR;
519
+ }
520
+ freeReplyObject(reply);
521
+ }
522
+ }
523
+
524
+ backend->db = sharedConnection;
525
+
526
+ backend->prefix = strdup(prefix);
527
+ backend->repo_path = strdup(path);
528
+
529
+ backend->parent.version = 1;
530
+
531
+ backend->parent.read = &hiredis_odb_backend__read;
532
+ backend->parent.write = &hiredis_odb_backend__write;
533
+ backend->parent.read_prefix = &hiredis_odb_backend__read_prefix;
534
+ backend->parent.read_header = &hiredis_odb_backend__read_header;
535
+ backend->parent.exists = &hiredis_odb_backend__exists;
536
+ backend->parent.free = &hiredis_odb_backend__free;
537
+
538
+ backend->parent.writestream = NULL;
539
+ backend->parent.foreach = NULL;
540
+
541
+ *backend_out = (git_odb_backend *) backend;
542
+
543
+ return GIT_OK;
544
+ }
545
+
546
+ int git_refdb_backend_hiredis(git_refdb_backend **backend_out, const char* prefix, const char* path, const char *host, int port, char* password)
547
+ {
548
+ hiredis_refdb_backend *backend;
549
+ redisReply *reply;
550
+
551
+ backend = calloc(1, sizeof(hiredis_refdb_backend));
552
+ if (backend == NULL)
553
+ return GITERR_NOMEMORY;
554
+
555
+ if (sharedConnection == NULL) {
556
+ sharedConnection = redisConnect(host, port);
557
+ if (sharedConnection->err) {
558
+ free(backend);
559
+ giterr_set_str(GITERR_REFERENCE, "Redis refdb storage couldn't connect to redis server");
560
+ return GIT_ERROR;
561
+ }
562
+
563
+ if(password != NULL) {
564
+ reply = redisCommand(sharedConnection, "AUTH %s", password);
565
+ if (reply->type == REDIS_REPLY_ERROR) {
566
+ giterr_set_str(GITERR_REFERENCE, "Redis refdb storage authentication with redis server failed");
567
+ return GIT_ERROR;
568
+ }
569
+ freeReplyObject(reply);
570
+ }
571
+ }
572
+
573
+ backend->db = sharedConnection;
574
+
575
+ backend->prefix = strdup(prefix);
576
+ backend->repo_path = strdup(path);
577
+
578
+ backend->parent.exists = &hiredis_refdb_backend__exists;
579
+ backend->parent.lookup = &hiredis_refdb_backend__lookup;
580
+ backend->parent.iterator = &hiredis_refdb_backend__iterator;
581
+ backend->parent.write = &hiredis_refdb_backend__write;
582
+ backend->parent.del = &hiredis_refdb_backend__del;
583
+ backend->parent.rename = &hiredis_refdb_backend__rename;
584
+ backend->parent.compress = NULL;
585
+ backend->parent.free = &hiredis_refdb_backend__free;
586
+
587
+ backend->parent.has_log = &hiredis_refdb_backend__has_log;
588
+ backend->parent.ensure_log = &hiredis_refdb_backend__ensure_log;
589
+ backend->parent.reflog_read = &hiredis_refdb_backend__reflog_read;
590
+ backend->parent.reflog_write = &hiredis_refdb_backend__reflog_write;
591
+ backend->parent.reflog_rename = &hiredis_refdb_backend__reflog_rename;
592
+ backend->parent.reflog_delete = &hiredis_refdb_backend__reflog_delete;
593
+
594
+ *backend_out = (git_refdb_backend *) backend;
595
+
596
+ return GIT_OK;
597
+ }
598
+