Skip to content

Commit

Permalink
Better Odb, Refdb and Config Backend support.
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurschreiber committed Oct 22, 2015
1 parent 1c47374 commit 248eae9
Show file tree
Hide file tree
Showing 16 changed files with 771 additions and 131 deletions.
12 changes: 11 additions & 1 deletion ext/rugged/rugged.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ void Init_rugged(void)
Init_rugged_branch();
Init_rugged_branch_collection();
Init_rugged_config();
Init_rugged_config_backend();
Init_rugged_remote();
Init_rugged_remote_collection();
Init_rugged_notes();
Expand All @@ -486,7 +487,16 @@ void Init_rugged(void)
Init_rugged_diff_line();
Init_rugged_blame();
Init_rugged_cred();
Init_rugged_backend();

Init_rugged_refdb();
Init_rugged_refdb_backend();
Init_rugged_refdb_backend_fs();

Init_rugged_odb();
Init_rugged_odb_backend();
Init_rugged_odb_backend_loose();
Init_rugged_odb_backend_one_pack();
Init_rugged_odb_backend_pack();

/*
* Sort the repository contents in no particular ordering;
Expand Down
23 changes: 16 additions & 7 deletions ext/rugged/rugged.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
#include <assert.h>
#include <git2.h>
#include <git2/odb_backend.h>
#include <git2/sys/config.h>
#include <git2/sys/refdb_backend.h>
#include <git2/sys/refs.h>
#include <git2/sys/repository.h>
#include <git2/sys/odb_backend.h>

#define rb_str_new_utf8(str) rb_enc_str_new(str, strlen(str), rb_utf8_encoding())
#define CSTR2SYM(s) (ID2SYM(rb_intern((s))))
Expand All @@ -61,6 +66,7 @@ void Init_rugged_revwalk(void);
void Init_rugged_reference(void);
void Init_rugged_reference_collection(void);
void Init_rugged_config(void);
void Init_rugged_config_backend(void);
void Init_rugged_remote(void);
void Init_rugged_remote_collection(void);
void Init_rugged_notes(void);
Expand All @@ -74,7 +80,14 @@ void Init_rugged_diff_hunk(void);
void Init_rugged_diff_line(void);
void Init_rugged_blame(void);
void Init_rugged_cred(void);
void Init_rugged_backend(void);
void Init_rugged_refdb(void);
void Init_rugged_refdb_backend(void);
void Init_rugged_refdb_backend_fs(void);
void Init_rugged_odb(void);
void Init_rugged_odb_backend(void);
void Init_rugged_odb_backend_loose(void);
void Init_rugged_odb_backend_one_pack(void);
void Init_rugged_odb_backend_pack(void);

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

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

VALUE rugged_repo_new(VALUE klass, git_repository *repo);
VALUE rugged_index_new(VALUE klass, VALUE owner, git_index *index);
VALUE rugged_refdb_new(VALUE klass, VALUE owner, git_refdb *refdb);
VALUE rugged_config_new(VALUE klass, VALUE owner, git_config *cfg);
VALUE rugged_odb_new(VALUE klass, VALUE owner, git_odb *odb);
VALUE rugged_object_new(VALUE owner, git_object *object);
VALUE rugged_object_rev_parse(VALUE rb_repo, VALUE rb_spec, int as_obj);
VALUE rugged_ref_new(VALUE klass, VALUE owner, git_reference *ref);
Expand Down Expand Up @@ -176,10 +191,4 @@ static inline VALUE rugged_create_oid(const git_oid *oid)
return rb_str_new(out, 40);
}


typedef struct _rugged_backend {
int (* odb_backend)(git_odb_backend **backend_out, struct _rugged_backend *backend, const char* path);
int (* refdb_backend)(git_refdb_backend **backend_out, struct _rugged_backend *backend, const char* path);
} rugged_backend;

#endif
86 changes: 78 additions & 8 deletions ext/rugged/rugged_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,21 @@ VALUE rugged_config_new(VALUE klass, VALUE owner, git_config *cfg)

/*
* call-seq:
* Config.new(path) -> new_config
* Config.new([path]) -> config
*
* Open the file specified in +path+ as a +Rugged::Config+ file.
* If +path+ cannot be found, or the file is an invalid Git config,
* an exception will be raised.
* Create a new config object.
*
* If +path+ is specified, the file at this path will be used as the backing
* config store. +path+ can also be an array of file paths to be used.
*
* If +path+ is not specified, an empty config object will be returned.
*/
static VALUE rb_git_config_new(VALUE klass, VALUE rb_path)
static VALUE rb_git_config_new(int argc, VALUE *argv, VALUE klass)
{
git_config *config = NULL;
git_config *config;
VALUE rb_path;

rb_scan_args(argc, argv, "01", &rb_path);

if (TYPE(rb_path) == T_ARRAY) {
int error, i;
Expand All @@ -71,8 +77,11 @@ static VALUE rb_git_config_new(VALUE klass, VALUE rb_path)
rugged_exception_check(
git_config_open_ondisk(&config, StringValueCStr(rb_path))
);
} else if (NIL_P(rb_path)) {
rugged_exception_check(git_config_new(&config));
} else {
rb_raise(rb_eTypeError, "Expecting a filename or an array of filenames");
rb_raise(rb_eTypeError, "wrong argument type %s (expected an Array, String, or nil)",
rb_obj_classname(rb_path));
}

return rugged_config_new(klass, Qnil, config);
Expand Down Expand Up @@ -375,19 +384,80 @@ static VALUE rb_git_config_transaction(VALUE self)
return rb_result;
}

/*
* call-seq:
* config.add_backend(backend, level, force = false) -> config
*
* Add a backend to be used by the config.
*
* A backend can only be assigned once, and becomes unusable from that
* point on. Trying to assign a backend a second time will raise an
* exception.
*/
static VALUE rb_git_config_add_backend(int argc, VALUE *argv, VALUE self)
{
git_config *config;
git_config_backend *backend;
ID id_level;
git_config_level_t level;
VALUE rb_backend, rb_level, rb_force;

rb_scan_args(argc, argv, "21", &rb_backend, &rb_level, &rb_force);

// TODO: Check rb_backend

Check_Type(rb_level, T_SYMBOL);

id_level = SYM2ID(rb_level);

if (id_level == rb_intern("system")) {
level = GIT_CONFIG_LEVEL_SYSTEM;
} else if (id_level == rb_intern("xdg")) {
level = GIT_CONFIG_LEVEL_XDG;
} else if (id_level == rb_intern("global")) {
level = GIT_CONFIG_LEVEL_GLOBAL;
} else if (id_level == rb_intern("local")) {
level = GIT_CONFIG_LEVEL_LOCAL;
} else if (id_level == rb_intern("app")) {
level = GIT_CONFIG_LEVEL_APP;
} else if (id_level == rb_intern("highest")) {
level = GIT_CONFIG_HIGHEST_LEVEL;
} else {
rb_raise(rb_eArgError, "Invalid config backend level.");
}

// TODO: if (!NIL_P(rb_force) && rb_force != Qtrue && rb_force != Qfalse)

Data_Get_Struct(self, git_config, config);
Data_Get_Struct(rb_backend, git_config_backend, backend);

if (!backend)
rb_exc_raise(rb_exc_new2(rb_eRuntimeError, "Can not reuse config backend instances"));

rugged_exception_check(git_config_add_backend(config, backend, level, RTEST(rb_force)));

// libgit2 has taken ownership of the backend, so we should make sure
// we don't try to free it.
((struct RData *)rb_backend)->data = NULL;

return self;
}

void Init_rugged_config(void)
{
/*
* Config
*/
rb_cRuggedConfig = rb_define_class_under(rb_mRugged, "Config", rb_cObject);
rb_define_singleton_method(rb_cRuggedConfig, "new", rb_git_config_new, 1);
rb_define_singleton_method(rb_cRuggedConfig, "new", rb_git_config_new, -1);

rb_define_singleton_method(rb_cRuggedConfig, "global", rb_git_config_open_default, 0);
rb_define_singleton_method(rb_cRuggedConfig, "open_global", rb_git_config_open_default, 0);

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

rb_define_method(rb_cRuggedConfig, "add_backend", rb_git_config_add_backend, -1);

rb_define_method(rb_cRuggedConfig, "store", rb_git_config_store, 2);
rb_define_method(rb_cRuggedConfig, "[]=", rb_git_config_store, 2);

Expand Down
33 changes: 33 additions & 0 deletions ext/rugged/rugged_config_backend.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* The MIT License
*
* Copyright (c) 2015 GitHub, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include "rugged.h"

extern VALUE rb_cRuggedConfig;
VALUE rb_cRuggedConfigBackend;

void Init_rugged_config_backend(void)
{
rb_cRuggedConfigBackend = rb_define_class_under(rb_cRuggedConfig, "Backend", rb_cObject);
}
141 changes: 141 additions & 0 deletions ext/rugged/rugged_odb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* The MIT License
*
* Copyright (c) 2015 GitHub, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include "rugged.h"

extern VALUE rb_mRugged;
VALUE rb_cRuggedOdb;

VALUE rugged_odb_new(VALUE klass, VALUE owner, git_odb *odb)
{
VALUE rb_odb = Data_Wrap_Struct(klass, NULL, &git_odb_free, odb);

rugged_set_owner(rb_odb, owner);

return rb_odb;
}

/*
* call-seq:
* Odb.new() -> odb
*
* Create a new object database with no backend.
*
* Before the object database can be used, backends
* needs to be assigned using `Odb#add_backend`.
*/
static VALUE rb_git_odb_new(VALUE klass) {
git_odb *odb;

rugged_exception_check(git_odb_new(&odb));

return rugged_odb_new(klass, Qnil, odb);
}

/*
* call-seq:
* Odb.open(dir) -> odb
*
* Create a new object database with the default filesystem
* backends.
*
* `dir` needs to point to the objects folder to be used
* by the filesystem backends.
*/
static VALUE rb_git_odb_open(VALUE klass, VALUE rb_path) {
git_odb *odb;

rugged_exception_check(git_odb_open(&odb, StringValueCStr(rb_path)));

return rugged_odb_new(klass, Qnil, odb);
}

/*
* call-seq:
* odb.add_backend(backend, priority) -> odb
*
* Add a backend to be used by the object db.
*
* A backend can only be assigned once, and becomes unusable from that
* point on. Trying to assign a backend a second time will raise an
* exception.
*/
static VALUE rb_git_odb_add_backend(VALUE self, VALUE rb_backend, VALUE rb_priority)
{
git_odb *odb;
git_odb_backend *backend;

Data_Get_Struct(self, git_odb, odb);
Data_Get_Struct(rb_backend, git_odb_backend, backend);

if (!backend)
rb_exc_raise(rb_exc_new2(rb_eRuntimeError, "Can not reuse odb backend instances"));

rugged_exception_check(git_odb_add_backend(odb, backend, NUM2INT(rb_priority)));

// libgit2 has taken ownership of the backend, so we should make sure
// we don't try to free it.
((struct RData *)rb_backend)->data = NULL;

return self;
}

static int cb_odb__each(const git_oid *id, void *data)
{
char out[40];
struct rugged_cb_payload *payload = data;

git_oid_fmt(out, id);
rb_protect(rb_yield, rb_str_new(out, 40), &payload->exception);

return payload->exception ? GIT_ERROR : GIT_OK;
}

static VALUE rb_git_odb_each(VALUE self)
{
git_odb *odb;
int error;
struct rugged_cb_payload payload = { self, 0 };

Data_Get_Struct(self, git_odb, odb);

error = git_odb_foreach(odb, &cb_odb__each, &payload);

if (payload.exception)
rb_jump_tag(payload.exception);
rugged_exception_check(error);

return Qnil;
}

void Init_rugged_odb(void)
{
rb_cRuggedOdb = rb_define_class_under(rb_mRugged, "Odb", rb_cObject);

rb_define_singleton_method(rb_cRuggedOdb, "new", rb_git_odb_new, 0);
rb_define_singleton_method(rb_cRuggedOdb, "open", rb_git_odb_open, 1);

rb_define_method(rb_cRuggedOdb, "add_backend", rb_git_odb_add_backend, 2);
rb_define_method(rb_cRuggedOdb, "each", rb_git_odb_each, 0);
}
Loading

0 comments on commit 248eae9

Please sign in to comment.