Signed-off-by: Felipe Contreras <felipe.contreras@xxxxxxxxx> --- Notes: With this support, third parties would be able to write scripts more easily and access libgit facilities. Also, it could help developers by allowing easier prototyping git ruby > actual <<EOF && for_each_ref() do |name, sha1, flags| puts "%s: %s" % [name, sha1_to_hex(sha1)] end .gitignore | 1 + Makefile | 19 ++++++++++++++++++- git-rb-setup.rb | 11 +++++++++++ ruby.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ t/t10000-ruby.sh | 42 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 git-rb-setup.rb create mode 100644 ruby.c create mode 100755 t/t10000-ruby.sh diff --git a/.gitignore b/.gitignore index 6b1fd1b..51b04be 100644 --- a/.gitignore +++ b/.gitignore @@ -139,6 +139,7 @@ /git-rev-parse /git-revert /git-rm +/git-ruby /git-send-email /git-send-pack /git-sh-i18n diff --git a/Makefile b/Makefile index 3588ca1..2fdee15 100644 --- a/Makefile +++ b/Makefile @@ -491,6 +491,8 @@ SCRIPT_PERL += git-svn.perl SCRIPT_PYTHON += git-remote-testpy.py SCRIPT_PYTHON += git-p4.py +SCRIPT_RUBY += git-rb-setup.rb + NO_INSTALL += git-remote-testgit NO_INSTALL += git-remote-testpy @@ -502,6 +504,7 @@ SCRIPT_PYTHON_GEN = $(patsubst %.py,%,$(SCRIPT_PYTHON)) SCRIPT_SH_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_SH_GEN)) SCRIPT_PERL_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_PERL_GEN)) SCRIPT_PYTHON_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_PYTHON_GEN)) +SCRIPT_RUBY_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_RUBY)) # Individual rules to allow e.g. # "make -C ../.. SCRIPT_PERL=contrib/foo/bar.perl build-perl-script" @@ -511,13 +514,15 @@ build-perl-script: $(SCRIPT_PERL_GEN) build-sh-script: $(SCRIPT_SH_GEN) build-python-script: $(SCRIPT_PYTHON_GEN) -.PHONY: install-perl-script install-sh-script install-python-script +.PHONY: install-perl-script install-sh-script install-python-script install-ruby-script install-sh-script: $(SCRIPT_SH_INS) $(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' install-perl-script: $(SCRIPT_PERL_INS) $(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' install-python-script: $(SCRIPT_PYTHON_INS) $(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' +install-ruby-script: $(SCRIPT_RUBY_INS) + $(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' .PHONY: clean-perl-script clean-sh-script clean-python-script clean-sh-script: @@ -530,6 +535,7 @@ clean-python-script: SCRIPTS = $(SCRIPT_SH_INS) \ $(SCRIPT_PERL_INS) \ $(SCRIPT_PYTHON_INS) \ + $(SCRIPT_RUBY_INS) \ git-instaweb ETAGS_TARGET = TAGS @@ -1502,6 +1508,12 @@ ifneq (,$(XDL_FAST_HASH)) BASIC_CFLAGS += -DXDL_FAST_HASH endif +ifndef NO_RUBY + RUBY_LIBS = $(shell pkg-config --libs ruby-2.0) + RUBY_CFLAGS = $(shell pkg-config --cflags ruby-2.0) + PROGRAM_OBJS += ruby.o +endif + ifeq ($(TCLTK_PATH),) NO_TCLTK = NoThanks endif @@ -2059,6 +2071,11 @@ git-http-push$X: revision.o http.o http-push.o GIT-LDFLAGS $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) +git-ruby$X: BASIC_CFLAGS += $(RUBY_CFLAGS) +git-ruby$X: ruby.o GIT-LDFLAGS $(GITLIBS) + $(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(RUBY_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ + $(LIBS) $(RUBY_LIBS) + git-remote-testsvn$X: remote-testsvn.o GIT-LDFLAGS $(GITLIBS) $(VCSSVN_LIB) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) \ $(VCSSVN_LIB) diff --git a/git-rb-setup.rb b/git-rb-setup.rb new file mode 100644 index 0000000..969278a --- /dev/null +++ b/git-rb-setup.rb @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby + +def die(*args) + fmt = args.shift + $stderr.printf("fatal: %s\n" % fmt, *args) + exit 128 +end + +def sha1_to_hex(sha1) + sha1.unpack('H*').first +end diff --git a/ruby.c b/ruby.c new file mode 100644 index 0000000..ee6a0e7 --- /dev/null +++ b/ruby.c @@ -0,0 +1,56 @@ +#include "cache.h" +#include "exec_cmd.h" +#include "refs.h" + +#undef NORETURN +#undef PATH_SEP + +#include <ruby.h> + +static inline VALUE sha1_to_str(const unsigned char *sha1) +{ + return rb_str_new((const char *)sha1, 20); +} + +static int for_each_ref_fn(const char *refname, const unsigned char *sha1, int flags, void *cb_data) +{ + VALUE r; + r = rb_yield_values(3, rb_str_new2(refname), sha1_to_str(sha1), INT2FIX(flags)); + return r == Qfalse; +} + +static VALUE git_rb_for_each_ref(void) +{ + int r; + r = for_each_ref(for_each_ref_fn, NULL); + return INT2FIX(r); +} + +static void git_ruby_init(void) +{ + rb_define_global_function("for_each_ref", git_rb_for_each_ref, 0); +} + +static int run_ruby_command(const char *cmd, int argc, const char **argv) +{ + static char buf[PATH_MAX + 1]; + void *node; + struct stat st; + + ruby_init(); + git_ruby_init(); + + node = ruby_options(argc, (char **)argv); + + ruby_script(cmd); + snprintf(buf, PATH_MAX, "%s/%s", git_exec_path(), "git-rb-setup.rb"); + if (!stat(buf, &st)) + rb_load(rb_str_new2(buf), 0); + + return ruby_run_node(node); +} + +int main(int argc, const char **argv) +{ + return run_ruby_command(argv[1], argc, argv); +} diff --git a/t/t10000-ruby.sh b/t/t10000-ruby.sh new file mode 100755 index 0000000..eb03706 --- /dev/null +++ b/t/t10000-ruby.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# +# Copyright (c) 2013 Felipe Contreras +# + +test_description='test ruby support' + +. ./test-lib.sh + +test_expect_success 'basic support' ' + git ruby > actual <<-EOF && + puts "hello world" + EOF + echo "hello world" > expected && + test_cmp expected actual +' + +test_expect_success 'argument passing' ' + cat > script <<-"EOF" && + p($0) + p(ARGV) + EOF + git ruby script foo bar > actual && + cat > expected <<-EOF && + "script" + ["foo", "bar"] + EOF + test_cmp expected actual +' + +test_expect_success 'test for_each_ref()' ' + test_commit foo && + git ruby > actual <<-EOF && + for_each_ref() do |name, sha1, flags| + puts "%s: %s" % [name, sha1_to_hex(sha1)] + end + EOF + git for-each-ref --format="%(refname): %(objectname)" > expected && + test_cmp expected actual +' + +test_done -- 1.8.4-fc -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html