[PATCH v2 01/44] Add support for ruby commands

2013-09-28 Thread Felipe Contreras
Signed-off-by: Felipe Contreras felipe.contre...@gmail.com
---

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/t1-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/t1-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 000..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 000..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 

Re: [PATCH v2 01/44] Add support for ruby commands

2013-09-28 Thread Felipe Contreras
On Sat, Sep 28, 2013 at 11:30 PM, Ramkumar Ramachandra
artag...@gmail.com wrote:
 Felipe Contreras wrote:
 +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
 +'

 So, git-ruby is a new builtin that's just like a ruby interpreter,
 except that it has certain git-related functions defined: you pass it
 source code on stdin, and it returns the result on stdout. I wonder
 what the purpose of passing arguments to it is though.

git ruby is just like ruby, so you can pass the script from stdin, or
you can specify the script name.

 +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
 +'

 I find it interesting that you chose to implement for-each-ref in the
 initial version. It currently takes no arguments, but we can always
 extend it to do ref-hierarchy filtering like f-e-r in the future.

It takes no arguments because for_each_ref()(refs.h) takes no
arguments (that Ruby would need). builtin/for-each-ref.c uses
for_each_rawref()(refs.h), which is basically the same.

-- 
Felipe Contreras
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html