rugged-mysql 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }