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.
@@ -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
+ }