rugged-mysql 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +22 -0
- data/LICENSE +22 -0
- data/README.md +40 -0
- data/Rakefile +8 -0
- data/ext/rugged/mysql/extconf.rb +24 -0
- data/ext/rugged/mysql/mysql_odb_backend.c +478 -0
- data/ext/rugged/mysql/mysql_refdb_backend.c +735 -0
- data/ext/rugged/mysql/rugged_mysql.c +13 -0
- data/ext/rugged/mysql/rugged_mysql.h +4 -0
- data/ext/rugged/mysql/rugged_mysql_backend.c +161 -0
- data/lib/rugged-mysql.rb +1 -0
- data/lib/rugged/mysql.rb +9 -0
- data/lib/rugged/mysql/version.rb +5 -0
- data/rugged-mysql.gemspec +28 -0
- metadata +118 -0
@@ -0,0 +1,735 @@
|
|
1
|
+
#include <assert.h>
|
2
|
+
#include <string.h>
|
3
|
+
|
4
|
+
#include <git2.h>
|
5
|
+
#include <git2/sys/refdb_backend.h>
|
6
|
+
#include <git2/sys/refs.h>
|
7
|
+
#include <git2/sys/reflog.h>
|
8
|
+
#include <refs.h>
|
9
|
+
#include <iterator.h>
|
10
|
+
#include <refdb.h>
|
11
|
+
#include <fnmatch.h>
|
12
|
+
#include <pool.h>
|
13
|
+
#include <buffer.h>
|
14
|
+
#include <sqlite3.h>
|
15
|
+
|
16
|
+
#include <mysql.h>
|
17
|
+
|
18
|
+
#define GIT2_REFDB_TABLE_NAME "git2_refdb"
|
19
|
+
#define GIT_SYMREF "ref: "
|
20
|
+
#define GIT2_STORAGE_ENGINE "InnoDB"
|
21
|
+
|
22
|
+
typedef struct mysql_refdb_backend {
|
23
|
+
git_refdb_backend parent;
|
24
|
+
MYSQL *db;
|
25
|
+
MYSQL_STMT *st_read;
|
26
|
+
MYSQL_STMT *st_read_all;
|
27
|
+
MYSQL_STMT *st_write;
|
28
|
+
MYSQL_STMT *st_delete;
|
29
|
+
} mysql_refdb_backend;
|
30
|
+
|
31
|
+
static int ref_error_notfound(const char *name)
|
32
|
+
{
|
33
|
+
giterr_set(GITERR_REFERENCE, "Reference not found: %s", name);
|
34
|
+
return GIT_ENOTFOUND;
|
35
|
+
}
|
36
|
+
|
37
|
+
static const char *parse_symbolic(git_buf * ref_content)
|
38
|
+
{
|
39
|
+
const unsigned int header_len = (unsigned int)strlen(GIT_SYMREF);
|
40
|
+
const char *refname_start;
|
41
|
+
|
42
|
+
refname_start = (const char *)git_buf_cstr(ref_content);
|
43
|
+
|
44
|
+
if (git_buf_len(ref_content) < header_len + 1) {
|
45
|
+
giterr_set(GITERR_REFERENCE, "Corrupted reference");
|
46
|
+
return NULL;
|
47
|
+
}
|
48
|
+
|
49
|
+
/*
|
50
|
+
* Assume we have already checked for the header
|
51
|
+
* before calling this function
|
52
|
+
*/
|
53
|
+
refname_start += header_len;
|
54
|
+
|
55
|
+
return refname_start;
|
56
|
+
}
|
57
|
+
|
58
|
+
static int parse_oid(git_oid * oid, const char *filename, git_buf * ref_content)
|
59
|
+
{
|
60
|
+
const char *str = git_buf_cstr(ref_content);
|
61
|
+
|
62
|
+
if (git_buf_len(ref_content) < GIT_OID_HEXSZ) {
|
63
|
+
goto corrupted;
|
64
|
+
}
|
65
|
+
|
66
|
+
/* we need to get 40 OID characters from the file */
|
67
|
+
if (git_oid_fromstr(oid, str) < 0) {
|
68
|
+
goto corrupted;
|
69
|
+
}
|
70
|
+
|
71
|
+
/* If the file is longer than 40 chars, the 41st must be a space */
|
72
|
+
str += GIT_OID_HEXSZ;
|
73
|
+
if (*str == '\0' || git__isspace(*str)) {
|
74
|
+
return 0;
|
75
|
+
}
|
76
|
+
|
77
|
+
corrupted:
|
78
|
+
giterr_set(GITERR_REFERENCE, "Corrupted reference");
|
79
|
+
return -1;
|
80
|
+
}
|
81
|
+
|
82
|
+
static int
|
83
|
+
mysql_refdb_backend__exists(int *exists,
|
84
|
+
git_refdb_backend * _backend, const char *ref_name)
|
85
|
+
{
|
86
|
+
mysql_refdb_backend *backend = (mysql_refdb_backend *) _backend;
|
87
|
+
MYSQL_BIND bind_buffers[1];
|
88
|
+
|
89
|
+
assert(backend);
|
90
|
+
memset(bind_buffers, 0, sizeof(bind_buffers));
|
91
|
+
|
92
|
+
*exists = 0;
|
93
|
+
|
94
|
+
bind_buffers[0].buffer = (void *)ref_name;
|
95
|
+
bind_buffers[0].buffer_type = MYSQL_TYPE_STRING;
|
96
|
+
if (mysql_stmt_bind_param(backend->st_read, bind_buffers) != 0) {
|
97
|
+
return 0;
|
98
|
+
}
|
99
|
+
if (mysql_stmt_execute(backend->st_read) != 0) {
|
100
|
+
return 0;
|
101
|
+
}
|
102
|
+
|
103
|
+
if (mysql_stmt_store_result(backend->st_read) != 0) {
|
104
|
+
return 0;
|
105
|
+
}
|
106
|
+
|
107
|
+
if (mysql_stmt_num_rows(backend->st_read) == 1) {
|
108
|
+
*exists = 1;
|
109
|
+
}
|
110
|
+
|
111
|
+
mysql_stmt_reset(backend->st_read);
|
112
|
+
return 0;
|
113
|
+
}
|
114
|
+
|
115
|
+
static int
|
116
|
+
loose_lookup(git_reference ** out,
|
117
|
+
mysql_refdb_backend * backend, const char *ref_name)
|
118
|
+
{
|
119
|
+
git_buf ref_buf = GIT_BUF_INIT;
|
120
|
+
MYSQL_BIND bind_buffers[1];
|
121
|
+
MYSQL_ROW row;
|
122
|
+
int error = GIT_ERROR;
|
123
|
+
|
124
|
+
assert(backend);
|
125
|
+
|
126
|
+
bind_buffers[0].buffer = (void *)ref_name;
|
127
|
+
bind_buffers[0].buffer_type = MYSQL_TYPE_STRING;
|
128
|
+
|
129
|
+
if (mysql_stmt_bind_param(backend->st_read, bind_buffers) != 0) {
|
130
|
+
return ref_error_notfound(ref_name);
|
131
|
+
}
|
132
|
+
|
133
|
+
if (mysql_stmt_execute(backend->st_read) != 0) {
|
134
|
+
return ref_error_notfound(ref_name);
|
135
|
+
}
|
136
|
+
if (mysql_stmt_store_result(backend->st_read) != 0) {
|
137
|
+
return ref_error_notfound(ref_name);
|
138
|
+
}
|
139
|
+
if ((row = mysql_fetch_row(backend->st_read))) {
|
140
|
+
char *raw_ref = row[0];
|
141
|
+
|
142
|
+
git_buf_set(&ref_buf, raw_ref, strlen(raw_ref));
|
143
|
+
|
144
|
+
if (git__prefixcmp(git_buf_cstr(&ref_buf), GIT_SYMREF) == 0) {
|
145
|
+
const char *target;
|
146
|
+
|
147
|
+
git_buf_rtrim(&ref_buf);
|
148
|
+
|
149
|
+
if (!(target = parse_symbolic(&ref_buf))) {
|
150
|
+
error = -1;
|
151
|
+
} else if (out != NULL) {
|
152
|
+
*out =
|
153
|
+
git_reference__alloc_symbolic(ref_name,
|
154
|
+
target);
|
155
|
+
}
|
156
|
+
} else {
|
157
|
+
git_oid oid;
|
158
|
+
|
159
|
+
if (!(error = parse_oid(&oid, ref_name, &ref_buf))
|
160
|
+
&& out != NULL)
|
161
|
+
*out =
|
162
|
+
git_reference__alloc(ref_name, &oid, NULL);
|
163
|
+
}
|
164
|
+
|
165
|
+
}
|
166
|
+
|
167
|
+
git_buf_free(&ref_buf);
|
168
|
+
mysql_stmt_reset(backend->st_read);
|
169
|
+
|
170
|
+
return error;
|
171
|
+
}
|
172
|
+
|
173
|
+
static int
|
174
|
+
mysql_refdb_backend__lookup(git_reference ** out,
|
175
|
+
git_refdb_backend * _backend, const char *ref_name)
|
176
|
+
{
|
177
|
+
mysql_refdb_backend *backend = (mysql_refdb_backend *) _backend;
|
178
|
+
int error;
|
179
|
+
|
180
|
+
assert(backend);
|
181
|
+
|
182
|
+
if (!(error = loose_lookup(out, backend, ref_name))) {
|
183
|
+
return 0;
|
184
|
+
}
|
185
|
+
|
186
|
+
return error;
|
187
|
+
}
|
188
|
+
|
189
|
+
typedef struct {
|
190
|
+
git_reference_iterator parent;
|
191
|
+
|
192
|
+
char *glob;
|
193
|
+
|
194
|
+
git_pool pool;
|
195
|
+
git_vector loose;
|
196
|
+
|
197
|
+
size_t loose_pos;
|
198
|
+
} mysql_refdb_iter;
|
199
|
+
|
200
|
+
static void mysql_refdb_backend__iterator_free(git_reference_iterator * _iter)
|
201
|
+
{
|
202
|
+
mysql_refdb_iter *iter = (mysql_refdb_iter *) _iter;
|
203
|
+
|
204
|
+
git_vector_free(&iter->loose);
|
205
|
+
git_pool_clear(&iter->pool);
|
206
|
+
git__free(iter);
|
207
|
+
}
|
208
|
+
|
209
|
+
static int
|
210
|
+
iter_load_loose_paths(mysql_refdb_backend * backend, mysql_refdb_iter * iter)
|
211
|
+
{
|
212
|
+
int error = GIT_ERROR;
|
213
|
+
MYSQL_ROW row;
|
214
|
+
|
215
|
+
if (mysql_stmt_execute(backend->st_read_all) != 0) {
|
216
|
+
return GIT_ERROR;
|
217
|
+
}
|
218
|
+
if (mysql_stmt_store_result(backend->st_read_all) != 0) {
|
219
|
+
return GIT_ERROR;
|
220
|
+
}
|
221
|
+
|
222
|
+
while ((row = mysql_fetch_row(backend->st_read_all))) {
|
223
|
+
char *ref_dup;
|
224
|
+
char *ref_name = row[0];
|
225
|
+
|
226
|
+
if (git__suffixcmp(ref_name, ".lock") == 0 ||
|
227
|
+
(iter->glob && p_fnmatch(iter->glob, ref_name, 0) != 0))
|
228
|
+
continue;
|
229
|
+
|
230
|
+
ref_dup = git_pool_strdup(&iter->pool, ref_name);
|
231
|
+
if (!ref_dup)
|
232
|
+
error = -1;
|
233
|
+
else
|
234
|
+
error = git_vector_insert(&iter->loose, ref_dup);
|
235
|
+
}
|
236
|
+
|
237
|
+
mysql_stmt_reset(backend->st_read_all);
|
238
|
+
|
239
|
+
return error;
|
240
|
+
}
|
241
|
+
|
242
|
+
static int
|
243
|
+
mysql_refdb_backend__iterator_next(git_reference ** out,
|
244
|
+
git_reference_iterator * _iter)
|
245
|
+
{
|
246
|
+
int error = GIT_ITEROVER;
|
247
|
+
mysql_refdb_iter *iter = (mysql_refdb_iter *) _iter;
|
248
|
+
mysql_refdb_backend *backend =
|
249
|
+
(mysql_refdb_backend *) iter->parent.db->backend;
|
250
|
+
|
251
|
+
while (iter->loose_pos < iter->loose.length) {
|
252
|
+
const char *path =
|
253
|
+
git_vector_get(&iter->loose, iter->loose_pos++);
|
254
|
+
|
255
|
+
if (loose_lookup(out, backend, path) == 0)
|
256
|
+
return 0;
|
257
|
+
|
258
|
+
giterr_clear();
|
259
|
+
}
|
260
|
+
|
261
|
+
return error;
|
262
|
+
}
|
263
|
+
|
264
|
+
static int
|
265
|
+
mysql_refdb_backend__iterator_next_name(const char **out,
|
266
|
+
git_reference_iterator * _iter)
|
267
|
+
{
|
268
|
+
int error = GIT_ITEROVER;
|
269
|
+
mysql_refdb_iter *iter = (mysql_refdb_iter *) _iter;
|
270
|
+
mysql_refdb_backend *backend =
|
271
|
+
(mysql_refdb_backend *) iter->parent.db->backend;
|
272
|
+
|
273
|
+
while (iter->loose_pos < iter->loose.length) {
|
274
|
+
const char *path =
|
275
|
+
git_vector_get(&iter->loose, iter->loose_pos++);
|
276
|
+
|
277
|
+
if (loose_lookup(NULL, backend, path) == 0) {
|
278
|
+
*out = path;
|
279
|
+
return 0;
|
280
|
+
}
|
281
|
+
|
282
|
+
giterr_clear();
|
283
|
+
}
|
284
|
+
|
285
|
+
return error;
|
286
|
+
}
|
287
|
+
|
288
|
+
static int
|
289
|
+
mysql_refdb_backend__iterator(git_reference_iterator ** out,
|
290
|
+
git_refdb_backend * _backend, const char *glob)
|
291
|
+
{
|
292
|
+
mysql_refdb_iter *iter;
|
293
|
+
mysql_refdb_backend *backend = (mysql_refdb_backend *) _backend;
|
294
|
+
|
295
|
+
assert(backend);
|
296
|
+
|
297
|
+
iter = git__calloc(1, sizeof(mysql_refdb_iter));
|
298
|
+
GITERR_CHECK_ALLOC(iter);
|
299
|
+
|
300
|
+
if (git_pool_init(&iter->pool, 1, 0) < 0 ||
|
301
|
+
git_vector_init(&iter->loose, 8, NULL) < 0)
|
302
|
+
goto fail;
|
303
|
+
|
304
|
+
if (glob != NULL &&
|
305
|
+
(iter->glob = git_pool_strdup(&iter->pool, glob)) == NULL)
|
306
|
+
goto fail;
|
307
|
+
|
308
|
+
iter->parent.next = mysql_refdb_backend__iterator_next;
|
309
|
+
iter->parent.next_name = mysql_refdb_backend__iterator_next_name;
|
310
|
+
iter->parent.free = mysql_refdb_backend__iterator_free;
|
311
|
+
|
312
|
+
if (iter_load_loose_paths(backend, iter) < 0)
|
313
|
+
goto fail;
|
314
|
+
|
315
|
+
*out = (git_reference_iterator *) iter;
|
316
|
+
return 0;
|
317
|
+
|
318
|
+
fail:
|
319
|
+
mysql_refdb_backend__iterator_free((git_reference_iterator *) iter);
|
320
|
+
return -1;
|
321
|
+
}
|
322
|
+
|
323
|
+
static int
|
324
|
+
reference_path_available(mysql_refdb_backend * backend,
|
325
|
+
const char *new_ref, const char *old_ref, int force)
|
326
|
+
{
|
327
|
+
if (!force) {
|
328
|
+
int exists;
|
329
|
+
|
330
|
+
if (mysql_refdb_backend__exists
|
331
|
+
(&exists, (git_refdb_backend *) backend, new_ref) < 0)
|
332
|
+
return -1;
|
333
|
+
|
334
|
+
if (exists) {
|
335
|
+
giterr_set(GITERR_REFERENCE,
|
336
|
+
"Failed to write reference '%s': a reference with "
|
337
|
+
"that name already exists.", new_ref);
|
338
|
+
return GIT_EEXISTS;
|
339
|
+
}
|
340
|
+
}
|
341
|
+
|
342
|
+
return 0;
|
343
|
+
}
|
344
|
+
|
345
|
+
static int
|
346
|
+
mysql_refdb_backend__write(git_refdb_backend * _backend,
|
347
|
+
const git_reference * ref,
|
348
|
+
int force,
|
349
|
+
const git_signature * who, const char *message)
|
350
|
+
{
|
351
|
+
mysql_refdb_backend *backend = (mysql_refdb_backend *) _backend;
|
352
|
+
int error;
|
353
|
+
MYSQL_BIND bind_buffers[2];
|
354
|
+
|
355
|
+
assert(backend);
|
356
|
+
|
357
|
+
error = reference_path_available(backend, ref->name, NULL, force);
|
358
|
+
if (error < 0) {
|
359
|
+
return error;
|
360
|
+
}
|
361
|
+
|
362
|
+
error = GIT_ERROR;
|
363
|
+
|
364
|
+
bind_buffers[0].buffer = (void *)ref->name;
|
365
|
+
bind_buffers[0].buffer_type = MYSQL_TYPE_STRING;
|
366
|
+
if (ref->type == GIT_REF_OID) {
|
367
|
+
char oid[GIT_OID_HEXSZ + 1];
|
368
|
+
git_oid_nfmt(oid, sizeof(oid), &ref->target.oid);
|
369
|
+
|
370
|
+
bind_buffers[1].buffer = (void *)oid;
|
371
|
+
bind_buffers[1].buffer_type = MYSQL_TYPE_STRING;
|
372
|
+
|
373
|
+
} else if (ref->type == GIT_REF_SYMBOLIC) {
|
374
|
+
char *symbolic_ref =
|
375
|
+
malloc(strlen(GIT_SYMREF) + strlen(ref->target.symbolic) +
|
376
|
+
1);
|
377
|
+
|
378
|
+
strcpy(symbolic_ref, GIT_SYMREF);
|
379
|
+
strcat(symbolic_ref, ref->target.symbolic);
|
380
|
+
|
381
|
+
bind_buffers[1].buffer = (void *)symbolic_ref;
|
382
|
+
bind_buffers[1].buffer_type = MYSQL_TYPE_STRING;
|
383
|
+
}
|
384
|
+
|
385
|
+
if (mysql_stmt_bind_param(backend->st_write, bind_buffers) != 0) {
|
386
|
+
return GIT_ERROR;
|
387
|
+
}
|
388
|
+
|
389
|
+
if (mysql_stmt_execute(backend->st_write) != 0) {
|
390
|
+
giterr_set(GITERR_ODB,
|
391
|
+
"Error writing reference to Sqlite RefDB backend");
|
392
|
+
return GIT_ERROR;
|
393
|
+
}
|
394
|
+
|
395
|
+
mysql_stmt_reset(backend->st_write);
|
396
|
+
|
397
|
+
return GIT_OK;
|
398
|
+
}
|
399
|
+
|
400
|
+
static int
|
401
|
+
mysql_refdb_backend__delete(git_refdb_backend * _backend, const char *name)
|
402
|
+
{
|
403
|
+
mysql_refdb_backend *backend = (mysql_refdb_backend *) _backend;
|
404
|
+
int error;
|
405
|
+
MYSQL_BIND bind_buffers[1];
|
406
|
+
|
407
|
+
assert(backend && name);
|
408
|
+
memset(bind_buffers, 0, sizeof(bind_buffers));
|
409
|
+
|
410
|
+
bind_buffers[0].buffer = (void *)name;
|
411
|
+
bind_buffers[0].buffer_type = MYSQL_TYPE_STRING;
|
412
|
+
|
413
|
+
if (mysql_stmt_bind_param(backend->st_delete, bind_buffers) != 0) {
|
414
|
+
return GIT_ERROR;
|
415
|
+
}
|
416
|
+
if (mysql_stmt_execute(backend->st_delete) != 0) {
|
417
|
+
return GIT_ERROR;
|
418
|
+
}
|
419
|
+
|
420
|
+
return GIT_OK;
|
421
|
+
|
422
|
+
}
|
423
|
+
|
424
|
+
static int
|
425
|
+
mysql_refdb_backend__rename(git_reference ** out,
|
426
|
+
git_refdb_backend * _backend,
|
427
|
+
const char *old_name,
|
428
|
+
const char *new_name,
|
429
|
+
int force,
|
430
|
+
const git_signature * who, const char *message)
|
431
|
+
{
|
432
|
+
mysql_refdb_backend *backend = (mysql_refdb_backend *) _backend;
|
433
|
+
git_reference *old, *new;
|
434
|
+
int error;
|
435
|
+
|
436
|
+
assert(backend);
|
437
|
+
|
438
|
+
if ((error =
|
439
|
+
reference_path_available(backend, new_name, old_name, force)) < 0
|
440
|
+
|| (error =
|
441
|
+
mysql_refdb_backend__lookup(&old, _backend, old_name)) < 0)
|
442
|
+
return error;
|
443
|
+
|
444
|
+
if ((error = mysql_refdb_backend__delete(_backend, old_name)) < 0) {
|
445
|
+
git_reference_free(old);
|
446
|
+
return error;
|
447
|
+
}
|
448
|
+
|
449
|
+
new = git_reference__set_name(old, new_name);
|
450
|
+
if (!new) {
|
451
|
+
git_reference_free(old);
|
452
|
+
return -1;
|
453
|
+
}
|
454
|
+
|
455
|
+
if ((error =
|
456
|
+
mysql_refdb_backend__write(_backend, new, force, who,
|
457
|
+
message)) > 0) {
|
458
|
+
git_reference_free(new);
|
459
|
+
return error;
|
460
|
+
}
|
461
|
+
|
462
|
+
*out = new;
|
463
|
+
return GIT_OK;
|
464
|
+
}
|
465
|
+
|
466
|
+
static int mysql_refdb_backend__compress(git_refdb_backend * _backend)
|
467
|
+
{
|
468
|
+
return 0;
|
469
|
+
}
|
470
|
+
|
471
|
+
static int
|
472
|
+
mysql_refdb_backend__has_log(git_refdb_backend * _backend, const char *name)
|
473
|
+
{
|
474
|
+
return -1;
|
475
|
+
}
|
476
|
+
|
477
|
+
static int
|
478
|
+
mysql_refdb_backend__ensure_log(git_refdb_backend * _backend, const char *name)
|
479
|
+
{
|
480
|
+
return 0;
|
481
|
+
}
|
482
|
+
|
483
|
+
static void mysql_refdb_backend__free(git_refdb_backend * _backend)
|
484
|
+
{
|
485
|
+
mysql_refdb_backend *backend = (mysql_refdb_backend *) _backend;
|
486
|
+
|
487
|
+
assert(backend);
|
488
|
+
|
489
|
+
if (backend->st_read) {
|
490
|
+
mysql_stmt_close(backend->st_read);
|
491
|
+
}
|
492
|
+
if (backend->st_read_all) {
|
493
|
+
mysql_stmt_close(backend->st_read_all);
|
494
|
+
}
|
495
|
+
if (backend->st_write) {
|
496
|
+
mysql_stmt_close(backend->st_write);
|
497
|
+
}
|
498
|
+
if (backend->st_delete) {
|
499
|
+
mysql_stmt_close(backend->st_delete);
|
500
|
+
}
|
501
|
+
mysql_close(backend->db);
|
502
|
+
|
503
|
+
free(backend);
|
504
|
+
}
|
505
|
+
|
506
|
+
static int
|
507
|
+
mysql_refdb_backend__reflog_read(git_reflog ** out,
|
508
|
+
git_refdb_backend * _backend, const char *name)
|
509
|
+
{
|
510
|
+
return 0;
|
511
|
+
}
|
512
|
+
|
513
|
+
static int
|
514
|
+
mysql_refdb_backend__reflog_write(git_refdb_backend * _backend,
|
515
|
+
git_reflog * reflog)
|
516
|
+
{
|
517
|
+
return 0;
|
518
|
+
}
|
519
|
+
|
520
|
+
static int
|
521
|
+
mysql_refdb_backend__reflog_rename(git_refdb_backend * _backend,
|
522
|
+
const char *old_name, const char *new_name)
|
523
|
+
{
|
524
|
+
return 0;
|
525
|
+
}
|
526
|
+
|
527
|
+
static int
|
528
|
+
mysql_refdb_backend__reflog_delete(git_refdb_backend * _backend,
|
529
|
+
const char *name)
|
530
|
+
{
|
531
|
+
return 0;
|
532
|
+
}
|
533
|
+
|
534
|
+
static int create_table(MYSQL * db)
|
535
|
+
{
|
536
|
+
static const char *sql_creat =
|
537
|
+
"CREATE TABLE '" GIT2_REFDB_TABLE_NAME "' ("
|
538
|
+
"'refname' TEXT PRIMARY KEY NOT NULL,"
|
539
|
+
"'ref' TEXT NOT NULL"
|
540
|
+
") ENGINE=" GIT2_STORAGE_ENGINE
|
541
|
+
" DEFAULT CHARSET=utf8 COLLATE=utf8_bin;";
|
542
|
+
|
543
|
+
if (mysql_real_query(db, sql_creat, strlen(sql_creat)) != 0) {
|
544
|
+
giterr_set(GITERR_REFERENCE,
|
545
|
+
"Error creating table for MySql RefDB backend");
|
546
|
+
return GIT_ERROR;
|
547
|
+
}
|
548
|
+
|
549
|
+
return GIT_OK;
|
550
|
+
}
|
551
|
+
|
552
|
+
static int init_db(MYSQL * db)
|
553
|
+
{
|
554
|
+
static const char *sql_check =
|
555
|
+
"SHOW TABLES LIKE '" GIT2_REFDB_TABLE_NAME "';";
|
556
|
+
|
557
|
+
MYSQL_RES *res;
|
558
|
+
int error;
|
559
|
+
my_ulonglong num_rows;
|
560
|
+
|
561
|
+
if (mysql_real_query(db, sql_check, strlen(sql_check)) != 0) {
|
562
|
+
return GIT_ERROR;
|
563
|
+
}
|
564
|
+
|
565
|
+
res = mysql_store_result(db);
|
566
|
+
if (res == NULL) {
|
567
|
+
return GIT_ERROR;
|
568
|
+
}
|
569
|
+
|
570
|
+
num_rows = mysql_num_rows(res);
|
571
|
+
if (num_rows == 0) {
|
572
|
+
error = create_table(db);
|
573
|
+
} else if (num_rows > 0) {
|
574
|
+
error = GIT_OK;
|
575
|
+
} else {
|
576
|
+
error = GIT_ERROR;
|
577
|
+
}
|
578
|
+
|
579
|
+
mysql_free_result(res);
|
580
|
+
|
581
|
+
return error;
|
582
|
+
}
|
583
|
+
|
584
|
+
static int init_statements(mysql_refdb_backend * backend)
|
585
|
+
{
|
586
|
+
my_bool truth = 1;
|
587
|
+
static const char *sql_read =
|
588
|
+
"SELECT ref FROM '" GIT2_REFDB_TABLE_NAME "' WHERE refname = ?;";
|
589
|
+
|
590
|
+
static const char *sql_read_all =
|
591
|
+
"SELECT refname FROM '" GIT2_REFDB_TABLE_NAME "';";
|
592
|
+
|
593
|
+
static const char *sql_write =
|
594
|
+
"INSERT OR IGNORE INTO '" GIT2_REFDB_TABLE_NAME "' VALUES (?, ?);";
|
595
|
+
|
596
|
+
static const char *sql_delete =
|
597
|
+
"DELETE FROM '" GIT2_REFDB_TABLE_NAME "' WHERE refname = ?;";
|
598
|
+
|
599
|
+
backend->st_read = mysql_stmt_init(backend->db);
|
600
|
+
if (backend->st_read == NULL) {
|
601
|
+
giterr_set(GITERR_REFERENCE,
|
602
|
+
"Error creating prepared statement for MySql RefDB backend");
|
603
|
+
return GIT_ERROR;
|
604
|
+
}
|
605
|
+
if (mysql_stmt_attr_set
|
606
|
+
(backend->st_read, STMT_ATTR_UPDATE_MAX_LENGTH, &truth) != 0) {
|
607
|
+
giterr_set(GITERR_REFERENCE,
|
608
|
+
"Error creating prepared statement for MySql RefDB backend");
|
609
|
+
return GIT_ERROR;
|
610
|
+
}
|
611
|
+
if (mysql_stmt_prepare(backend->st_read, sql_read, strlen(sql_read)) !=
|
612
|
+
0) {
|
613
|
+
giterr_set(GITERR_REFERENCE,
|
614
|
+
"Error creating prepared statement for MySql RefDB backend");
|
615
|
+
return GIT_ERROR;
|
616
|
+
}
|
617
|
+
|
618
|
+
backend->st_read_all = mysql_stmt_init(backend->db);
|
619
|
+
if (backend->st_read_all == NULL) {
|
620
|
+
giterr_set(GITERR_REFERENCE,
|
621
|
+
"Error creating prepared statement for MySql RefDB backend");
|
622
|
+
return GIT_ERROR;
|
623
|
+
}
|
624
|
+
if (mysql_stmt_attr_set
|
625
|
+
(backend->st_read_all, STMT_ATTR_UPDATE_MAX_LENGTH, &truth) != 0) {
|
626
|
+
giterr_set(GITERR_REFERENCE,
|
627
|
+
"Error creating prepared statement for MySql RefDB backend");
|
628
|
+
return GIT_ERROR;
|
629
|
+
}
|
630
|
+
if (mysql_stmt_prepare
|
631
|
+
(backend->st_read_all, sql_read_all, strlen(sql_read_all)) != 0) {
|
632
|
+
giterr_set(GITERR_REFERENCE,
|
633
|
+
"Error creating prepared statement for MySql RefDB backend");
|
634
|
+
return GIT_ERROR;
|
635
|
+
}
|
636
|
+
|
637
|
+
backend->st_write = mysql_stmt_init(backend->db);
|
638
|
+
if (backend->st_write == NULL) {
|
639
|
+
giterr_set(GITERR_REFERENCE,
|
640
|
+
"Error creating prepared statement for MySql RefDB backend");
|
641
|
+
return GIT_ERROR;
|
642
|
+
}
|
643
|
+
if (mysql_stmt_attr_set
|
644
|
+
(backend->st_write, STMT_ATTR_UPDATE_MAX_LENGTH, &truth) != 0) {
|
645
|
+
giterr_set(GITERR_REFERENCE,
|
646
|
+
"Error creating prepared statement for MySql RefDB backend");
|
647
|
+
return GIT_ERROR;
|
648
|
+
}
|
649
|
+
if (mysql_stmt_prepare(backend->st_write, sql_write, strlen(sql_write))
|
650
|
+
!= 0) {
|
651
|
+
giterr_set(GITERR_REFERENCE,
|
652
|
+
"Error creating prepared statement for MySql RefDB backend");
|
653
|
+
return GIT_ERROR;
|
654
|
+
}
|
655
|
+
|
656
|
+
backend->st_delete = mysql_stmt_init(backend->db);
|
657
|
+
if (backend->st_delete == NULL) {
|
658
|
+
giterr_set(GITERR_REFERENCE,
|
659
|
+
"Error creating prepared statement for MySql RefDB backend");
|
660
|
+
return GIT_ERROR;
|
661
|
+
}
|
662
|
+
if (mysql_stmt_attr_set
|
663
|
+
(backend->st_delete, STMT_ATTR_UPDATE_MAX_LENGTH, &truth) != 0) {
|
664
|
+
giterr_set(GITERR_REFERENCE,
|
665
|
+
"Error creating prepared statement for MySql RefDB backend");
|
666
|
+
return GIT_ERROR;
|
667
|
+
}
|
668
|
+
if (mysql_stmt_prepare
|
669
|
+
(backend->st_delete, sql_delete, strlen(sql_delete)) != 0) {
|
670
|
+
giterr_set(GITERR_REFERENCE,
|
671
|
+
"Error creating prepared statement for MySql RefDB backend");
|
672
|
+
return GIT_ERROR;
|
673
|
+
}
|
674
|
+
|
675
|
+
return GIT_OK;
|
676
|
+
}
|
677
|
+
|
678
|
+
int
|
679
|
+
git_refdb_backend_mysql(git_refdb_backend ** backend_out,
|
680
|
+
const char *mysql_host,
|
681
|
+
unsigned int mysql_port,
|
682
|
+
const char *mysql_unix_socket, const char *mysql_db,
|
683
|
+
const char *mysql_user, const char *mysql_passwd,
|
684
|
+
unsigned long mysql_client_flag)
|
685
|
+
{
|
686
|
+
mysql_refdb_backend *backend;
|
687
|
+
my_bool reconnect = 1;
|
688
|
+
|
689
|
+
backend = calloc(1, sizeof(mysql_refdb_backend));
|
690
|
+
if (backend == NULL) {
|
691
|
+
return GITERR_NOMEMORY;
|
692
|
+
}
|
693
|
+
|
694
|
+
backend->db = mysql_init(backend->db);
|
695
|
+
|
696
|
+
if (mysql_options(backend->db, MYSQL_OPT_RECONNECT, &reconnect) != 0) {
|
697
|
+
goto cleanup;
|
698
|
+
}
|
699
|
+
|
700
|
+
if (mysql_real_connect
|
701
|
+
(backend->db, mysql_host, mysql_user, mysql_passwd, mysql_db,
|
702
|
+
mysql_port, mysql_unix_socket, mysql_client_flag) != backend->db) {
|
703
|
+
goto cleanup;
|
704
|
+
}
|
705
|
+
|
706
|
+
if (init_db(backend->db) < 0) {
|
707
|
+
goto cleanup;
|
708
|
+
}
|
709
|
+
|
710
|
+
if (init_statements(backend) < 0) {
|
711
|
+
goto cleanup;
|
712
|
+
}
|
713
|
+
|
714
|
+
backend->parent.exists = &mysql_refdb_backend__exists;
|
715
|
+
backend->parent.lookup = &mysql_refdb_backend__lookup;
|
716
|
+
backend->parent.iterator = &mysql_refdb_backend__iterator;
|
717
|
+
backend->parent.write = &mysql_refdb_backend__write;
|
718
|
+
backend->parent.del = &mysql_refdb_backend__delete;
|
719
|
+
backend->parent.rename = &mysql_refdb_backend__rename;
|
720
|
+
backend->parent.compress = &mysql_refdb_backend__compress;
|
721
|
+
backend->parent.has_log = &mysql_refdb_backend__has_log;
|
722
|
+
backend->parent.ensure_log = &mysql_refdb_backend__ensure_log;
|
723
|
+
backend->parent.free = &mysql_refdb_backend__free;
|
724
|
+
backend->parent.reflog_read = &mysql_refdb_backend__reflog_read;
|
725
|
+
backend->parent.reflog_write = &mysql_refdb_backend__reflog_write;
|
726
|
+
backend->parent.reflog_rename = &mysql_refdb_backend__reflog_rename;
|
727
|
+
backend->parent.reflog_delete = &mysql_refdb_backend__reflog_delete;
|
728
|
+
|
729
|
+
*backend_out = (git_refdb_backend *) backend;
|
730
|
+
return GIT_OK;
|
731
|
+
|
732
|
+
cleanup:
|
733
|
+
mysql_refdb_backend__free((git_refdb_backend *) backend);
|
734
|
+
return GIT_ERROR;
|
735
|
+
}
|