Skip to content

Commit 248eae9

Browse files
Better Odb, Refdb and Config Backend support.
1 parent 1c47374 commit 248eae9

16 files changed

+771
-131
lines changed

ext/rugged/rugged.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ void Init_rugged(void)
473473
Init_rugged_branch();
474474
Init_rugged_branch_collection();
475475
Init_rugged_config();
476+
Init_rugged_config_backend();
476477
Init_rugged_remote();
477478
Init_rugged_remote_collection();
478479
Init_rugged_notes();
@@ -486,7 +487,16 @@ void Init_rugged(void)
486487
Init_rugged_diff_line();
487488
Init_rugged_blame();
488489
Init_rugged_cred();
489-
Init_rugged_backend();
490+
491+
Init_rugged_refdb();
492+
Init_rugged_refdb_backend();
493+
Init_rugged_refdb_backend_fs();
494+
495+
Init_rugged_odb();
496+
Init_rugged_odb_backend();
497+
Init_rugged_odb_backend_loose();
498+
Init_rugged_odb_backend_one_pack();
499+
Init_rugged_odb_backend_pack();
490500

491501
/*
492502
* Sort the repository contents in no particular ordering;

ext/rugged/rugged.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
#include <assert.h>
4141
#include <git2.h>
4242
#include <git2/odb_backend.h>
43+
#include <git2/sys/config.h>
44+
#include <git2/sys/refdb_backend.h>
45+
#include <git2/sys/refs.h>
46+
#include <git2/sys/repository.h>
47+
#include <git2/sys/odb_backend.h>
4348

4449
#define rb_str_new_utf8(str) rb_enc_str_new(str, strlen(str), rb_utf8_encoding())
4550
#define CSTR2SYM(s) (ID2SYM(rb_intern((s))))
@@ -61,6 +66,7 @@ void Init_rugged_revwalk(void);
6166
void Init_rugged_reference(void);
6267
void Init_rugged_reference_collection(void);
6368
void Init_rugged_config(void);
69+
void Init_rugged_config_backend(void);
6470
void Init_rugged_remote(void);
6571
void Init_rugged_remote_collection(void);
6672
void Init_rugged_notes(void);
@@ -74,7 +80,14 @@ void Init_rugged_diff_hunk(void);
7480
void Init_rugged_diff_line(void);
7581
void Init_rugged_blame(void);
7682
void Init_rugged_cred(void);
77-
void Init_rugged_backend(void);
83+
void Init_rugged_refdb(void);
84+
void Init_rugged_refdb_backend(void);
85+
void Init_rugged_refdb_backend_fs(void);
86+
void Init_rugged_odb(void);
87+
void Init_rugged_odb_backend(void);
88+
void Init_rugged_odb_backend_loose(void);
89+
void Init_rugged_odb_backend_one_pack(void);
90+
void Init_rugged_odb_backend_pack(void);
7891

7992
VALUE rb_git_object_init(git_otype type, int argc, VALUE *argv, VALUE self);
8093

@@ -84,7 +97,9 @@ VALUE rugged_signature_new(const git_signature *sig, const char *encoding_name);
8497

8598
VALUE rugged_repo_new(VALUE klass, git_repository *repo);
8699
VALUE rugged_index_new(VALUE klass, VALUE owner, git_index *index);
100+
VALUE rugged_refdb_new(VALUE klass, VALUE owner, git_refdb *refdb);
87101
VALUE rugged_config_new(VALUE klass, VALUE owner, git_config *cfg);
102+
VALUE rugged_odb_new(VALUE klass, VALUE owner, git_odb *odb);
88103
VALUE rugged_object_new(VALUE owner, git_object *object);
89104
VALUE rugged_object_rev_parse(VALUE rb_repo, VALUE rb_spec, int as_obj);
90105
VALUE rugged_ref_new(VALUE klass, VALUE owner, git_reference *ref);
@@ -176,10 +191,4 @@ static inline VALUE rugged_create_oid(const git_oid *oid)
176191
return rb_str_new(out, 40);
177192
}
178193

179-
180-
typedef struct _rugged_backend {
181-
int (* odb_backend)(git_odb_backend **backend_out, struct _rugged_backend *backend, const char* path);
182-
int (* refdb_backend)(git_refdb_backend **backend_out, struct _rugged_backend *backend, const char* path);
183-
} rugged_backend;
184-
185194
#endif

ext/rugged/rugged_config.c

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,21 @@ VALUE rugged_config_new(VALUE klass, VALUE owner, git_config *cfg)
4141

4242
/*
4343
* call-seq:
44-
* Config.new(path) -> new_config
44+
* Config.new([path]) -> config
4545
*
46-
* Open the file specified in +path+ as a +Rugged::Config+ file.
47-
* If +path+ cannot be found, or the file is an invalid Git config,
48-
* an exception will be raised.
46+
* Create a new config object.
47+
*
48+
* If +path+ is specified, the file at this path will be used as the backing
49+
* config store. +path+ can also be an array of file paths to be used.
50+
*
51+
* If +path+ is not specified, an empty config object will be returned.
4952
*/
50-
static VALUE rb_git_config_new(VALUE klass, VALUE rb_path)
53+
static VALUE rb_git_config_new(int argc, VALUE *argv, VALUE klass)
5154
{
52-
git_config *config = NULL;
55+
git_config *config;
56+
VALUE rb_path;
57+
58+
rb_scan_args(argc, argv, "01", &rb_path);
5359

5460
if (TYPE(rb_path) == T_ARRAY) {
5561
int error, i;
@@ -71,8 +77,11 @@ static VALUE rb_git_config_new(VALUE klass, VALUE rb_path)
7177
rugged_exception_check(
7278
git_config_open_ondisk(&config, StringValueCStr(rb_path))
7379
);
80+
} else if (NIL_P(rb_path)) {
81+
rugged_exception_check(git_config_new(&config));
7482
} else {
75-
rb_raise(rb_eTypeError, "Expecting a filename or an array of filenames");
83+
rb_raise(rb_eTypeError, "wrong argument type %s (expected an Array, String, or nil)",
84+
rb_obj_classname(rb_path));
7685
}
7786

7887
return rugged_config_new(klass, Qnil, config);
@@ -375,19 +384,80 @@ static VALUE rb_git_config_transaction(VALUE self)
375384
return rb_result;
376385
}
377386

387+
/*
388+
* call-seq:
389+
* config.add_backend(backend, level, force = false) -> config
390+
*
391+
* Add a backend to be used by the config.
392+
*
393+
* A backend can only be assigned once, and becomes unusable from that
394+
* point on. Trying to assign a backend a second time will raise an
395+
* exception.
396+
*/
397+
static VALUE rb_git_config_add_backend(int argc, VALUE *argv, VALUE self)
398+
{
399+
git_config *config;
400+
git_config_backend *backend;
401+
ID id_level;
402+
git_config_level_t level;
403+
VALUE rb_backend, rb_level, rb_force;
404+
405+
rb_scan_args(argc, argv, "21", &rb_backend, &rb_level, &rb_force);
406+
407+
// TODO: Check rb_backend
408+
409+
Check_Type(rb_level, T_SYMBOL);
410+
411+
id_level = SYM2ID(rb_level);
412+
413+
if (id_level == rb_intern("system")) {
414+
level = GIT_CONFIG_LEVEL_SYSTEM;
415+
} else if (id_level == rb_intern("xdg")) {
416+
level = GIT_CONFIG_LEVEL_XDG;
417+
} else if (id_level == rb_intern("global")) {
418+
level = GIT_CONFIG_LEVEL_GLOBAL;
419+
} else if (id_level == rb_intern("local")) {
420+
level = GIT_CONFIG_LEVEL_LOCAL;
421+
} else if (id_level == rb_intern("app")) {
422+
level = GIT_CONFIG_LEVEL_APP;
423+
} else if (id_level == rb_intern("highest")) {
424+
level = GIT_CONFIG_HIGHEST_LEVEL;
425+
} else {
426+
rb_raise(rb_eArgError, "Invalid config backend level.");
427+
}
428+
429+
// TODO: if (!NIL_P(rb_force) && rb_force != Qtrue && rb_force != Qfalse)
430+
431+
Data_Get_Struct(self, git_config, config);
432+
Data_Get_Struct(rb_backend, git_config_backend, backend);
433+
434+
if (!backend)
435+
rb_exc_raise(rb_exc_new2(rb_eRuntimeError, "Can not reuse config backend instances"));
436+
437+
rugged_exception_check(git_config_add_backend(config, backend, level, RTEST(rb_force)));
438+
439+
// libgit2 has taken ownership of the backend, so we should make sure
440+
// we don't try to free it.
441+
((struct RData *)rb_backend)->data = NULL;
442+
443+
return self;
444+
}
445+
378446
void Init_rugged_config(void)
379447
{
380448
/*
381449
* Config
382450
*/
383451
rb_cRuggedConfig = rb_define_class_under(rb_mRugged, "Config", rb_cObject);
384-
rb_define_singleton_method(rb_cRuggedConfig, "new", rb_git_config_new, 1);
452+
rb_define_singleton_method(rb_cRuggedConfig, "new", rb_git_config_new, -1);
385453

386454
rb_define_singleton_method(rb_cRuggedConfig, "global", rb_git_config_open_default, 0);
387455
rb_define_singleton_method(rb_cRuggedConfig, "open_global", rb_git_config_open_default, 0);
388456

389457
rb_define_method(rb_cRuggedConfig, "delete", rb_git_config_delete, 1);
390458

459+
rb_define_method(rb_cRuggedConfig, "add_backend", rb_git_config_add_backend, -1);
460+
391461
rb_define_method(rb_cRuggedConfig, "store", rb_git_config_store, 2);
392462
rb_define_method(rb_cRuggedConfig, "[]=", rb_git_config_store, 2);
393463

ext/rugged/rugged_config_backend.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2015 GitHub, Inc
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
#include "rugged.h"
26+
27+
extern VALUE rb_cRuggedConfig;
28+
VALUE rb_cRuggedConfigBackend;
29+
30+
void Init_rugged_config_backend(void)
31+
{
32+
rb_cRuggedConfigBackend = rb_define_class_under(rb_cRuggedConfig, "Backend", rb_cObject);
33+
}

ext/rugged/rugged_odb.c

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2015 GitHub, Inc
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
#include "rugged.h"
26+
27+
extern VALUE rb_mRugged;
28+
VALUE rb_cRuggedOdb;
29+
30+
VALUE rugged_odb_new(VALUE klass, VALUE owner, git_odb *odb)
31+
{
32+
VALUE rb_odb = Data_Wrap_Struct(klass, NULL, &git_odb_free, odb);
33+
34+
rugged_set_owner(rb_odb, owner);
35+
36+
return rb_odb;
37+
}
38+
39+
/*
40+
* call-seq:
41+
* Odb.new() -> odb
42+
*
43+
* Create a new object database with no backend.
44+
*
45+
* Before the object database can be used, backends
46+
* needs to be assigned using `Odb#add_backend`.
47+
*/
48+
static VALUE rb_git_odb_new(VALUE klass) {
49+
git_odb *odb;
50+
51+
rugged_exception_check(git_odb_new(&odb));
52+
53+
return rugged_odb_new(klass, Qnil, odb);
54+
}
55+
56+
/*
57+
* call-seq:
58+
* Odb.open(dir) -> odb
59+
*
60+
* Create a new object database with the default filesystem
61+
* backends.
62+
*
63+
* `dir` needs to point to the objects folder to be used
64+
* by the filesystem backends.
65+
*/
66+
static VALUE rb_git_odb_open(VALUE klass, VALUE rb_path) {
67+
git_odb *odb;
68+
69+
rugged_exception_check(git_odb_open(&odb, StringValueCStr(rb_path)));
70+
71+
return rugged_odb_new(klass, Qnil, odb);
72+
}
73+
74+
/*
75+
* call-seq:
76+
* odb.add_backend(backend, priority) -> odb
77+
*
78+
* Add a backend to be used by the object db.
79+
*
80+
* A backend can only be assigned once, and becomes unusable from that
81+
* point on. Trying to assign a backend a second time will raise an
82+
* exception.
83+
*/
84+
static VALUE rb_git_odb_add_backend(VALUE self, VALUE rb_backend, VALUE rb_priority)
85+
{
86+
git_odb *odb;
87+
git_odb_backend *backend;
88+
89+
Data_Get_Struct(self, git_odb, odb);
90+
Data_Get_Struct(rb_backend, git_odb_backend, backend);
91+
92+
if (!backend)
93+
rb_exc_raise(rb_exc_new2(rb_eRuntimeError, "Can not reuse odb backend instances"));
94+
95+
rugged_exception_check(git_odb_add_backend(odb, backend, NUM2INT(rb_priority)));
96+
97+
// libgit2 has taken ownership of the backend, so we should make sure
98+
// we don't try to free it.
99+
((struct RData *)rb_backend)->data = NULL;
100+
101+
return self;
102+
}
103+
104+
static int cb_odb__each(const git_oid *id, void *data)
105+
{
106+
char out[40];
107+
struct rugged_cb_payload *payload = data;
108+
109+
git_oid_fmt(out, id);
110+
rb_protect(rb_yield, rb_str_new(out, 40), &payload->exception);
111+
112+
return payload->exception ? GIT_ERROR : GIT_OK;
113+
}
114+
115+
static VALUE rb_git_odb_each(VALUE self)
116+
{
117+
git_odb *odb;
118+
int error;
119+
struct rugged_cb_payload payload = { self, 0 };
120+
121+
Data_Get_Struct(self, git_odb, odb);
122+
123+
error = git_odb_foreach(odb, &cb_odb__each, &payload);
124+
125+
if (payload.exception)
126+
rb_jump_tag(payload.exception);
127+
rugged_exception_check(error);
128+
129+
return Qnil;
130+
}
131+
132+
void Init_rugged_odb(void)
133+
{
134+
rb_cRuggedOdb = rb_define_class_under(rb_mRugged, "Odb", rb_cObject);
135+
136+
rb_define_singleton_method(rb_cRuggedOdb, "new", rb_git_odb_new, 0);
137+
rb_define_singleton_method(rb_cRuggedOdb, "open", rb_git_odb_open, 1);
138+
139+
rb_define_method(rb_cRuggedOdb, "add_backend", rb_git_odb_add_backend, 2);
140+
rb_define_method(rb_cRuggedOdb, "each", rb_git_odb_each, 0);
141+
}

0 commit comments

Comments
 (0)