git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH/RFC 0/7] Support for Ruby
@ 2013-09-21 18:48 Felipe Contreras
  2013-09-21 18:48 ` [PATCH/RFC 1/7] Add support for ruby commands Felipe Contreras
                   ` (7 more replies)
  0 siblings, 8 replies; 26+ messages in thread
From: Felipe Contreras @ 2013-09-21 18:48 UTC (permalink / raw)
  To: git; +Cc: Ramkumar Ramachandra, Felipe Contreras

Hi,

It was discussed before that there was a need to replace Git scripts from perl
and sh that utilize the 'git' binary to do everything they need, which requires
many forks, and that creates problems on platforms like Windows.

This is a first step meant to show how a solution using Ruby would look like.

Other alternatives just don't cut it. Shell scripts are too simple, and
invariably require forks. Perl could use Git's internal C code, but it's syntax
is too cumbersome and it's loosing more and more popularity. Python and Ruby
are the only modern languages that could fit all the needs, but Python's syntax
is not ideal, specially considering the background of the Git community, and
also, Ruby's C extensibility is simply superb.

This patch series introduces Ruby bindings for Git's C internal library, and
add example commands to show how it could be used, and how it resembles the
original C code, shell code, and perl code. Basically, Ruby fits like a glove.

== Syntax ==

First of all, the syntax of Ruby is very similar to other languages used by Git:

C:

  if (a && b || (c & FLAG) != 0)
    return 0
  else
    break
  end

  printf("format: %s: %i\n", "this string", 0)

  count += 1

Shell:

  out = `git rev-parse #{committish}`

  str = <<EOF
  multi
  line
  string
  EOF

Perl

  var ||= 'default'

The following Perl code:

  sub abbr {
    my $ref = shift;
    if ($ref =~ m{^refs/heads/(.*)$}) {
      return $1;
    }
    return $ref;
  }

Looks like this in Ruby:

  def abbr(ref)
    if (ref =~ %r{^refs/heads/(.*)$}m)
      return $1
    end
    return ref
  end

== C bindings ==

It's extremely easy to write wrappers for Git's C functions:

  static VALUE git_rb_get_git_dir(VALUE self)
  {
    return rb_str_new2(get_git_dir());
  }

  rb_define_global_function("get_git_dir", git_rb_get_git_dir, 0);

Then in Ruby:

  dir = get_git_dir()

== Much more ==

Ruby's power allows for plenty of extensibility.

For example:

  p `echo yes`
  => "yes\n"

Usually we want to chomp the last new line. Fortunately everything is open in
Ruby, so it's possible to override the `() method:

  def `(cmd)
    IO.popen(cmd) { |pipe| pipe.read.chomp }
  end

Now:

  p `echo yes`
  => "yes"

Also, in shell, if we want to make sure a sequence of commands is executed, we
would do something like:

  git command 1 &&
  git command 2 &&
  git command 3 ||
  error

This gets specially troublesome the bigger the sequence. In Ruby:

  def run(*args)
    system(*args)
    raise RuntimeError unless $?.success?
  end

  begin
    run('git command 1')
    run('git command 2')
    run('git command 3')
  rescue RuntimeError
    error
  end

Finally, Ruby has the concept of blocks:

  def run_with_lock()
    puts "lock"
    yield
    puts "unlock"
  end

  branch = 'master'

  run_with_lock() do
    puts "do stuff with #{branch}"
  end

Notice how the block inside run_with_lock() is able to access the 'branch'
variable, because it's in it's context, but the block is not actually called
until run_with_lock() calls 'yield'.

Python has a similar concept, but not nearly as powerful.

== Upgrade path ==

Ruby 2.0 didn't suffer the problems Python 3 is suffering because they have a
sane upgrade path.

Ruby 1.9 changed the syntax, so people using 1.8 had to do minor changes to
upgrade to 1.9, but they didn't miss many major features. After people updated
to 1.9, 2.0 came along with major features, but it was compatible with 1.9, so
nobody had to do any further changes.

Either way, it's still possible to run code that works in 1.8, 1.9, and 2.0.

== Community ==

The Ruby community is already heavily engaged in Git, as statistics in GitHub
show, plenty of Ruby projects use Git, outnumbering by far the Python ones.

There might be some correlation based on the fact that Mercurial is written in
Python.

http://adambard.com/blog/top-github-languages-for-2013-so-far/

== Conclusion ==

Ruby is an extremly powerful modern language, it features object oriented
paradigm, as well as functional, and procedural. It borrows from languages such
as C, Perl, and many others.

It's possible that by opening the possibilities to write Ruby scripts, many
Ruby developers would join the effort to improve Git.

Felipe Contreras (7):
  Add support for ruby commands
  ruby: add setup script
  ruby: add simple wrappers
  ruby: rewrite 'request-pull'
  ruby: rewrite perl script
  ruby: remove one fork
  ruby: rewrite 'reset'

 Makefile            |  16 +-
 cache.h             |   2 +
 git-rb-setup.rb     | 125 +++++++++++++
 git-refs.rb         |   7 +
 git-request-pull.rb | 159 ++++++++++++++++
 git-request-pull.sh | 162 -----------------
 git-reset.rb        | 223 +++++++++++++++++++++++
 git.c               |   4 +-
 ruby.c              | 511 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 1044 insertions(+), 165 deletions(-)
 create mode 100644 git-rb-setup.rb
 create mode 100644 git-refs.rb
 create mode 100644 git-request-pull.rb
 delete mode 100755 git-request-pull.sh
 create mode 100644 git-reset.rb
 create mode 100644 ruby.c

-- 
1.8.4-fc

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH/RFC 1/7] Add support for ruby commands
  2013-09-21 18:48 [PATCH/RFC 0/7] Support for Ruby Felipe Contreras
@ 2013-09-21 18:48 ` Felipe Contreras
  2013-09-21 18:48 ` [PATCH/RFC 2/7] ruby: add setup script Felipe Contreras
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Felipe Contreras @ 2013-09-21 18:48 UTC (permalink / raw)
  To: git; +Cc: Ramkumar Ramachandra, Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 Makefile |  4 ++++
 cache.h  |  2 ++
 git.c    |  3 +++
 ruby.c   | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 57 insertions(+)
 create mode 100644 ruby.c

diff --git a/Makefile b/Makefile
index 3588ca1..7cbcbcb 100644
--- a/Makefile
+++ b/Makefile
@@ -899,6 +899,7 @@ LIB_OBJS += ws.o
 LIB_OBJS += wt-status.o
 LIB_OBJS += xdiff-interface.o
 LIB_OBJS += zlib.o
+LIB_OBJS += ruby.o
 
 BUILTIN_OBJS += builtin/add.o
 BUILTIN_OBJS += builtin/annotate.o
@@ -1502,6 +1503,9 @@ ifneq (,$(XDL_FAST_HASH))
 	BASIC_CFLAGS += -DXDL_FAST_HASH
 endif
 
+EXTLIBS += $(shell pkg-config --libs ruby-2.0)
+BASIC_CFLAGS += $(shell pkg-config --cflags ruby-2.0)
+
 ifeq ($(TCLTK_PATH),)
 NO_TCLTK = NoThanks
 endif
diff --git a/cache.h b/cache.h
index 85b544f..4b1abd4 100644
--- a/cache.h
+++ b/cache.h
@@ -1393,4 +1393,6 @@ int stat_validity_check(struct stat_validity *sv, const char *path);
  */
 void stat_validity_update(struct stat_validity *sv, int fd);
 
+extern void handle_ruby_command(int argc, const char **argv);
+
 #endif /* CACHE_H */
diff --git a/git.c b/git.c
index 2025f77..0e1d97d 100644
--- a/git.c
+++ b/git.c
@@ -499,6 +499,9 @@ static int run_argv(int *argcp, const char ***argv)
 		/* See if it's an internal command */
 		handle_internal_command(*argcp, *argv);
 
+		/* See if it's a ruby command */
+		handle_ruby_command(*argcp, *argv);
+
 		/* .. then try the external ones */
 		execv_dashed_external(*argv);
 
diff --git a/ruby.c b/ruby.c
new file mode 100644
index 0000000..5701753
--- /dev/null
+++ b/ruby.c
@@ -0,0 +1,48 @@
+#include "cache.h"
+#include "exec_cmd.h"
+
+#undef NORETURN
+#undef PATH_SEP
+
+#include <ruby.h>
+
+static const char *commands[] = {
+};
+
+static void run_ruby_command(int argc, const char **argv)
+{
+	const char *cmd = argv[0];
+	static char buf[PATH_MAX + 1];
+	const char *dir;
+	char *args[argc + 2];
+	void *node;
+	VALUE prefix;
+	int i;
+
+	dir = git_exec_path();
+	snprintf(buf, PATH_MAX, "%s/git-%s.rb", dir, cmd);
+
+	ruby_init();
+
+	prefix = Qnil;
+	rb_define_variable("$prefix", &prefix);
+
+	args[0] = "git";
+	args[1] = buf;
+	for (i = 0; i < argc; i++)
+		args[i + 2] = (char*)argv[i];
+	node = ruby_options(argc + 2, args);
+
+	exit(ruby_run_node(node));
+}
+
+void handle_ruby_command(int argc, const char **argv)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(commands); i++) {
+		if (strcmp(commands[i], argv[0]))
+			continue;
+
+		run_ruby_command(argc, argv);
+	}
+}
-- 
1.8.4-fc

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH/RFC 2/7] ruby: add setup script
  2013-09-21 18:48 [PATCH/RFC 0/7] Support for Ruby Felipe Contreras
  2013-09-21 18:48 ` [PATCH/RFC 1/7] Add support for ruby commands Felipe Contreras
@ 2013-09-21 18:48 ` Felipe Contreras
  2013-09-21 18:48 ` [PATCH/RFC 3/7] ruby: add simple wrappers Felipe Contreras
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Felipe Contreras @ 2013-09-21 18:48 UTC (permalink / raw)
  To: git; +Cc: Ramkumar Ramachandra, Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 Makefile        |  8 +++++++-
 git-rb-setup.rb | 11 +++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)
 create mode 100644 git-rb-setup.rb

diff --git a/Makefile b/Makefile
index 7cbcbcb..138f9bf 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
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
-- 
1.8.4-fc

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH/RFC 3/7] ruby: add simple wrappers
  2013-09-21 18:48 [PATCH/RFC 0/7] Support for Ruby Felipe Contreras
  2013-09-21 18:48 ` [PATCH/RFC 1/7] Add support for ruby commands Felipe Contreras
  2013-09-21 18:48 ` [PATCH/RFC 2/7] ruby: add setup script Felipe Contreras
@ 2013-09-21 18:48 ` Felipe Contreras
  2013-09-21 18:48 ` [PATCH/RFC 4/7] ruby: rewrite 'request-pull' Felipe Contreras
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Felipe Contreras @ 2013-09-21 18:48 UTC (permalink / raw)
  To: git; +Cc: Ramkumar Ramachandra, Felipe Contreras

So that we can use for_each_ref() inside Ruby, and provide an example
script.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 Makefile    |  1 +
 git-refs.rb |  7 +++++++
 ruby.c      | 27 +++++++++++++++++++++++++++
 3 files changed, 35 insertions(+)
 create mode 100644 git-refs.rb

diff --git a/Makefile b/Makefile
index 138f9bf..8a4e48f 100644
--- a/Makefile
+++ b/Makefile
@@ -492,6 +492,7 @@ SCRIPT_PYTHON += git-remote-testpy.py
 SCRIPT_PYTHON += git-p4.py
 
 SCRIPT_RUBY += git-rb-setup.rb
+SCRIPT_RUBY += git-refs.rb
 
 NO_INSTALL += git-remote-testgit
 NO_INSTALL += git-remote-testpy
diff --git a/git-refs.rb b/git-refs.rb
new file mode 100644
index 0000000..b048714
--- /dev/null
+++ b/git-refs.rb
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+
+require_relative 'git-rb-setup'
+
+for_each_ref() do |name, sha1, flags|
+  puts '%s: %s' % [name, sha1_to_hex(sha1)]
+end
diff --git a/ruby.c b/ruby.c
index 5701753..7f0cc9d 100644
--- a/ruby.c
+++ b/ruby.c
@@ -1,12 +1,38 @@
 #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_init(void)
+{
+	rb_define_global_function("for_each_ref", git_rb_for_each_ref, 0);
+}
+
 static const char *commands[] = {
+	"refs",
 };
 
 static void run_ruby_command(int argc, const char **argv)
@@ -23,6 +49,7 @@ static void run_ruby_command(int argc, const char **argv)
 	snprintf(buf, PATH_MAX, "%s/git-%s.rb", dir, cmd);
 
 	ruby_init();
+	git_init();
 
 	prefix = Qnil;
 	rb_define_variable("$prefix", &prefix);
-- 
1.8.4-fc

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH/RFC 4/7] ruby: rewrite 'request-pull'
  2013-09-21 18:48 [PATCH/RFC 0/7] Support for Ruby Felipe Contreras
                   ` (2 preceding siblings ...)
  2013-09-21 18:48 ` [PATCH/RFC 3/7] ruby: add simple wrappers Felipe Contreras
@ 2013-09-21 18:48 ` Felipe Contreras
  2013-09-21 18:48 ` [PATCH/RFC 5/7] ruby: rewrite perl script Felipe Contreras
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Felipe Contreras @ 2013-09-21 18:48 UTC (permalink / raw)
  To: git; +Cc: Ramkumar Ramachandra, Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 Makefile            |   2 +-
 git-rb-setup.rb     |  25 ++++++++
 git-request-pull.rb | 153 +++++++++++++++++++++++++++++++++++++++++++++++++
 git-request-pull.sh | 162 ----------------------------------------------------
 ruby.c              |   1 +
 5 files changed, 180 insertions(+), 163 deletions(-)
 create mode 100644 git-request-pull.rb
 delete mode 100755 git-request-pull.sh

diff --git a/Makefile b/Makefile
index 8a4e48f..cb6bb4e 100644
--- a/Makefile
+++ b/Makefile
@@ -465,7 +465,6 @@ SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
 SCRIPT_SH += git-repack.sh
-SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
 SCRIPT_SH += git-web--browse.sh
@@ -493,6 +492,7 @@ SCRIPT_PYTHON += git-p4.py
 
 SCRIPT_RUBY += git-rb-setup.rb
 SCRIPT_RUBY += git-refs.rb
+SCRIPT_RUBY += git-request-pull.rb
 
 NO_INSTALL += git-remote-testgit
 NO_INSTALL += git-remote-testpy
diff --git a/git-rb-setup.rb b/git-rb-setup.rb
index 969278a..f3a2c99 100644
--- a/git-rb-setup.rb
+++ b/git-rb-setup.rb
@@ -9,3 +9,28 @@ end
 def sha1_to_hex(sha1)
   sha1.unpack('H*').first
 end
+
+def pager(msg)
+  pager = ENV['GIT_PAGER'] || `git var GIT_PAGER`.chomp
+  system("echo -n '#{msg}' | #{pager}")
+end
+
+class CommandError < RuntimeError
+
+  attr_reader :command, :output
+
+  def initialize(command, output)
+     @command = command
+     @output = output
+  end
+
+  def to_s
+    Array(@command).join(' ').inspect
+  end
+
+end
+
+def run(cmd)
+  system(cmd)
+  raise CommandError.new(cmd, nil) unless $?.success?
+end
diff --git a/git-request-pull.rb b/git-request-pull.rb
new file mode 100644
index 0000000..b6d0156
--- /dev/null
+++ b/git-request-pull.rb
@@ -0,0 +1,153 @@
+#!/usr/bin/env ruby
+
+require_relative 'git-rb-setup'
+
+patch = ''
+
+ARGV.shift
+
+def usage
+  pager <<EOF
+usage: git request-pull [options] start url [end]
+
+    -p                    show patch text as well
+
+EOF
+  exit 1
+end
+
+until ARGV.empty?
+  case ARGV.first
+  when '-p'
+    patch = '-p'
+  when '--'
+    ARGV.shift
+    break
+  when /^-/
+    usage
+  else
+    break
+  end
+  ARGV.shift
+end
+
+base = ARGV[0]
+url = ARGV[1]
+head = ARGV[2] || 'HEAD'
+status = 0
+branch_name = nil
+
+headref = `git symbolic-ref -q "#{head}"`.chomp
+
+if system(%[git show-ref -q --verify "#{headref}"])
+  branch_name = headref.gsub(/^refs\/heads\//, '')
+  if branch_name == headref ||
+    ! system(%[git config "branch.#{branch_name}.description" >/dev/null])
+    branch_name = nil
+  end
+end
+
+tag_name = `git describe --exact "#{head}^0" 2>/dev/null`.chomp
+
+usage unless base or url
+
+baserev = `git rev-parse --verify --quiet "#{base}"^0`.chomp
+die "Not a valid revision: #{base}" if baserev.empty?
+
+headrev = `git rev-parse --verify --quiet "#{head}"^0`.chomp
+die "Not a valid revision: #{head}" if headrev.empty?
+
+merge_base = `git merge-base #{baserev} #{headrev}`.chomp
+die "No commits in common between #{base} and #{head}" unless $?.success?
+
+# $head is the token given from the command line, and $tag_name, if
+# exists, is the tag we are going to show the commit information for.
+# If that tag exists at the remote and it points at the commit, use it.
+# Otherwise, if a branch with the same name as $head exists at the remote
+# and their values match, use that instead.
+#
+# Otherwise find a random ref that matches $headrev.
+find_matching_ref='
+  sub abbr {
+    my $ref = shift;
+    if ($ref =~ s|^refs/heads/|| || $ref =~ s|^refs/tags/|tags/|) {
+      return $ref;
+    } else {
+      return $ref;
+    }
+  }
+
+  my ($tagged, $branch, $found);
+  while (<STDIN>) {
+    my ($sha1, $ref, $deref) = /^(\S+)\s+(\S+?)(\^\{\})?$/;
+    next unless ($sha1 eq $ARGV[1]);
+    $found = abbr($ref);
+    if ($deref && $ref eq "tags/$ARGV[2]") {
+      $tagged = $found;
+      last;
+    }
+    if ($ref =~ m|/\Q$ARGV[0]\E$|) {
+      $exact = $found;
+    }
+  }
+  if ($tagged) {
+    print "$tagged\n";
+  } elsif ($exact) {
+    print "$exact\n";
+  } elsif ($found) {
+    print "$found\n";
+  }
+'
+
+ref = `git ls-remote "#{url}" | perl -e '#{find_matching_ref}' "#{head}" "#{headrev}" "#{tag_name}"`.chomp
+url = `git ls-remote --get-url "#{url}"`.chomp
+
+begin
+  run(%[git show -s --format='The following changes since commit %H:
+
+  %s (%ci)
+
+are available in the git repository at:
+' #{merge_base}])
+  puts "  #{url}" + (ref.empty? ? "" : " #{ref}")
+  run(%[git show -s --format='
+for you to fetch changes up to %H:
+
+  %s (%ci)
+
+----------------------------------------------------------------' #{headrev}])
+
+  if branch_name
+    puts "(from the branch description for #{branch_name} local branch)"
+    puts
+    run(%[git config "branch.#{branch_name}.description"])
+  end
+
+  if not tag_name.empty?
+    if ref.empty? || ref != "tags/#{tag_name}"
+      $stderr.puts "warn: You locally have #{tag_name} but it does not (yet)"
+      $stderr.puts "warn: appear to be at #{url}"
+      $stderr.puts "warn: Do you want to push it there, perhaps?"
+    end
+    run(%[git cat-file tag "#{tag_name}" | sed -n -e '1,/^$/d' -e '/^-----BEGIN PGP /q' -e p])
+    puts
+  end
+
+  if branch_name or not tag_name.empty?
+    puts "----------------------------------------------------------------"
+  end
+
+  run(%[git shortlog ^#{baserev} #{headrev}])
+  run(%[git diff -M --stat --summary #{patch} #{merge_base}..#{headrev}])
+
+  if ref.empty?
+    $stderr.puts "warn: No branch of #{url} is at:"
+    run("git show -s --format='warn:   %h: %s' #{headrev} >&2")
+    $stderr.puts "warn: Are you sure you pushed '#{head}' there?"
+    status = 1
+  end
+rescue CommandError
+  status = 1
+end
+
+exit status
diff --git a/git-request-pull.sh b/git-request-pull.sh
deleted file mode 100755
index ebf1269..0000000
--- a/git-request-pull.sh
+++ /dev/null
@@ -1,162 +0,0 @@
-#!/bin/sh
-# Copyright 2005, Ryan Anderson <ryan@michonline.com>
-#
-# This file is licensed under the GPL v2, or a later version
-# at the discretion of Linus Torvalds.
-
-USAGE='<start> <url> [<end>]'
-LONG_USAGE='Summarizes the changes between two commits to the standard output,
-and includes the given URL in the generated summary.'
-SUBDIRECTORY_OK='Yes'
-OPTIONS_KEEPDASHDASH=
-OPTIONS_SPEC='git request-pull [options] start url [end]
---
-p    show patch text as well
-'
-
-. git-sh-setup
-
-GIT_PAGER=
-export GIT_PAGER
-
-patch=
-while	case "$#" in 0) break ;; esac
-do
-	case "$1" in
-	-p)
-		patch=-p ;;
-	--)
-		shift; break ;;
-	-*)
-		usage ;;
-	*)
-		break ;;
-	esac
-	shift
-done
-
-base=$1 url=$2 head=${3-HEAD} status=0 branch_name=
-
-headref=$(git symbolic-ref -q "$head")
-if git show-ref -q --verify "$headref"
-then
-	branch_name=${headref#refs/heads/}
-	if test "z$branch_name" = "z$headref" ||
-		! git config "branch.$branch_name.description" >/dev/null
-	then
-		branch_name=
-	fi
-fi
-
-tag_name=$(git describe --exact "$head^0" 2>/dev/null)
-
-test -n "$base" && test -n "$url" || usage
-
-baserev=$(git rev-parse --verify --quiet "$base"^0)
-if test -z "$baserev"
-then
-    die "fatal: Not a valid revision: $base"
-fi
-
-headrev=$(git rev-parse --verify --quiet "$head"^0)
-if test -z "$headrev"
-then
-    die "fatal: Not a valid revision: $head"
-fi
-
-merge_base=$(git merge-base $baserev $headrev) ||
-die "fatal: No commits in common between $base and $head"
-
-# $head is the token given from the command line, and $tag_name, if
-# exists, is the tag we are going to show the commit information for.
-# If that tag exists at the remote and it points at the commit, use it.
-# Otherwise, if a branch with the same name as $head exists at the remote
-# and their values match, use that instead.
-#
-# Otherwise find a random ref that matches $headrev.
-find_matching_ref='
-	sub abbr {
-		my $ref = shift;
-		if ($ref =~ s|^refs/heads/|| || $ref =~ s|^refs/tags/|tags/|) {
-			return $ref;
-		} else {
-			return $ref;
-		}
-	}
-
-	my ($tagged, $branch, $found);
-	while (<STDIN>) {
-		my ($sha1, $ref, $deref) = /^(\S+)\s+(\S+?)(\^\{\})?$/;
-		next unless ($sha1 eq $ARGV[1]);
-		$found = abbr($ref);
-		if ($deref && $ref eq "tags/$ARGV[2]") {
-			$tagged = $found;
-			last;
-		}
-		if ($ref =~ m|/\Q$ARGV[0]\E$|) {
-			$exact = $found;
-		}
-	}
-	if ($tagged) {
-		print "$tagged\n";
-	} elsif ($exact) {
-		print "$exact\n";
-	} elsif ($found) {
-		print "$found\n";
-	}
-'
-
-ref=$(git ls-remote "$url" | perl -e "$find_matching_ref" "$head" "$headrev" "$tag_name")
-
-url=$(git ls-remote --get-url "$url")
-
-git show -s --format='The following changes since commit %H:
-
-  %s (%ci)
-
-are available in the git repository at:
-' $merge_base &&
-echo "  $url${ref+ $ref}" &&
-git show -s --format='
-for you to fetch changes up to %H:
-
-  %s (%ci)
-
-----------------------------------------------------------------' $headrev &&
-
-if test -n "$branch_name"
-then
-	echo "(from the branch description for $branch_name local branch)"
-	echo
-	git config "branch.$branch_name.description"
-fi &&
-
-if test -n "$tag_name"
-then
-	if test -z "$ref" || test "$ref" != "tags/$tag_name"
-	then
-		echo >&2 "warn: You locally have $tag_name but it does not (yet)"
-		echo >&2 "warn: appear to be at $url"
-		echo >&2 "warn: Do you want to push it there, perhaps?"
-	fi
-	git cat-file tag "$tag_name" |
-	sed -n -e '1,/^$/d' -e '/^-----BEGIN PGP /q' -e p
-	echo
-fi &&
-
-if test -n "$branch_name" || test -n "$tag_name"
-then
-	echo "----------------------------------------------------------------"
-fi &&
-
-git shortlog ^$baserev $headrev &&
-git diff -M --stat --summary $patch $merge_base..$headrev || status=1
-
-if test -z "$ref"
-then
-	echo "warn: No branch of $url is at:" >&2
-	git show -s --format='warn:   %h: %s' $headrev >&2
-	echo "warn: Are you sure you pushed '$head' there?" >&2
-	status=1
-fi
-exit $status
diff --git a/ruby.c b/ruby.c
index 7f0cc9d..733215a 100644
--- a/ruby.c
+++ b/ruby.c
@@ -33,6 +33,7 @@ static void git_init(void)
 
 static const char *commands[] = {
 	"refs",
+	"request-pull",
 };
 
 static void run_ruby_command(int argc, const char **argv)
-- 
1.8.4-fc

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH/RFC 5/7] ruby: rewrite perl script
  2013-09-21 18:48 [PATCH/RFC 0/7] Support for Ruby Felipe Contreras
                   ` (3 preceding siblings ...)
  2013-09-21 18:48 ` [PATCH/RFC 4/7] ruby: rewrite 'request-pull' Felipe Contreras
@ 2013-09-21 18:48 ` Felipe Contreras
  2013-09-21 18:48 ` [PATCH/RFC 6/7] ruby: remove one fork Felipe Contreras
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Felipe Contreras @ 2013-09-21 18:48 UTC (permalink / raw)
  To: git; +Cc: Ramkumar Ramachandra, Felipe Contreras

Ruby can do it just fine, no need for perl.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 git-request-pull.rb | 66 ++++++++++++++++++++++++++---------------------------
 1 file changed, 33 insertions(+), 33 deletions(-)

diff --git a/git-request-pull.rb b/git-request-pull.rb
index b6d0156..6a96a98 100644
--- a/git-request-pull.rb
+++ b/git-request-pull.rb
@@ -67,39 +67,39 @@ die "No commits in common between #{base} and #{head}" unless $?.success?
 # and their values match, use that instead.
 #
 # Otherwise find a random ref that matches $headrev.
-find_matching_ref='
-  sub abbr {
-    my $ref = shift;
-    if ($ref =~ s|^refs/heads/|| || $ref =~ s|^refs/tags/|tags/|) {
-      return $ref;
-    } else {
-      return $ref;
-    }
-  }
-
-  my ($tagged, $branch, $found);
-  while (<STDIN>) {
-    my ($sha1, $ref, $deref) = /^(\S+)\s+(\S+?)(\^\{\})?$/;
-    next unless ($sha1 eq $ARGV[1]);
-    $found = abbr($ref);
-    if ($deref && $ref eq "tags/$ARGV[2]") {
-      $tagged = $found;
-      last;
-    }
-    if ($ref =~ m|/\Q$ARGV[0]\E$|) {
-      $exact = $found;
-    }
-  }
-  if ($tagged) {
-    print "$tagged\n";
-  } elsif ($exact) {
-    print "$exact\n";
-  } elsif ($found) {
-    print "$found\n";
-  }
-'
-
-ref = `git ls-remote "#{url}" | perl -e '#{find_matching_ref}' "#{head}" "#{headrev}" "#{tag_name}"`.chomp
+
+def abbr(ref)
+    if (ref =~ /^refs\/heads\/(.*)/ || ref =~ /^refs\/(tags\/.*)/)
+      return $1
+    end
+    return ref
+end
+
+found = tagged = exact = nil
+IO.popen(%[git ls-remote "#{url}"]) do |out|
+  out.each do |l|
+    sha1, ref, deref = l.scan(/^(\S+)\s+(\S+?)(\^\{\})?$/).first
+    next unless sha1 == headrev
+    found = abbr(ref)
+    if (deref && ref == "tags/#{tag_name}")
+      tagged = found
+      break
+    end
+    if (ref =~ /\/#{Regexp.escape(head)}$/m)
+      exact = found
+    end
+  end
+end
+
+if tagged
+  ref = tagged
+elsif exact
+  ref = exact
+else
+  ref = found
+end
+
+ref = '' if ref == nil
 url = `git ls-remote --get-url "#{url}"`.chomp
 
 begin
-- 
1.8.4-fc

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH/RFC 6/7] ruby: remove one fork
  2013-09-21 18:48 [PATCH/RFC 0/7] Support for Ruby Felipe Contreras
                   ` (4 preceding siblings ...)
  2013-09-21 18:48 ` [PATCH/RFC 5/7] ruby: rewrite perl script Felipe Contreras
@ 2013-09-21 18:48 ` Felipe Contreras
  2013-09-21 18:48 ` [PATCH/RFC 7/7] ruby: rewrite 'reset' Felipe Contreras
  2013-09-21 21:29 ` [PATCH/RFC 0/7] Support for Ruby brian m. carlson
  7 siblings, 0 replies; 26+ messages in thread
From: Felipe Contreras @ 2013-09-21 18:48 UTC (permalink / raw)
  To: git; +Cc: Ramkumar Ramachandra, Felipe Contreras

This is an example of how to start moving out of Git commands, towards
using Git's internal library.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 git-request-pull.rb |  8 +++++++-
 ruby.c              | 21 +++++++++++++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/git-request-pull.rb b/git-request-pull.rb
index 6a96a98..fc3175c 100644
--- a/git-request-pull.rb
+++ b/git-request-pull.rb
@@ -37,7 +37,13 @@ head = ARGV[2] || 'HEAD'
 status = 0
 branch_name = nil
 
-headref = `git symbolic-ref -q "#{head}"`.chomp
+def get_symbolic_ref(refname)
+  refname, sha1, flags = resolve_ref_unsafe(refname, 0)
+  return nil if (flags & REF_ISSYMREF) == 0
+  return refname
+end
+
+headref = get_symbolic_ref(head)
 
 if system(%[git show-ref -q --verify "#{headref}"])
   branch_name = headref.gsub(/^refs\/heads\//, '')
diff --git a/ruby.c b/ruby.c
index 733215a..b4e874d 100644
--- a/ruby.c
+++ b/ruby.c
@@ -26,9 +26,30 @@ static VALUE git_rb_for_each_ref(void)
 	return INT2FIX(r);
 }
 
+static VALUE git_rb_resolve_ref_unsafe(VALUE self, VALUE refname, VALUE reading)
+{
+	VALUE a = rb_ary_new2(3);
+	unsigned char sha1[20];
+	int flag;
+	const char *r;
+
+	r = resolve_ref_unsafe(RSTRING_PTR(refname), sha1, FIX2INT(reading), &flag);
+	if (!r)
+		return Qnil;
+	rb_ary_store(a, 0, rb_str_new2(r));
+	rb_ary_store(a, 1, sha1_to_str(sha1));
+	rb_ary_store(a, 2, INT2FIX(flag));
+	return a;
+}
+
 static void git_init(void)
 {
+	rb_define_global_const("REF_ISSYMREF", INT2FIX(REF_ISSYMREF));
+	rb_define_global_const("REF_ISPACKED", INT2FIX(REF_ISPACKED));
+	rb_define_global_const("REF_ISBROKEN", INT2FIX(REF_ISBROKEN));
+
 	rb_define_global_function("for_each_ref", git_rb_for_each_ref, 0);
+	rb_define_global_function("resolve_ref_unsafe", git_rb_resolve_ref_unsafe, 2);
 }
 
 static const char *commands[] = {
-- 
1.8.4-fc

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH/RFC 7/7] ruby: rewrite 'reset'
  2013-09-21 18:48 [PATCH/RFC 0/7] Support for Ruby Felipe Contreras
                   ` (5 preceding siblings ...)
  2013-09-21 18:48 ` [PATCH/RFC 6/7] ruby: remove one fork Felipe Contreras
@ 2013-09-21 18:48 ` Felipe Contreras
  2013-09-21 21:29 ` [PATCH/RFC 0/7] Support for Ruby brian m. carlson
  7 siblings, 0 replies; 26+ messages in thread
From: Felipe Contreras @ 2013-09-21 18:48 UTC (permalink / raw)
  To: git; +Cc: Ramkumar Ramachandra, Felipe Contreras

Purely for demonstration purposes.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 Makefile        |   1 +
 git-rb-setup.rb |  89 ++++++++++++
 git-reset.rb    | 223 ++++++++++++++++++++++++++++++
 git.c           |   1 -
 ruby.c          | 414 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 727 insertions(+), 1 deletion(-)
 create mode 100644 git-reset.rb

diff --git a/Makefile b/Makefile
index cb6bb4e..087b33d 100644
--- a/Makefile
+++ b/Makefile
@@ -493,6 +493,7 @@ SCRIPT_PYTHON += git-p4.py
 SCRIPT_RUBY += git-rb-setup.rb
 SCRIPT_RUBY += git-refs.rb
 SCRIPT_RUBY += git-request-pull.rb
+SCRIPT_RUBY += git-reset.rb
 
 NO_INSTALL += git-remote-testgit
 NO_INSTALL += git-remote-testpy
diff --git a/git-rb-setup.rb b/git-rb-setup.rb
index f3a2c99..a789946 100644
--- a/git-rb-setup.rb
+++ b/git-rb-setup.rb
@@ -6,10 +6,25 @@ def die(*args)
   exit 128
 end
 
+def warning(*args)
+  fmt = args.shift
+  $stderr.printf("warning: %s\n" % fmt, *args)
+end
+
+def error(*args)
+  fmt = args.shift
+  $stderr.printf("fatal: %s\n" % fmt, *args)
+  return -1
+end
+
 def sha1_to_hex(sha1)
   sha1.unpack('H*').first
 end
 
+def git_path(*path)
+  File.join(get_git_dir, *path)
+end
+
 def pager(msg)
   pager = ENV['GIT_PAGER'] || `git var GIT_PAGER`.chomp
   system("echo -n '#{msg}' | #{pager}")
@@ -34,3 +49,77 @@ def run(cmd)
   system(cmd)
   raise CommandError.new(cmd, nil) unless $?.success?
 end
+
+class SimpleParser
+  attr_writer :usage
+
+  class Option
+    attr_reader :short, :long, :values, :help
+
+    def initialize(short, long, values, help, &block)
+      @block = block
+      @short = short
+      @long = long
+      @values = values
+      @help = help
+    end
+
+    def call(v)
+      @block.call(v)
+    end
+  end
+
+  def initialize
+    @list = {}
+  end
+
+  def on(*args, &block)
+    short = args.shift if args.first.is_a?(String) or args.first == nil
+    long = args.shift if args.first.is_a?(String)
+    values = args.shift if args.first.is_a?(Array)
+    help = args.shift if args.first.is_a?(String)
+    opt = Option.new(short, long, values, help, &block)
+    @list[short] = opt if short
+    @list[long] = opt if long
+  end
+
+  def parse(args = ARGV)
+    i = 0
+    if args.member?('-h') or args.member?('--help')
+      usage
+      exit! 1
+    end
+    while cur = args[i] do
+      if cur =~ /^(-.+?)(?:=(.*))?$/
+        opt = @list[$1]
+        if opt
+          v = $2
+          if not v
+            if not opt.values
+              extra = true
+            else
+              extra = !!opt.values.map(&:to_s).member?(args[i + 1])
+            end
+            extra = false
+            v = extra ? args.delete_at(i + 1) : true
+          end
+          opt.call(v)
+          args.delete_at(i)
+          next
+        end
+      end
+      i += 1
+    end
+  end
+
+  def usage
+    puts 'usage: %s' % @usage
+    @list.values.uniq.each do |opt|
+      s = '    '
+      s << [opt.short, opt.long].compact.join(', ')
+      s << '%*s%s' % [26 - s.size, '', opt.help] if opt.help
+      puts s
+    end
+  end
+
+end
diff --git a/git-reset.rb b/git-reset.rb
new file mode 100644
index 0000000..88697c8
--- /dev/null
+++ b/git-reset.rb
@@ -0,0 +1,223 @@
+#!/usr/bin/env ruby
+
+require_relative 'git-rb-setup'
+
+$quiet = false
+$patch_mode = false
+
+def reflog_message(action, rev=nil)
+  rla = ENV['GIT_REFLOG_ACTION']
+  if rla
+    '%s: %s' % [rla, action]
+  elsif rev
+    'reset: moving to %s' % rev
+  else
+    'reset: %s' % action
+  end
+end
+
+def update_refs(rev, sha1)
+  sha1_old_orig = get_sha1('ORIG_HEAD')
+  old_orig = sha1_old_orig if sha1_old_orig
+  sha1_orig = get_sha1('HEAD')
+  if sha1_orig
+    orig = sha1_orig
+    msg = reflog_message('updating ORIG_HEAD')
+    update_ref(msg, 'ORIG_HEAD', orig, old_orig, 0, MSG_ON_ERR)
+  elsif old_orig
+    delete_ref('ORIG_HEAD', old_orig, 0)
+  end
+  msg = reflog_message('updating HEAD', rev)
+  return update_ref(msg, 'HEAD', sha1, orig, 0, MSG_ON_ERR)
+end
+
+def is_merge
+  return test('e', git_path('MERGE_HEAD'))
+end
+
+def parse_args(args)
+  rev = 'HEAD'
+  if args[0]
+    if args[0] == '--'
+      args.shift
+    elsif args[1] == '--'
+      rev = args.shift
+      args.shift
+    elsif (!args[1] && get_sha1_committish(args[0])) || (args[1] && get_sha1_treeish(args[0]))
+      verify_non_filename($prefix, args[0])
+      rev = args.shift
+    else
+      verify_filename($prefix, args[0], 1)
+    end
+  end
+  pathspec = args[0] ? get_pathspec($prefix, args) : []
+  return [rev, pathspec]
+end
+
+def reset_index(sha1, reset_type)
+  read_cache_unmerged
+  opts = {}
+
+  case reset_type
+  when :merge, :keep
+    opts[:update] = true
+  when :hard
+    opts[:update] = true
+    opts[:reset] = true
+  else
+    opts[:reset] = true
+  end
+
+  opts[:verobse] = true unless $quiet
+
+  if reset_type == :keep
+    head_sha1 = get_sha1('HEAD')
+    return error('You do not have a valid HEAD.') unless head_sha1
+    opts[:head] = head_sha1
+  end
+
+  if unpack_trees(sha1, opts) != 0
+    return -1
+  end
+
+  if reset_type == :hard || reset_type == :mixed
+    tree = parse_tree_indirect(sha1);
+    prime_cache_tree(nil, tree);
+  end
+
+  return 0
+end
+
+def print_new_head_line(commit)
+  hex = find_unique_abbrev(commit.sha1, DEFAULT_ABBREV)
+  print('HEAD is now at %s' % hex)
+	msg = logmsg_reencode(commit, get_log_output_encoding());
+  _, body = msg.split("\n\n", 2)
+  if body
+    puts [' ', body.lines.first].join
+  else
+    puts
+  end
+end
+
+def cmd(*args)
+  args.shift
+
+  reset_type = :none
+
+  opts = SimpleParser.new
+  opts.usage = 'git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]'
+
+  opts.on('-q', '--quiet', '') do |v|
+    $quiet = true
+  end
+
+  opts.on(nil, '--hard', 'reset HEAD, index and working tree') do |v|
+    reset_type = :hard
+  end
+
+  opts.on(nil, '--soft', 'reset only HEAD') do |v|
+    reset_type = :soft
+  end
+
+  opts.on(nil, '--mixed', 'reset HEAD and index') do |v|
+    reset_type = :mixed
+  end
+
+  opts.on(nil, '--merge', '') do |v|
+    reset_type = :merge
+  end
+
+  opts.on(nil, '--keep', '') do |v|
+    reset_type = :keep
+  end
+
+  opts.on('-p', '--patch', '') do |v|
+    $patch_mode = true
+  end
+
+  $prefix = setup_git_directory
+  git_config
+
+  opts.parse(args)
+  rev, pathspec = parse_args(args)
+
+  unborn = rev == 'HEAD' && !get_sha1('HEAD')
+  if unborn
+    sha1 = EMPTY_TREE_SHA1_BIN
+  elsif pathspec.empty?
+    sha1 = get_sha1_committish(rev)
+    die("Failed to resolve '%s' as a valid revision." % rev) unless sha1
+    commit = lookup_commit_reference(sha1)
+    die("Could not parse object '%s'." % rev) unless commit
+    sha1 = commit.sha1
+  else
+    sha1 = get_sha1_treeish(rev)
+    die("Failed to resolve '%s' as a valid tree." % rev) unless sha1
+    tree = parse_tree_indirect(sha1)
+    die("Could not parse object '%s'.", rev) unless tree
+    sha1 = tree.sha1
+  end
+
+  if $patch_mode
+    args = []
+    args << 'add--interactive'
+    args << '--patch=reset'
+    args << sha1_to_hex(sha1)
+    args << '--'
+    args += pathspec
+    return run_command(args, RUN_GIT_CMD);
+  end
+
+  if not pathspec.empty?
+    if reset_type == :mixed
+      warning("--mixed with paths is deprecated; use 'git reset -- <paths>' instead.")
+    elsif reset_type != :none
+      die('Cannot do %s reset with paths.' % reset_type.to_s)
+    end
+  end
+
+  reset_type = :mixed if reset_type == :none
+
+  if reset_type != :soft && reset_type != :mixed
+    setup_work_tree
+  end
+
+  if reset_type == :mixed && is_bare_repository
+    die('%s reset is not allowed in a bare repository' % reset_type.to_s);
+  end
+
+  if reset_type == :soft || reset_type == :keep
+    if is_merge || read_cache < 0 || unmerged_cache != 0
+      die('Cannot do a %s reset in the middle of a merge.' % reset_type.to_s)
+    end
+  end
+
+  if reset_type != :soft
+    do_locked_index(1) do |f|
+      if reset_type == :mixed
+        r = read_from_tree(pathspec, sha1)
+        return 1 if not r
+        flags = $quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN
+        refresh_index(flags, nil, 'Unstaged changes after reset:')
+      else
+        err = reset_index(sha1, reset_type)
+        err = reset_index(sha1, :mixed) if reset_type == :keep && err == 0
+        die("Could not reset index file to revision '%s'." % rev) if err != 0
+      end
+      write_cache(f)
+    end || die('Could not write new index file.')
+  end
+
+  status = 0
+  if pathspec.empty? && !unborn
+    status = update_refs(rev, sha1)
+    if reset_type == :hard && status == 0 && !$quiet
+      print_new_head_line(lookup_commit_reference(sha1))
+    end
+  end
+  remove_branch_state if pathspec.empty?
+  return status
+end
+
+exit cmd(*ARGV)
diff --git a/git.c b/git.c
index 0e1d97d..777a34a 100644
--- a/git.c
+++ b/git.c
@@ -399,7 +399,6 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "replace", cmd_replace, RUN_SETUP },
 		{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
 		{ "rerere", cmd_rerere, RUN_SETUP },
-		{ "reset", cmd_reset, RUN_SETUP },
 		{ "rev-list", cmd_rev_list, RUN_SETUP },
 		{ "rev-parse", cmd_rev_parse },
 		{ "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
diff --git a/ruby.c b/ruby.c
index b4e874d..b3be386 100644
--- a/ruby.c
+++ b/ruby.c
@@ -1,17 +1,40 @@
 #include "cache.h"
 #include "exec_cmd.h"
 #include "refs.h"
+#include "commit.h"
+#include "tree-walk.h"
+#include "unpack-trees.h"
+#include "diff.h"
+#include "diffcore.h"
+#include "branch.h"
+#include "run-command.h"
+#include "cache-tree.h"
 
 #undef NORETURN
 #undef PATH_SEP
 
 #include <ruby.h>
 
+static VALUE git_rb_commit;
+static VALUE git_rb_tree;
+
 static inline VALUE sha1_to_str(const unsigned char *sha1)
 {
 	return rb_str_new((const char *)sha1, 20);
 }
 
+static inline char *str_to_cstr(VALUE str)
+{
+	if (str == Qnil)
+		return NULL;
+	return RSTRING_PTR(str);
+}
+
+static inline unsigned char *str_to_sha1(VALUE str)
+{
+	return (unsigned char *)str_to_cstr(str);
+}
+
 static int for_each_ref_fn(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
 {
 	VALUE r;
@@ -42,19 +65,410 @@ static VALUE git_rb_resolve_ref_unsafe(VALUE self, VALUE refname, VALUE reading)
 	return a;
 }
 
+static VALUE git_rb_get_sha1(VALUE self, VALUE name)
+{
+	unsigned char buf[20];
+	int r;
+	r = get_sha1(RSTRING_PTR(name), buf);
+	if (r)
+		return Qnil;
+	return sha1_to_str(buf);
+}
+
+static VALUE git_rb_setup_git_directory(VALUE self)
+{
+	const char *prefix;
+	prefix = setup_git_directory();
+	if (!prefix)
+		return Qnil;
+	return rb_str_new2(prefix);
+}
+
+static VALUE git_rb_setup_work_tree(VALUE self)
+{
+	setup_work_tree();
+	return Qnil;
+}
+
+static VALUE git_rb_is_bare_repository(VALUE self)
+{
+	return is_bare_repository() ? Qtrue : Qfalse;
+}
+
+static VALUE git_rb_get_sha1_committish(VALUE self, VALUE str)
+{
+	unsigned char buf[20];
+	if (get_sha1_committish(RSTRING_PTR(str), buf))
+		return Qnil;
+	return sha1_to_str(buf);
+}
+
+static VALUE git_rb_get_sha1_treeish(VALUE self, VALUE str)
+{
+	unsigned char buf[20];
+	if (get_sha1_treeish(RSTRING_PTR(str), buf))
+		return Qnil;
+	return sha1_to_str(buf);
+}
+
+static VALUE git_rb_lookup_commit_reference(VALUE self, VALUE id)
+{
+	struct commit *commit;
+	commit = lookup_commit_reference(str_to_sha1(id));
+	if (!commit)
+		return Qnil;
+	return Data_Wrap_Struct(git_rb_commit, NULL, NULL, commit);
+}
+
+static VALUE git_rb_commit_sha1(VALUE self)
+{
+	struct commit *commit;
+	Data_Get_Struct(self, struct commit, commit);
+	return sha1_to_str(commit->object.sha1);
+}
+
+static VALUE git_rb_commit_buffer(VALUE self)
+{
+	struct commit *commit;
+	Data_Get_Struct(self, struct commit, commit);
+	return rb_str_new2(commit->buffer);
+}
+
+static VALUE git_rb_parse_tree_indirect(VALUE self, VALUE id)
+{
+	struct tree *tree;
+	tree = parse_tree_indirect(str_to_sha1(id));
+	if (!tree)
+		return Qnil;
+	return Data_Wrap_Struct(git_rb_tree, NULL, NULL, tree);
+}
+
+static VALUE git_rb_tree_sha1(VALUE self)
+{
+	struct tree *tree;
+	Data_Get_Struct(self, struct tree, tree);
+	return sha1_to_str(tree->object.sha1);
+}
+
+static VALUE git_rb_unpack_trees(VALUE self, VALUE sha1, VALUE uopts)
+{
+	struct tree_desc desc[2];
+	struct unpack_trees_options opts;
+	int r;
+	int nr = 1;
+	VALUE head;
+
+	memset(&opts, 0, sizeof(opts));
+
+	opts.head_idx = 1;
+	opts.src_index = &the_index;
+	opts.dst_index = &the_index;
+	opts.fn = oneway_merge;
+	opts.merge = 1;
+
+	if (rb_hash_lookup(uopts, ID2SYM(rb_intern("update"))) == Qtrue)
+		opts.update = 1;
+	if (rb_hash_lookup(uopts, ID2SYM(rb_intern("reset"))) == Qtrue)
+		opts.reset = 1;
+	if (rb_hash_lookup(uopts, ID2SYM(rb_intern("verbose"))) == Qtrue)
+		opts.verbose_update = 1;
+
+	head = rb_hash_lookup(uopts, ID2SYM(rb_intern("head")));
+	if (head != Qnil) {
+		fill_tree_descriptor(desc, str_to_sha1(head));
+		opts.fn = twoway_merge;
+		nr++;
+	}
+
+	fill_tree_descriptor(desc + nr - 1, str_to_sha1(sha1));
+	r = unpack_trees(nr, desc, &opts);
+	return INT2NUM(r);
+}
+
+static VALUE git_rb_read_cache_unmerged(VALUE self)
+{
+	read_cache_unmerged();
+	return Qnil;
+}
+
+static VALUE git_rb_read_cache(VALUE self)
+{
+	int r;
+	r = read_cache();
+	return INT2NUM(r);
+}
+
+static VALUE git_rb_unmerged_cache(VALUE self)
+{
+	int r;
+	r = unmerged_cache();
+	return INT2NUM(r);
+}
+
+static void update_index_from_diff(struct diff_queue_struct *q,
+		struct diff_options *opt, void *data)
+{
+	int i;
+
+	for (i = 0; i < q->nr; i++) {
+		struct diff_filespec *one = q->queue[i]->one;
+		if (one->mode && !is_null_sha1(one->sha1)) {
+			struct cache_entry *ce;
+			ce = make_cache_entry(one->mode, one->sha1, one->path,
+				0, 0);
+			if (!ce)
+				die(_("make_cache_entry failed for path '%s'"),
+				    one->path);
+			add_cache_entry(ce, ADD_CACHE_OK_TO_ADD |
+				ADD_CACHE_OK_TO_REPLACE);
+		} else
+			remove_file_from_cache(one->path);
+	}
+}
+
+static VALUE git_rb_read_from_tree(VALUE self, VALUE paths, VALUE tree_sha1)
+{
+	struct diff_options opt;
+	const char **pathspec = NULL;
+
+	if (paths != Qnil && RARRAY_LEN(paths) > 0) {
+		int i;
+		VALUE *cpaths = RARRAY_PTR(paths);
+		pathspec = xcalloc(RARRAY_LEN(paths) + 1, sizeof(*pathspec));
+		for (i = 0; i < RARRAY_LEN(paths); i++)
+			pathspec[i] = RSTRING_PTR(cpaths[i]);
+		pathspec[i] = NULL;
+	}
+
+	memset(&opt, 0, sizeof(opt));
+	diff_tree_setup_paths(pathspec, &opt);
+	opt.output_format = DIFF_FORMAT_CALLBACK;
+	opt.format_callback = update_index_from_diff;
+
+	read_cache();
+	if (do_diff_cache(str_to_sha1(tree_sha1), &opt))
+		return Qfalse;
+	diffcore_std(&opt);
+	diff_flush(&opt);
+	diff_tree_release_paths(&opt);
+
+	return Qtrue;
+}
+
+static VALUE git_rb_refresh_index(VALUE self, VALUE flags, VALUE seen, VALUE header_msg)
+{
+	int r;
+	r = refresh_index(&the_index, FIX2INT(flags), NULL, NULL, str_to_cstr(header_msg));
+	return INT2NUM(r);
+}
+
+static VALUE git_rb_update_ref(VALUE self, VALUE action, VALUE refname, VALUE sha1, VALUE oldval, VALUE flags, VALUE onerr)
+{
+	int r;
+	r = update_ref(RSTRING_PTR(action), RSTRING_PTR(refname), str_to_sha1(sha1), str_to_sha1(oldval),
+			NUM2INT(flags), FIX2INT(onerr));
+	return INT2NUM(r);
+}
+
+static VALUE git_rb_delete_ref(VALUE self, VALUE refname, VALUE sha1, VALUE delopt)
+{
+	int r;
+	r = delete_ref(RSTRING_PTR(refname), str_to_sha1(sha1), NUM2INT(delopt));
+	return INT2NUM(r);
+}
+
+static VALUE git_rb_remove_branch_state(VALUE self)
+{
+	remove_branch_state();
+	return Qnil;
+}
+
+static VALUE git_rb_write_cache(VALUE self, VALUE fd)
+{
+	int r;
+	r = write_index(&the_index, NUM2INT(fd));
+	return INT2NUM(r);
+}
+
+static VALUE git_rb_get_index_file(VALUE self)
+{
+	char *file;
+	file = get_index_file();
+	return rb_str_new2(file);
+}
+
+static VALUE git_rb_do_locked_index(VALUE self, VALUE die_on_error)
+{
+	struct lock_file *lock = xcalloc(1, sizeof(*lock));
+	int fd, cr;
+	VALUE r;
+
+	fd = hold_locked_index(lock, NUM2INT(die_on_error));
+	r = rb_yield(INT2NUM(fd));
+	cr = NUM2INT(r);
+	if (cr == 0)
+		cr = commit_locked_index(lock);
+	return cr == 0 ? Qtrue : Qfalse;
+}
+
+static VALUE git_rb_verify_filename(VALUE self, VALUE prefix, VALUE arg, VALUE diagnose_misspelt_rev)
+{
+	verify_filename(str_to_cstr(prefix), str_to_cstr(arg), NUM2INT(diagnose_misspelt_rev));
+	return Qnil;
+}
+
+static VALUE git_rb_verify_non_filename(VALUE self, VALUE prefix, VALUE arg)
+{
+	verify_non_filename(str_to_cstr(prefix), str_to_cstr(arg));
+	return Qnil;
+}
+
+static VALUE git_rb_git_config(VALUE self)
+{
+	git_config(git_default_config, NULL);
+	return Qnil;
+}
+
+static VALUE git_rb_run_command(VALUE self, VALUE args, VALUE opt)
+{
+	const char **argv;
+	int i, r;
+	VALUE *cargs;
+
+	cargs = RARRAY_PTR(args);
+	argv = xcalloc(RARRAY_LEN(args) + 1, sizeof(*argv));
+	for (i = 0; i < RARRAY_LEN(args); i++)
+		argv[i] = RSTRING_PTR(cargs[i]);
+	argv[i] = NULL;
+
+	r = run_command_v_opt(argv, FIX2INT(opt));
+	return INT2NUM(r);
+}
+
+static VALUE git_rb_prime_cache_tree(VALUE self, VALUE cache, VALUE rtree)
+{
+	struct tree *tree;
+	Data_Get_Struct(rtree, struct tree, tree);
+	prime_cache_tree(&active_cache_tree, tree);
+	return Qnil;
+}
+
+static VALUE git_rb_get_pathspec(VALUE self, VALUE prefix, VALUE pathspec)
+{
+	const char **dst, **src;
+	VALUE *rsrc, *rdst;
+	int i, c;
+
+	c = RARRAY_LEN(pathspec);
+	rsrc = RARRAY_PTR(pathspec);
+
+	src = xcalloc(c + 1, sizeof(*src));
+	for (i = 0; i < c; i++)
+		src[i] = RSTRING_PTR(rsrc[i]);
+	src[i] = NULL;
+
+	dst = get_pathspec(str_to_cstr(prefix), src);
+
+	rdst = xcalloc(c, sizeof(*rdst));
+	for (i = 0; i < c; i++)
+		rdst[i] = rb_str_new2(dst[i]);
+
+	return rb_ary_new4(c, rdst);
+}
+
+static VALUE git_rb_get_git_dir(VALUE self)
+{
+	return rb_str_new2(get_git_dir());
+}
+
+static VALUE git_rb_find_unique_abbrev(VALUE self, VALUE sha1, VALUE len)
+{
+	const char *abbrev;
+	abbrev = find_unique_abbrev(str_to_sha1(sha1), NUM2INT(len));
+	return rb_str_new2(abbrev);
+}
+
+static VALUE git_rb_get_log_output_encoding(VALUE self)
+{
+	return rb_str_new2(get_log_output_encoding());
+}
+
+static VALUE git_rb_logmsg_reencode(VALUE self, VALUE commit, VALUE output_encoding)
+{
+	struct commit *g_commit;
+	char *str;
+
+	Data_Get_Struct(commit, struct commit, g_commit);
+	str = logmsg_reencode(g_commit, NULL, RSTRING_PTR(output_encoding));
+	return rb_str_new2(str);
+}
+
 static void git_init(void)
 {
+	VALUE mod, tmp;
+
+	mod = rb_define_module("Git");
+
 	rb_define_global_const("REF_ISSYMREF", INT2FIX(REF_ISSYMREF));
 	rb_define_global_const("REF_ISPACKED", INT2FIX(REF_ISPACKED));
 	rb_define_global_const("REF_ISBROKEN", INT2FIX(REF_ISBROKEN));
 
+	rb_define_global_const("MSG_ON_ERR", INT2FIX(MSG_ON_ERR));
+	rb_define_global_const("REFRESH_QUIET", INT2FIX(REFRESH_QUIET));
+	rb_define_global_const("REFRESH_IN_PORCELAIN", INT2FIX(REFRESH_IN_PORCELAIN));
+	rb_define_global_const("RUN_GIT_CMD", INT2FIX(RUN_GIT_CMD));
+	rb_define_global_const("DEFAULT_ABBREV", INT2FIX(DEFAULT_ABBREV));
+
+	tmp = rb_obj_freeze(rb_str_new((const char *)EMPTY_TREE_SHA1_BIN, 20));
+	rb_define_global_const("EMPTY_TREE_SHA1_BIN", tmp);
+
+	git_rb_commit = rb_define_class_under(mod, "Commit", rb_cData);
+	rb_define_method(git_rb_commit, "sha1", git_rb_commit_sha1, 0);
+	rb_define_method(git_rb_commit, "buffer", git_rb_commit_buffer, 0);
+
+	git_rb_tree = rb_define_class_under(mod, "Tree", rb_cData);
+	rb_define_method(git_rb_tree, "sha1", git_rb_tree_sha1, 0);
+
 	rb_define_global_function("for_each_ref", git_rb_for_each_ref, 0);
 	rb_define_global_function("resolve_ref_unsafe", git_rb_resolve_ref_unsafe, 2);
+
+	rb_define_global_function("get_sha1", git_rb_get_sha1, 1);
+	rb_define_global_function("setup_git_directory", git_rb_setup_git_directory, 0);
+	rb_define_global_function("setup_work_tree", git_rb_setup_work_tree, 0);
+	rb_define_global_function("is_bare_repository", git_rb_is_bare_repository, 0);
+	rb_define_global_function("get_sha1_committish", git_rb_get_sha1_committish, 1);
+	rb_define_global_function("get_sha1_treeish", git_rb_get_sha1_treeish, 1);
+	rb_define_global_function("lookup_commit_reference", git_rb_lookup_commit_reference, 1);
+	rb_define_global_function("parse_tree_indirect", git_rb_parse_tree_indirect, 1);
+
+	rb_define_global_function("read_cache_unmerged", git_rb_read_cache_unmerged, 0);
+	rb_define_global_function("unpack_trees", git_rb_unpack_trees, 2);
+	rb_define_global_function("read_cache", git_rb_read_cache, 0);
+	rb_define_global_function("unmerged_cache", git_rb_unmerged_cache, 0);
+	rb_define_global_function("read_from_tree", git_rb_read_from_tree, 2);
+	rb_define_global_function("update_ref", git_rb_update_ref, 6);
+	rb_define_global_function("delete_ref", git_rb_delete_ref, 3);
+	rb_define_global_function("remove_branch_state", git_rb_remove_branch_state, 0);
+	rb_define_global_function("write_cache", git_rb_write_cache, 1);
+	rb_define_global_function("get_index_file", git_rb_get_index_file, 0);
+	rb_define_global_function("do_locked_index", git_rb_do_locked_index, 1);
+	rb_define_global_function("refresh_index", git_rb_refresh_index, 3);
+	rb_define_global_function("verify_filename", git_rb_verify_filename, 3);
+	rb_define_global_function("verify_non_filename", git_rb_verify_non_filename, 2);
+	rb_define_global_function("git_config", git_rb_git_config, 0);
+	rb_define_global_function("run_command", git_rb_run_command, 2);
+	rb_define_global_function("prime_cache_tree", git_rb_prime_cache_tree, 2);
+	rb_define_global_function("get_pathspec", git_rb_get_pathspec, 2);
+	rb_define_global_function("get_git_dir", git_rb_get_git_dir, 0);
+	rb_define_global_function("find_unique_abbrev", git_rb_find_unique_abbrev, 2);
+	rb_define_global_function("get_log_output_encoding", git_rb_get_log_output_encoding, 0);
+	rb_define_global_function("logmsg_reencode", git_rb_logmsg_reencode, 2);
 }
 
 static const char *commands[] = {
 	"refs",
 	"request-pull",
+	"reset",
 };
 
 static void run_ruby_command(int argc, const char **argv)
-- 
1.8.4-fc

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-21 18:48 [PATCH/RFC 0/7] Support for Ruby Felipe Contreras
                   ` (6 preceding siblings ...)
  2013-09-21 18:48 ` [PATCH/RFC 7/7] ruby: rewrite 'reset' Felipe Contreras
@ 2013-09-21 21:29 ` brian m. carlson
  2013-09-21 22:52   ` Felipe Contreras
  7 siblings, 1 reply; 26+ messages in thread
From: brian m. carlson @ 2013-09-21 21:29 UTC (permalink / raw)
  To: Felipe Contreras; +Cc: git, Ramkumar Ramachandra

[-- Attachment #1: Type: text/plain, Size: 2215 bytes --]

On Sat, Sep 21, 2013 at 01:48:08PM -0500, Felipe Contreras wrote:
> Hi,
> 
> It was discussed before that there was a need to replace Git scripts
> from perl and sh that utilize the 'git' binary to do everything they
> need, which requires many forks, and that creates problems on
> platforms like Windows.
> 
> This is a first step meant to show how a solution using Ruby would look like.
> 
> Other alternatives just don't cut it. Shell scripts are too simple, and
> invariably require forks. Perl could use Git's internal C code, but it's syntax
> is too cumbersome and it's loosing more and more popularity. Python and Ruby
> are the only modern languages that could fit all the needs, but Python's syntax
> is not ideal, specially considering the background of the Git community, and
> also, Ruby's C extensibility is simply superb.
> 
> This patch series introduces Ruby bindings for Git's C internal library, and
> add example commands to show how it could be used, and how it resembles the
> original C code, shell code, and perl code. Basically, Ruby fits like a glove.

A couple of things: first, I'm not opposed in principle to using Ruby
for git.  As you say, it's a good language and it has much nicer C
bindings.

As Junio has also pointed out in the past, there are people who aren't
able to use Ruby in the same way that they are Perl and Python.  If it's
announced now, Git 2.0 might be a good time to start accepting Ruby
scripts, as that will give people time to plan for its inclusion.

On a more technical note, my objection to your binding implementation is
that fundamentally, Ruby is an object-oriented language, but your
bindings don't take advantage of that; they're completely procedural.  I
realize most of the git codebase is as well, but that's because it's
written in C.  It seems a shame not to take advantage of what the
language offers, especially since I know others are going to want to
take advantage of the provided bindings.

-- 
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-21 21:29 ` [PATCH/RFC 0/7] Support for Ruby brian m. carlson
@ 2013-09-21 22:52   ` Felipe Contreras
  2013-09-21 23:56     ` brian m. carlson
  0 siblings, 1 reply; 26+ messages in thread
From: Felipe Contreras @ 2013-09-21 22:52 UTC (permalink / raw)
  To: brian m. carlson; +Cc: git, Ramkumar Ramachandra

On Sat, Sep 21, 2013 at 4:29 PM, brian m. carlson
<sandals@crustytoothpaste.net> wrote:
> On Sat, Sep 21, 2013 at 01:48:08PM -0500, Felipe Contreras wrote:
>> Hi,
>>
>> It was discussed before that there was a need to replace Git scripts
>> from perl and sh that utilize the 'git' binary to do everything they
>> need, which requires many forks, and that creates problems on
>> platforms like Windows.
>>
>> This is a first step meant to show how a solution using Ruby would look like.
>>
>> Other alternatives just don't cut it. Shell scripts are too simple, and
>> invariably require forks. Perl could use Git's internal C code, but it's syntax
>> is too cumbersome and it's loosing more and more popularity. Python and Ruby
>> are the only modern languages that could fit all the needs, but Python's syntax
>> is not ideal, specially considering the background of the Git community, and
>> also, Ruby's C extensibility is simply superb.
>>
>> This patch series introduces Ruby bindings for Git's C internal library, and
>> add example commands to show how it could be used, and how it resembles the
>> original C code, shell code, and perl code. Basically, Ruby fits like a glove.
>
> A couple of things: first, I'm not opposed in principle to using Ruby
> for git.  As you say, it's a good language and it has much nicer C
> bindings.
>
> As Junio has also pointed out in the past, there are people who aren't
> able to use Ruby in the same way that they are Perl and Python.  If it's
> announced now, Git 2.0 might be a good time to start accepting Ruby
> scripts, as that will give people time to plan for its inclusion.

Yes, and there are people who aren't able to use Perl/Python in the
same way they use Ruby. That's why I tried to show why Ruby makes a
perfect choice.

> On a more technical note, my objection to your binding implementation is
> that fundamentally, Ruby is an object-oriented language, but your
> bindings don't take advantage of that; they're completely procedural.  I
> realize most of the git codebase is as well, but that's because it's
> written in C.  It seems a shame not to take advantage of what the
> language offers, especially since I know others are going to want to
> take advantage of the provided bindings.

For the moment the bindings are only for Git commands, so the primary
users are Git developers, that's why I tried to leave them close to
the current C/shell/perl code.

Having said that, it does use a little bit of object-oriented stuff:

  commit = lookup_commit_reference(sha1)
  p commit.buffer

Now, if anybody has ideas into how the bindings could be more object
oriented, I'm all ears, but unfortunately what I foresee is that
nobody will consider this proposal seriously.

Cheers.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-21 22:52   ` Felipe Contreras
@ 2013-09-21 23:56     ` brian m. carlson
  2013-09-22  5:36       ` Felipe Contreras
                         ` (2 more replies)
  0 siblings, 3 replies; 26+ messages in thread
From: brian m. carlson @ 2013-09-21 23:56 UTC (permalink / raw)
  To: Felipe Contreras; +Cc: git, Ramkumar Ramachandra

[-- Attachment #1: Type: text/plain, Size: 2574 bytes --]

On Sat, Sep 21, 2013 at 05:52:05PM -0500, Felipe Contreras wrote:
> On Sat, Sep 21, 2013 at 4:29 PM, brian m. carlson
> <sandals@crustytoothpaste.net> wrote:
> > As Junio has also pointed out in the past, there are people who aren't
> > able to use Ruby in the same way that they are Perl and Python.  If it's
> > announced now, Git 2.0 might be a good time to start accepting Ruby
> > scripts, as that will give people time to plan for its inclusion.
> 
> Yes, and there are people who aren't able to use Perl/Python in the
> same way they use Ruby. That's why I tried to show why Ruby makes a
> perfect choice.

I'm not arguing against Ruby.  As I said, it's a nice language.  I'm
just saying that Ruby is not as common as Perl and Python.  For example,
in Debian, Perl is Essential (cannot be removed), Python is priority
standard, and Ruby is priority optional.

I think it's a bad idea to introduce an entirely new runtime, especially
one known to occasionally blow up on less-common architectures, without
some advance notice.  For example, at work I would not be able to deploy
a git using Ruby immediately because Git is an RPM and Ruby is compiled
from source, if it is even present at all.

Also, the only Python script that is shipped with Git is git-p4, which
is essentially optional, since most git users probably do not use
Perforce.  Otherwise, all the scripts in git are shell or Perl.  So this
would be adding a significant additional dependency to core git, one
which is likely not installed on many systems.  Of the systems in the
Debian popularity contest, 41% have git installed and 23% have ruby1.8
installed, with only 16% having the default ruby installed.

> Now, if anybody has ideas into how the bindings could be more object
> oriented, I'm all ears, but unfortunately what I foresee is that
> nobody will consider this proposal seriously.

My concern is that the Ruby code will end up not being idiomatic, and
people will view it as bizarre and unmaintainable.

for_each_ref could end up being something like REPOSITORY.refs.each,
which would be more idiomatic.  repository.refs would probably be an
Enumerator in that case.  If the decision is made to incorporate Ruby
code, I'm happy to submit some patches to help provide a sane interface,
even though I'm not that familiar with Ruby.

-- 
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-21 23:56     ` brian m. carlson
@ 2013-09-22  5:36       ` Felipe Contreras
  2013-09-22  7:31         ` Fredrik Gustafsson
  2013-09-23  0:00       ` Junio C Hamano
  2013-09-28 23:06       ` Felipe Contreras
  2 siblings, 1 reply; 26+ messages in thread
From: Felipe Contreras @ 2013-09-22  5:36 UTC (permalink / raw)
  To: brian m. carlson, Felipe Contreras; +Cc: git, Ramkumar Ramachandra

brian m. carlson wrote:
> On Sat, Sep 21, 2013 at 05:52:05PM -0500, Felipe Contreras wrote:
> > On Sat, Sep 21, 2013 at 4:29 PM, brian m. carlson
> > <sandals@crustytoothpaste.net> wrote:
> > > As Junio has also pointed out in the past, there are people who aren't
> > > able to use Ruby in the same way that they are Perl and Python.  If it's
> > > announced now, Git 2.0 might be a good time to start accepting Ruby
> > > scripts, as that will give people time to plan for its inclusion.
> > 
> > Yes, and there are people who aren't able to use Perl/Python in the
> > same way they use Ruby. That's why I tried to show why Ruby makes a
> > perfect choice.
> 
> I'm not arguing against Ruby.  As I said, it's a nice language.  I'm
> just saying that Ruby is not as common as Perl and Python.

In my books Perl is only a tiny bit more common than Ruby.

http://www.tiobe.com/content/paperinfo/tpci/index.html

> I think it's a bad idea to introduce an entirely new runtime, especially
> one known to occasionally blow up on less-common architectures, without
> some advance notice.

This is just FUD. What do you mean blow up on less-common architectures? Do you
have actual evidence or can we just dismiss that as a baseless argument?

> For example, at work I would not be able to deploy a git using Ruby
> immediately because Git is an RPM and Ruby is compiled from source, if it is
> even present at all.

Again, what do you mean? In all the distributions I've seen, vim is compiled
with Ruby support by default, so unless you think vim is an essoteric package,
libruby is almost definetly packaged and available.

> Also, the only Python script that is shipped with Git is git-p4, which
> is essentially optional, since most git users probably do not use
> Perforce. Otherwise, all the scripts in git are shell or Perl.

Neither perl, nor shell, nor python scripts solve the forking problem. My
proposal does.

> So this would be adding a significant additional dependency to core git, one
> which is likely not installed on many systems.

Another claim without a shred of evidence. It's the other way around, it's
likely already installed, and it would not be an additional dependency if the
current scripts get phased out in favor Ruby ones, or even better, C code.

> Of the systems in the Debian popularity contest, 41% have git installed and
> 23% have ruby1.8 installed, with only 16% having the default ruby installed.

Plus the 17% of ruby1.9.1, you get 41%, exactly the same as Git.

But we don't need ruby, all we need is libruby, which is 47%.

> > Now, if anybody has ideas into how the bindings could be more object
> > oriented, I'm all ears, but unfortunately what I foresee is that
> > nobody will consider this proposal seriously.
> 
> My concern is that the Ruby code will end up not being idiomatic, and
> people will view it as bizarre and unmaintainable.

There is no such thing as idiomatic Ruby code. In Ruby there's no single best
way to do something, there's many ways to do the same thing.

> for_each_ref could end up being something like REPOSITORY.refs.each,
> which would be more idiomatic.

And how do you propose to achieve that if the C code doesn't support that?

Do you have in mind the C code that would achieve that, or are you just saying?

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-22  5:36       ` Felipe Contreras
@ 2013-09-22  7:31         ` Fredrik Gustafsson
  2013-09-22  7:43           ` Felipe Contreras
  0 siblings, 1 reply; 26+ messages in thread
From: Fredrik Gustafsson @ 2013-09-22  7:31 UTC (permalink / raw)
  To: Felipe Contreras; +Cc: brian m. carlson, git, Ramkumar Ramachandra

On Sun, Sep 22, 2013 at 12:36:51AM -0500, Felipe Contreras wrote:
> > I think it's a bad idea to introduce an entirely new runtime, especially
> > one known to occasionally blow up on less-common architectures, without
> > some advance notice.
> 
> This is just FUD. What do you mean blow up on less-common architectures? Do you
> have actual evidence or can we just dismiss that as a baseless argument?
> 
> > For example, at work I would not be able to deploy a git using Ruby
> > immediately because Git is an RPM and Ruby is compiled from source, if it is
> > even present at all.
> 
> Again, what do you mean? In all the distributions I've seen, vim is compiled
> with Ruby support by default, so unless you think vim is an essoteric package,
> libruby is almost definetly packaged and available.

It would actually be usefull to know stats on where git is runned. In my
world of embedded computing, ruby support definitely isn't a standard,
nor is glibc.

As for architecture speaking I think it's important that git works on
ARM since that architecture increases on the server market. I've no idea
if this is a problem with ruby or not.

> 
> > Also, the only Python script that is shipped with Git is git-p4, which
> > is essentially optional, since most git users probably do not use
> > Perforce. Otherwise, all the scripts in git are shell or Perl.
> 
> Neither perl, nor shell, nor python scripts solve the forking problem. My
> proposal does.

It does, and so does Lua, which can be bundled with git and used in the
configuration files as well and is pure ansi C. However bundling
something has it bad sides too. At least this will solve the dependency
problem. So let the language war begin =).

-- 
Med vänliga hälsningar
Fredrik Gustafsson

tel: 0733-608274
e-post: iveqy@iveqy.com

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-22  7:31         ` Fredrik Gustafsson
@ 2013-09-22  7:43           ` Felipe Contreras
  2013-09-22  8:12             ` Fredrik Gustafsson
  0 siblings, 1 reply; 26+ messages in thread
From: Felipe Contreras @ 2013-09-22  7:43 UTC (permalink / raw)
  To: Fredrik Gustafsson; +Cc: brian m. carlson, git, Ramkumar Ramachandra

On Sun, Sep 22, 2013 at 2:31 AM, Fredrik Gustafsson <iveqy@iveqy.com> wrote:
> On Sun, Sep 22, 2013 at 12:36:51AM -0500, Felipe Contreras wrote:
>> > I think it's a bad idea to introduce an entirely new runtime, especially
>> > one known to occasionally blow up on less-common architectures, without
>> > some advance notice.
>>
>> This is just FUD. What do you mean blow up on less-common architectures? Do you
>> have actual evidence or can we just dismiss that as a baseless argument?
>>
>> > For example, at work I would not be able to deploy a git using Ruby
>> > immediately because Git is an RPM and Ruby is compiled from source, if it is
>> > even present at all.
>>
>> Again, what do you mean? In all the distributions I've seen, vim is compiled
>> with Ruby support by default, so unless you think vim is an essoteric package,
>> libruby is almost definetly packaged and available.
>
> It would actually be usefull to know stats on where git is runned. In my
> world of embedded computing, ruby support definitely isn't a standard,
> nor is glibc.

I come from the embedded world as well, and I've never seen Git used there.

I'd say Windows support is much more important than embedded, and we
are not supporting that properly.

>> > Also, the only Python script that is shipped with Git is git-p4, which
>> > is essentially optional, since most git users probably do not use
>> > Perforce. Otherwise, all the scripts in git are shell or Perl.
>>
>> Neither perl, nor shell, nor python scripts solve the forking problem. My
>> proposal does.
>
> It does,

No, it does not. All the **current** perl/shell/python scripts use
'git foo' commands to achieve everything.

> and so does Lua,

There is no lua in Git.

> which can be bundled with git and used in the
> configuration files as well and is pure ansi C. However bundling
> something has it bad sides too. At least this will solve the dependency
> problem. So let the language war begin =).

Talk is cheap, show me the code.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-22  7:43           ` Felipe Contreras
@ 2013-09-22  8:12             ` Fredrik Gustafsson
  2013-09-22  8:29               ` Felipe Contreras
  0 siblings, 1 reply; 26+ messages in thread
From: Fredrik Gustafsson @ 2013-09-22  8:12 UTC (permalink / raw)
  To: Felipe Contreras
  Cc: Fredrik Gustafsson, brian m. carlson, git, Ramkumar Ramachandra

On Sun, Sep 22, 2013 at 02:43:39AM -0500, Felipe Contreras wrote:
> > It would actually be usefull to know stats on where git is runned. In my
> > world of embedded computing, ruby support definitely isn't a standard,
> > nor is glibc.
> 
> I come from the embedded world as well, and I've never seen Git used there.
> 
> I'd say Windows support is much more important than embedded, and we
> are not supporting that properly.

Me neither, it doesn't mean that it isn't used though... I agree with
the lack of windows support from git.git. However since Microsoft
working with libgit2 on a Visual Studio plugin this it might be that the
need for windows support decreases.

> 
> >> > Also, the only Python script that is shipped with Git is git-p4, which
> >> > is essentially optional, since most git users probably do not use
> >> > Perforce. Otherwise, all the scripts in git are shell or Perl.
> >>
> >> Neither perl, nor shell, nor python scripts solve the forking problem. My
> >> proposal does.
> >
> > It does,
> 
> No, it does not. All the **current** perl/shell/python scripts use
> 'git foo' commands to achieve everything.

As I said, "It does" meaning "Your solution solves the forking problem".

> 
> > and so does Lua,
> 
> There is no lua in Git.

There's no ruby in git either as far as I know... (and no, I don't think
contrib/ counts).

> 
> > which can be bundled with git and used in the
> > configuration files as well and is pure ansi C. However bundling
> > something has it bad sides too. At least this will solve the dependency
> > problem. So let the language war begin =).
> 
> Talk is cheap, show me the code.

See this thread by Jeff King:
http://thread.gmane.org/gmane.comp.version-control.git/206335/focus=206337

And see my humble test of what the speedup would be for git-submodule
even with a faulty lua integration (still forking... but huge
performance boost anyway):
http://thread.gmane.org/gmane.comp.version-control.git/228031/focus=228051

As you can see a lua integration would increase the git binary with
300kb.

-- 
Med vänliga hälsningar
Fredrik Gustafsson

tel: 0733-608274
e-post: iveqy@iveqy.com

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-22  8:12             ` Fredrik Gustafsson
@ 2013-09-22  8:29               ` Felipe Contreras
  2013-09-23 18:20                 ` Patrick Donnelly
  0 siblings, 1 reply; 26+ messages in thread
From: Felipe Contreras @ 2013-09-22  8:29 UTC (permalink / raw)
  To: Fredrik Gustafsson; +Cc: brian m. carlson, git, Ramkumar Ramachandra

On Sun, Sep 22, 2013 at 3:12 AM, Fredrik Gustafsson <iveqy@iveqy.com> wrote:
> On Sun, Sep 22, 2013 at 02:43:39AM -0500, Felipe Contreras wrote:
>> > It would actually be usefull to know stats on where git is runned. In my
>> > world of embedded computing, ruby support definitely isn't a standard,
>> > nor is glibc.
>>
>> I come from the embedded world as well, and I've never seen Git used there.
>>
>> I'd say Windows support is much more important than embedded, and we
>> are not supporting that properly.
>
> Me neither, it doesn't mean that it isn't used though... I agree with
> the lack of windows support from git.git.

Sure, it *might* be used, but I don't understand this fascination
about worrying about hypothetical users, possibly non-existent, when
we have real users to worry about, and in big numbers.

> However since Microsoft
> working with libgit2 on a Visual Studio plugin this it might be that the
> need for windows support decreases.

I'll believe it when I see it. And then, when the users like it and
don't report brokenness.

Personally, I don't have much faith the in the libgit2 project, and
it's ability to keep up with git.git.

>> >> > Also, the only Python script that is shipped with Git is git-p4, which
>> >> > is essentially optional, since most git users probably do not use
>> >> > Perforce. Otherwise, all the scripts in git are shell or Perl.
>> >>
>> >> Neither perl, nor shell, nor python scripts solve the forking problem. My
>> >> proposal does.
>> >
>> > It does,
>>
>> No, it does not. All the **current** perl/shell/python scripts use
>> 'git foo' commands to achieve everything.
>
> As I said, "It does" meaning "Your solution solves the forking problem".

Oh.

>> > and so does Lua,
>>
>> There is no lua in Git.
>
> There's no ruby in git either as far as I know... (and no, I don't think
> contrib/ counts).

There is when you apply this patch.

>> > which can be bundled with git and used in the
>> > configuration files as well and is pure ansi C. However bundling
>> > something has it bad sides too. At least this will solve the dependency
>> > problem. So let the language war begin =).
>>
>> Talk is cheap, show me the code.
>
> See this thread by Jeff King:
> http://thread.gmane.org/gmane.comp.version-control.git/206335/focus=206337

That is very very far from what I'm doing.

> And see my humble test of what the speedup would be for git-submodule
> even with a faulty lua integration (still forking... but huge
> performance boost anyway):
> http://thread.gmane.org/gmane.comp.version-control.git/228031/focus=228051

I don't see how that is relevant, but I'm certain the same can be done
with Ruby.

> As you can see a lua integration would increase the git binary with
> 300kb.

And my patch would increase it 49Kb.

IMO the problem with lua is that it's too simple, it's syntax doesn't
resemble c, perl, python, shell, or ruby, it's just weird. Also, it's
much less popular, it's not as powerful, and there isn't a big
community involved with Git like with Ruby.

Sure, for a couple of simple scripts lua bindings would be great, but
for the future, better maintainability, and to grab future developers,
Ruby is simply a better option.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-21 23:56     ` brian m. carlson
  2013-09-22  5:36       ` Felipe Contreras
@ 2013-09-23  0:00       ` Junio C Hamano
  2013-09-23  1:41         ` brian m. carlson
  2013-09-23 18:17         ` Felipe Contreras
  2013-09-28 23:06       ` Felipe Contreras
  2 siblings, 2 replies; 26+ messages in thread
From: Junio C Hamano @ 2013-09-23  0:00 UTC (permalink / raw)
  To: brian m. carlson; +Cc: Git Mailing List

[on vacaion, with only gmail webmail UI; please excuse me if this message comes
out badly formatted or gets dropped by vger.kernel.org]

On Sat, Sep 21, 2013 at 4:56 PM, brian m. carlson
<sandals@crustytoothpaste.net> wrote:
> On Sat, Sep 21, 2013 at 05:52:05PM -0500, Felipe Contreras wrote:
>> On Sat, Sep 21, 2013 at 4:29 PM, brian m. carlson
>> <sandals@crustytoothpaste.net> wrote:
>> > As Junio has also pointed out in the past, there are people who aren't
>> > able to use Ruby in the same way that they are Perl and Python.  If it's
>> > announced now, Git 2.0 might be a good time to start accepting Ruby
>> > scripts, as that will give people time to plan for its inclusion.

In the very beginning, the codebase and development community of Git was
very small. In order to give usability and also easy availability of minimally
sufficient features, we used shell and Perl for quicker turn-around and
implementation and included these Porcelain scripts written in higher level
languages in the same package as the core Git.

We should look at use of shell and Perl as necessary evil in that context,
not as an enabler for people who do not want to write in C. It is no longer
2005 and the "enabler" side has a much more suited project for it these days.

Namely, it is better served by various language-binding efforts around libgit2.
Binding that takes advantage of each specific language is better done over
there, I think. Cf. http://www.youtube.com/watch?v=4ZWqr6iih3s

If anything, I think the core side should be focused on three things
(in addition
to bug-fixes, of course) in the longer term:

 - Defining and implementing necessary improvements to the core on-file and
   on-the-wire data structures and the protocols to serve as the canonical
   implementation.

 - Moving away from higher-level scripting languages such as shell and Perl.
   Recent "clean --interactive" may have added some code that could be
   reused for a rewrite of "add -i" (which I think is in Perl), for example.
   The minimum "You need to have these to use Git" should be made more
   portable by doing *less* in shell or Perl, not by adding more in the higher-
   level languages, and certainly not by adding other languages, be it Ruby or
   Lua.

 - Giving solid interface to the outside world, e.g. remote-helpers, credential-
   helpers API, and let the users and developers that want to use them do their
   own projects, without adding things to contrib/.

In other words, now the Git user and developer community are strong
and thriving,
we should strive to make the core smaller, not larger, and encourage people to
form more third party communities that specialise in the areas the
participant of
these communities are stronger than those who are involved in the core
(e.g. like
myself, Peff, Nico, Jonathan, etc.). For programs that talk remote-helper or
credential-helper protocols, for example, it is wasteful to have them
in our contrib/
and have the changes to them go through my tree, with the same coding style
standard applied to the core, which would in the longer term only add
unnecessary overhead to what they want to do and what their effort supply the
users with.

For that, defining a good inter-system interface boundary is essential
on the core
side, but we do not need to (and I do not want to see us on the core side doing)
design and implement the other side that talks to us, which people may write in
their favorite higher-level languages.

We define a reasonably robust object & history transfer mechanism over SSH
connection with set of necessary hooks to customize what happens when a push
and a fetch is requested, and Sitaram built Gitolite totally outside
the core. I think
that is the kind of thing we want to see *more* in this community. Was it better
if we defined in the core how "hosting" service is to be done and implemented
one ourselves? I do not think so. Similarly for Michael Haggerty's iMerge, which
was done outside the core.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-23  0:00       ` Junio C Hamano
@ 2013-09-23  1:41         ` brian m. carlson
  2013-09-28 22:57           ` Felipe Contreras
  2013-09-23 18:17         ` Felipe Contreras
  1 sibling, 1 reply; 26+ messages in thread
From: brian m. carlson @ 2013-09-23  1:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List

[-- Attachment #1: Type: text/plain, Size: 1198 bytes --]

On Sun, Sep 22, 2013 at 05:00:44PM -0700, Junio C Hamano wrote:
>  - Moving away from higher-level scripting languages such as shell and Perl.
>    Recent "clean --interactive" may have added some code that could be
>    reused for a rewrite of "add -i" (which I think is in Perl), for example.
>    The minimum "You need to have these to use Git" should be made more
>    portable by doing *less* in shell or Perl, not by adding more in the higher-
>    level languages, and certainly not by adding other languages, be it Ruby or
>    Lua.

I can certainly go for that.  C is faster and the codebase can be more
consistent (and more portable to non-Unix).  My concern was that if
we're going to be adding additional languages, some previous warning
would be appropriate.  As I said, I wouldn't be able to deploy a git
using Ruby immediately, and I'm sure I'm not the only one.  If we're not
going to be adding another language, then obviously the issue becomes
moot.

-- 
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-23  0:00       ` Junio C Hamano
  2013-09-23  1:41         ` brian m. carlson
@ 2013-09-23 18:17         ` Felipe Contreras
  2013-09-28 22:56           ` Felipe Contreras
  1 sibling, 1 reply; 26+ messages in thread
From: Felipe Contreras @ 2013-09-23 18:17 UTC (permalink / raw)
  To: Junio C Hamano, brian m. carlson; +Cc: Git Mailing List

Junio C Hamano wrote:
> [on vacaion, with only gmail webmail UI; please excuse me if this message comes
> out badly formatted or gets dropped by vger.kernel.org]
> 
> On Sat, Sep 21, 2013 at 4:56 PM, brian m. carlson
> <sandals@crustytoothpaste.net> wrote:
> > On Sat, Sep 21, 2013 at 05:52:05PM -0500, Felipe Contreras wrote:
> >> On Sat, Sep 21, 2013 at 4:29 PM, brian m. carlson
> >> <sandals@crustytoothpaste.net> wrote:
> >> > As Junio has also pointed out in the past, there are people who aren't
> >> > able to use Ruby in the same way that they are Perl and Python.  If it's
> >> > announced now, Git 2.0 might be a good time to start accepting Ruby
> >> > scripts, as that will give people time to plan for its inclusion.
> 
> In the very beginning, the codebase and development community of Git was
> very small. In order to give usability and also easy availability of minimally
> sufficient features, we used shell and Perl for quicker turn-around and
> implementation and included these Porcelain scripts written in higher level
> languages in the same package as the core Git.
> 
> We should look at use of shell and Perl as necessary evil in that context,
> not as an enabler for people who do not want to write in C. It is no longer
> 2005 and the "enabler" side has a much more suited project for it these days.
> 
> Namely, it is better served by various language-binding efforts around libgit2.
> Binding that takes advantage of each specific language is better done over
> there, I think. Cf. http://www.youtube.com/watch?v=4ZWqr6iih3s

If libgit2 is so good as a library to interact with Git repositories, why isn't
Git using it?

Because it's not. It is a necessary evil due to the fact that Git developers
neglected to write code in a reusable manner so other people could utilize
libgit. So somebody else had to step up, so now we have two code-bases.

> If anything, I think the core side should be focused on three things
> (in addition
> to bug-fixes, of course) in the longer term:
> 
>  - Defining and implementing necessary improvements to the core on-file and
>    on-the-wire data structures and the protocols to serve as the canonical
>    implementation.
> 
>  - Moving away from higher-level scripting languages such as shell and Perl.
>    Recent "clean --interactive" may have added some code that could be
>    reused for a rewrite of "add -i" (which I think is in Perl), for example.
>    The minimum "You need to have these to use Git" should be made more
>    portable by doing *less* in shell or Perl, not by adding more in the higher-
>    level languages, and certainly not by adding other languages, be it Ruby or
>    Lua.
> 
>  - Giving solid interface to the outside world, e.g. remote-helpers, credential-
>    helpers API, and let the users and developers that want to use them do their
>    own projects, without adding things to contrib/.

It's interesting how none of these goals reflect what the users want:

https://www.survs.com/results/QPESOB10/ME8UTHXM4M

1. Better user-interface
2. Better documentation
3. GUI tools

Do you deny this is what users want? Or you just don't care?

I'm not trying to antagonize you, I just truly don't understand how something
so obvious for so many users just doesn't even factor into your decision making
as what needs to be done.

> In other words, now the Git user and developer community are strong
> and thriving,
> we should strive to make the core smaller, not larger, and encourage people to
> form more third party communities that specialise in the areas the
> participant of
> these communities are stronger than those who are involved in the core
> (e.g. like
> myself, Peff, Nico, Jonathan, etc.). For programs that talk remote-helper or
> credential-helper protocols, for example, it is wasteful to have them
> in our contrib/
> and have the changes to them go through my tree, with the same coding style
> standard applied to the core, which would in the longer term only add
> unnecessary overhead to what they want to do and what their effort supply the
> users with.

Of course, we can make the core smaller, by replacing all the perl/shell
scripts with ruby ones.

Sure, it would be better if all the scripts were rewritten in C, but that has
been going on for years, and there's no end in sight, and not that much
progress at all.

So, it's fair to say that the rewrite to C is just not going to happen any time
soon, and if we accept that, we should accept that an interim solution is
needed, because Windows users are important and they are hurting right now, and
that solution could definitely be Ruby.

Rewriting scripts to C is hard, rewriting them to Ruby is easy, and one of the
advantages of rewriting to Ruby, is that having the C->Ruby bindings available
would make it easy to replace part of the scripts chunk by chunk, so we could
have a half Ruby, half C script, and eventually 100% C.

This is a practical solution, it's a realistic path to move forward, not one
based on wishful thinking and intentions that never get realized.

Once again, the perfect being the enemy of the good in the Git project, even
when the good leads to perfect.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-22  8:29               ` Felipe Contreras
@ 2013-09-23 18:20                 ` Patrick Donnelly
  2013-09-23 18:53                   ` Felipe Contreras
  0 siblings, 1 reply; 26+ messages in thread
From: Patrick Donnelly @ 2013-09-23 18:20 UTC (permalink / raw)
  To: Felipe Contreras
  Cc: Fredrik Gustafsson, brian m. carlson, git, Ramkumar Ramachandra

Hello Felipe,

On Sun, Sep 22, 2013 at 4:29 AM, Felipe Contreras
<felipe.contreras@gmail.com> wrote:
> On Sun, Sep 22, 2013 at 3:12 AM, Fredrik Gustafsson <iveqy@iveqy.com> wrote:
>> And see my humble test of what the speedup would be for git-submodule
>> even with a faulty lua integration (still forking... but huge
>> performance boost anyway):
>> http://thread.gmane.org/gmane.comp.version-control.git/228031/focus=228051
>
> I don't see how that is relevant, but I'm certain the same can be done
> with Ruby.
>
>> As you can see a lua integration would increase the git binary with
>> 300kb.
>
> And my patch would increase it 49Kb.

Unless you statically compile in Ruby (which is what the above quoted
300kb implied for Lua, in actually it is less than 200kb). [Also good
luck statically compiling Python/Ruby into an executable.]

> IMO the problem with lua is that it's too simple, it's syntax doesn't
> resemble c, perl, python, shell, or ruby, it's just weird. Also, it's
> much less popular, it's not as powerful, and there isn't a big
> community involved with Git like with Ruby.

*sigh*. At this point you've really cemented your purpose here as a
language evangelist. It's unfortunate I have to reply to dismiss this
FUD (which you complained about earlier, ironically) otherwise
community accepts it as fact ("oh, I remember some guys saying Lua was
a language for idiots...").

Lua is by no means *simple*. Try "small" or "lightweight". Its syntax
is engineered to be readable and amateur friendly. You've placed Ruby
on a pedestal alongside those other major languages but its syntax
doesn't resemble any of those.

>Also, it's much less popular

https://sites.google.com/site/marbux/home/where-lua-is-used

The hallmark of a good embedded language is your users don't even know
it is there.

>  it's not as powerful,

This is really funny to me. Despite Lua's small size, it has lead the
way for modern dynamic language features, such as coroutines, block
level scoping and real closure, incremental GC, a simple and usable C
API (*yes* this is a feature), and a register based VM [1]. It is
consistently placed as the *fastest* dynamic language in existence
[e.g. 2]? The LuaJIT compiler often achieves competitive or better
performance than C [3]. What about this isn't powerful?

[1] Ierusalimschy, Roberto, Luiz Henrique De Figueiredo, and Waldemar
Celes Filho. "The Implementation of Lua 5.0." J. UCS 11.7 (2005):
1159-1176.
[2] http://benchmarksgame.alioth.debian.org/u32/benchmark.php?test=all&lang=lua&lang2=yarv&data=u32
[3] http://luajit.org/performance_x86.html

-- 
Patrick Donnelly

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-23 18:20                 ` Patrick Donnelly
@ 2013-09-23 18:53                   ` Felipe Contreras
  2013-09-23 19:20                     ` Patrick Donnelly
  0 siblings, 1 reply; 26+ messages in thread
From: Felipe Contreras @ 2013-09-23 18:53 UTC (permalink / raw)
  To: Patrick Donnelly
  Cc: Fredrik Gustafsson, brian m. carlson, git, Ramkumar Ramachandra

On Mon, Sep 23, 2013 at 1:20 PM, Patrick Donnelly <batrick@batbytes.com> wrote:
> Hello Felipe,
>
> On Sun, Sep 22, 2013 at 4:29 AM, Felipe Contreras
> <felipe.contreras@gmail.com> wrote:
>> On Sun, Sep 22, 2013 at 3:12 AM, Fredrik Gustafsson <iveqy@iveqy.com> wrote:
>>> And see my humble test of what the speedup would be for git-submodule
>>> even with a faulty lua integration (still forking... but huge
>>> performance boost anyway):
>>> http://thread.gmane.org/gmane.comp.version-control.git/228031/focus=228051
>>
>> I don't see how that is relevant, but I'm certain the same can be done
>> with Ruby.
>>
>>> As you can see a lua integration would increase the git binary with
>>> 300kb.
>>
>> And my patch would increase it 49Kb.
>
> Unless you statically compile in Ruby (which is what the above quoted
> 300kb implied for Lua, in actually it is less than 200kb). [Also good
> luck statically compiling Python/Ruby into an executable.]

Yes, but that's not what the words said, the words said 'lua
integration' and 'ruby integration' would take that much. Either way
it doesn't matter, shared libraries exist for a reason. We don't need
to statically compile openssl do we? No? Good.

>> IMO the problem with lua is that it's too simple, it's syntax doesn't
>> resemble c, perl, python, shell, or ruby, it's just weird. Also, it's
>> much less popular, it's not as powerful, and there isn't a big
>> community involved with Git like with Ruby.
>
> *sigh*. At this point you've really cemented your purpose here as a
> language evangelist. It's unfortunate I have to reply to dismiss this
> FUD (which you complained about earlier, ironically) otherwise
> community accepts it as fact ("oh, I remember some guys saying Lua was
> a language for idiots...").

I dismissed the claim as FUD, when the conclusion was exaggerated, and
there was no evidence in sight.

When I say Ruby is a superior alternative, I provide evidence.

> Lua is by no means *simple*. Try "small" or "lightweight". Its syntax
> is engineered to be readable and amateur friendly. You've placed Ruby
> on a pedestal alongside those other major languages but its syntax
> doesn't resemble any of those.
>
>>Also, it's much less popular
>
> https://sites.google.com/site/marbux/home/where-lua-is-used
>
> The hallmark of a good embedded language is your users don't even know
> it is there.

Users don't even know in what language those projects are programmed,
that's irrelevant. If MediaWiki does indeed use Lua, it must be a tiny
fraction of it.

Lua is #25 in the tiobe index with 0.518%, Ruby is #13 with 1.382%,
right next to Perl. Ruby is 54 times used more in GitHub than Lua.
These are the numbers I have, if you have other numbers, please, share
them.

>>  it's not as powerful,
>
> This is really funny to me. Despite Lua's small size, it has lead the
> way for modern dynamic language features, such as coroutines, block
> level scoping and real closure, incremental GC, a simple and usable C
> API (*yes* this is a feature), and a register based VM [1]. It is
> consistently placed as the *fastest* dynamic language in existence
> [e.g. 2]? The LuaJIT compiler often achieves competitive or better
> performance than C [3]. What about this isn't powerful?

Talk is cheap, show me the code.

Do what I did. Add lua bindings for several C functions, replace a
script with a Lua script (like git request-pull), replace a major
builtin (like git reset), and show how this succinct example I
provided in Ruby would look like:

cb_data = 'foo'
for_each_ref() do |name, sha1, flags|
  puts '%s: %s: %s' % [cb_data, name, sha1_to_hex(sha1)]
end

Let's see how it looks.

Until you do that, I'd say you are the one that is language
evangelizing, I'm providing an actual real solution to a very
important problem.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-23 18:53                   ` Felipe Contreras
@ 2013-09-23 19:20                     ` Patrick Donnelly
  2013-09-23 19:47                       ` Felipe Contreras
  0 siblings, 1 reply; 26+ messages in thread
From: Patrick Donnelly @ 2013-09-23 19:20 UTC (permalink / raw)
  To: Felipe Contreras
  Cc: Fredrik Gustafsson, brian m. carlson, git, Ramkumar Ramachandra

On Mon, Sep 23, 2013 at 2:53 PM, Felipe Contreras
<felipe.contreras@gmail.com> wrote:
> Yes, but that's not what the words said, the words said 'lua
> integration' and 'ruby integration' would take that much. Either way
> it doesn't matter, shared libraries exist for a reason. We don't need
> to statically compile openssl do we? No? Good.

Uh, you're willfully ignoring the conversation about avoiding
dependencies. One way to do that is to include and statically link Lua
along with Git. The cost of doing that is 200kb. I know this because I
actually do it for Nmap.

>>> IMO the problem with lua is that it's too simple, it's syntax doesn't
>>> resemble c, perl, python, shell, or ruby, it's just weird. Also, it's
>>> much less popular, it's not as powerful, and there isn't a big
>>> community involved with Git like with Ruby.
>>
>> *sigh*. At this point you've really cemented your purpose here as a
>> language evangelist. It's unfortunate I have to reply to dismiss this
>> FUD (which you complained about earlier, ironically) otherwise
>> community accepts it as fact ("oh, I remember some guys saying Lua was
>> a language for idiots...").
>
> I dismissed the claim as FUD, when the conclusion was exaggerated, and
> there was no evidence in sight.
>
> When I say Ruby is a superior alternative, I provide evidence.

You have provided *no* evidence.

>> Lua is by no means *simple*. Try "small" or "lightweight". Its syntax
>> is engineered to be readable and amateur friendly. You've placed Ruby
>> on a pedestal alongside those other major languages but its syntax
>> doesn't resemble any of those.
>>
>>>Also, it's much less popular
>>
>> https://sites.google.com/site/marbux/home/where-lua-is-used
>>
>> The hallmark of a good embedded language is your users don't even know
>> it is there.
>
> Users don't even know in what language those projects are programmed,
> that's irrelevant.

*Absolutely relevant*: as normal git user *never* wants to know, care,
or be exposed to the details of how `git` operates.

> If MediaWiki does indeed use Lua, it must be a tiny
> fraction of it.

They just started using it. Well done cherry-picking 1 example from a
host for your dismissal.

>>>  it's not as powerful,
>>
>> This is really funny to me. Despite Lua's small size, it has lead the
>> way for modern dynamic language features, such as coroutines, block
>> level scoping and real closure, incremental GC, a simple and usable C
>> API (*yes* this is a feature), and a register based VM [1]. It is
>> consistently placed as the *fastest* dynamic language in existence
>> [e.g. 2]? The LuaJIT compiler often achieves competitive or better
>> performance than C [3]. What about this isn't powerful?
>
> Talk is cheap, show me the code.
>
> Do what I did. Add lua bindings for several C functions, replace a
> script with a Lua script (like git request-pull), replace a major
> builtin (like git reset), and show how this succinct example I
> provided in Ruby would look like:
>
> cb_data = 'foo'
> for_each_ref() do |name, sha1, flags|
>   puts '%s: %s: %s' % [cb_data, name, sha1_to_hex(sha1)]
> end
>
> Let's see how it looks.

I address your performance claims, you dismiss them and then ask for
code to compare? Code which is primarily bindings to C which does all
the work? No thanks, that circle jerk doesn't interest me.

> Until you do that, I'd say you are the one that is language
> evangelizing, I'm providing an actual real solution to a very
> important problem.

As mentioned elsewhere, the solution Git is using is to move porcelain
commands to C. You're manufacturing problems and spreading FUD.

I'm letting this thread die as I only wanted to confront your baseless
dismissal of Lua. If you want to continue this, I'll do it offlist.

-- 
Patrick Donnelly

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-23 19:20                     ` Patrick Donnelly
@ 2013-09-23 19:47                       ` Felipe Contreras
  0 siblings, 0 replies; 26+ messages in thread
From: Felipe Contreras @ 2013-09-23 19:47 UTC (permalink / raw)
  To: Patrick Donnelly
  Cc: Fredrik Gustafsson, brian m. carlson, git, Ramkumar Ramachandra

On Mon, Sep 23, 2013 at 2:20 PM, Patrick Donnelly <batrick@batbytes.com> wrote:
> On Mon, Sep 23, 2013 at 2:53 PM, Felipe Contreras
> <felipe.contreras@gmail.com> wrote:
>> Yes, but that's not what the words said, the words said 'lua
>> integration' and 'ruby integration' would take that much. Either way
>> it doesn't matter, shared libraries exist for a reason. We don't need
>> to statically compile openssl do we? No? Good.
>
> Uh, you're willfully ignoring the conversation about avoiding
> dependencies. One way to do that is to include and statically link Lua
> along with Git. The cost of doing that is 200kb. I know this because I
> actually do it for Nmap.

Dependencies are avoided when it's possible and sensible to do so.
Yet, we still depend on a bunch of things.

My proposal to replace perl/shell with ruby would actually remove two
dependencies and add one, so in effect would remove one dependency. Of
course, people could still build with NO_RUBY=y, just like they can
build with NO_PERL=y, and deal with the consequences.

>>>> IMO the problem with lua is that it's too simple, it's syntax doesn't
>>>> resemble c, perl, python, shell, or ruby, it's just weird. Also, it's
>>>> much less popular, it's not as powerful, and there isn't a big
>>>> community involved with Git like with Ruby.
>>>
>>> *sigh*. At this point you've really cemented your purpose here as a
>>> language evangelist. It's unfortunate I have to reply to dismiss this
>>> FUD (which you complained about earlier, ironically) otherwise
>>> community accepts it as fact ("oh, I remember some guys saying Lua was
>>> a language for idiots...").
>>
>> I dismissed the claim as FUD, when the conclusion was exaggerated, and
>> there was no evidence in sight.
>>
>> When I say Ruby is a superior alternative, I provide evidence.
>
> You have provided *no* evidence.

I have, you just chose to ignore it.

>>> Lua is by no means *simple*. Try "small" or "lightweight". Its syntax
>>> is engineered to be readable and amateur friendly. You've placed Ruby
>>> on a pedestal alongside those other major languages but its syntax
>>> doesn't resemble any of those.
>>>
>>>>Also, it's much less popular
>>>
>>> https://sites.google.com/site/marbux/home/where-lua-is-used
>>>
>>> The hallmark of a good embedded language is your users don't even know
>>> it is there.
>>
>> Users don't even know in what language those projects are programmed,
>> that's irrelevant.
>
> *Absolutely relevant*: as normal git user *never* wants to know, care,
> or be exposed to the details of how `git` operates.

So? Before and after this patch they still wouldn't be exposed.

This is a total red herring.

>> If MediaWiki does indeed use Lua, it must be a tiny
>> fraction of it.
>
> They just started using it. Well done cherry-picking 1 example from a
> host for your dismissal.

I didn't cherry pick anything, I used the project I'm more familiar
with, replace MediaWiki with any other of your examples, and the claim
still stands.

>>>>  it's not as powerful,
>>>
>>> This is really funny to me. Despite Lua's small size, it has lead the
>>> way for modern dynamic language features, such as coroutines, block
>>> level scoping and real closure, incremental GC, a simple and usable C
>>> API (*yes* this is a feature), and a register based VM [1]. It is
>>> consistently placed as the *fastest* dynamic language in existence
>>> [e.g. 2]? The LuaJIT compiler often achieves competitive or better
>>> performance than C [3]. What about this isn't powerful?
>>
>> Talk is cheap, show me the code.
>>
>> Do what I did. Add lua bindings for several C functions, replace a
>> script with a Lua script (like git request-pull), replace a major
>> builtin (like git reset), and show how this succinct example I
>> provided in Ruby would look like:
>>
>> cb_data = 'foo'
>> for_each_ref() do |name, sha1, flags|
>>   puts '%s: %s: %s' % [cb_data, name, sha1_to_hex(sha1)]
>> end
>>
>> Let's see how it looks.
>
> I address your performance claims, you dismiss them and then ask for
> code to compare? Code which is primarily bindings to C which does all
> the work? No thanks, that circle jerk doesn't interest me.

I didn't make any performance claims, you made claims about being a
powerful language, well, let's see how powerful it is.

Ruby is so powerful I was able to write these patches with moderate
effort, surely if Lua is so powerful you can do the same.

>> Until you do that, I'd say you are the one that is language
>> evangelizing, I'm providing an actual real solution to a very
>> important problem.
>
> As mentioned elsewhere, the solution Git is using is to move porcelain
> commands to C. You're manufacturing problems and spreading FUD.

This effort has no end in sight, and as I've explained, using Ruby as
an interim solution would actually speed up the move to pure C.

In fact, I would know much more about the impediments since I sent
twenty eight patches to start replacing 'git rebase' with C code:

http://thread.gmane.org/gmane.comp.version-control.git/233396

They got rejected without so much as a reply. Why if it's so important
to move the scripts to C did these patches get ignored? Because it's
not. None of the core developers are interested in this, because they
don't use Windows, so it's not a priority for them.

> I'm letting this thread die as I only wanted to confront your baseless
> dismissal of Lua. If you want to continue this, I'll do it offlist.

Until you, or anyone, shows me the code, I'll continue to dismiss Lua,
or any other proposed solution.

I know doing what I did in Ruby would be very difficult in Lua, or any
other language for that matter, which is why I ask you to actually do
it, because I know you won't do it, because it's hard, which proves my
point.

I've proved other people wrong on this list by writing the code, if
you are not willing to walk the talk, then there's no point in
discussing. Even if I were to agree that Lua is a better option (which
I'm not), what have we achieved? Nothing. Who is going to implement
that? Not you, not me... So?

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-23 18:17         ` Felipe Contreras
@ 2013-09-28 22:56           ` Felipe Contreras
  0 siblings, 0 replies; 26+ messages in thread
From: Felipe Contreras @ 2013-09-28 22:56 UTC (permalink / raw)
  To: Junio C Hamano, brian m. carlson; +Cc: Git Mailing List

On Mon, Sep 23, 2013 at 1:17 PM, Felipe Contreras
<felipe.contreras@gmail.com> wrote:
> Junio C Hamano wrote:

>> In other words, now the Git user and developer community are strong
>> and thriving,
>> we should strive to make the core smaller, not larger, and encourage people to
>> form more third party communities that specialise in the areas the
>> participant of
>> these communities are stronger than those who are involved in the core
>> (e.g. like
>> myself, Peff, Nico, Jonathan, etc.). For programs that talk remote-helper or
>> credential-helper protocols, for example, it is wasteful to have them
>> in our contrib/
>> and have the changes to them go through my tree, with the same coding style
>> standard applied to the core, which would in the longer term only add
>> unnecessary overhead to what they want to do and what their effort supply the
>> users with.
>
> Of course, we can make the core smaller, by replacing all the perl/shell
> scripts with ruby ones.
>
> Sure, it would be better if all the scripts were rewritten in C, but that has
> been going on for years, and there's no end in sight, and not that much
> progress at all.
>
> So, it's fair to say that the rewrite to C is just not going to happen any time
> soon, and if we accept that, we should accept that an interim solution is
> needed, because Windows users are important and they are hurting right now, and
> that solution could definitely be Ruby.
>
> Rewriting scripts to C is hard, rewriting them to Ruby is easy, and one of the
> advantages of rewriting to Ruby, is that having the C->Ruby bindings available
> would make it easy to replace part of the scripts chunk by chunk, so we could
> have a half Ruby, half C script, and eventually 100% C.
>
> This is a practical solution, it's a realistic path to move forward, not one
> based on wishful thinking and intentions that never get realized.
>
> Once again, the perfect being the enemy of the good in the Git project, even
> when the good leads to perfect.

I think I've pretty much demonstrated that Ruby would be an excellent
tool to make the code smaller with my 44 patch series.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-23  1:41         ` brian m. carlson
@ 2013-09-28 22:57           ` Felipe Contreras
  0 siblings, 0 replies; 26+ messages in thread
From: Felipe Contreras @ 2013-09-28 22:57 UTC (permalink / raw)
  To: brian m. carlson; +Cc: Junio C Hamano, Git Mailing List

On Sun, Sep 22, 2013 at 8:41 PM, brian m. carlson
<sandals@crustytoothpaste.net> wrote:
> On Sun, Sep 22, 2013 at 05:00:44PM -0700, Junio C Hamano wrote:
>>  - Moving away from higher-level scripting languages such as shell and Perl.
>>    Recent "clean --interactive" may have added some code that could be
>>    reused for a rewrite of "add -i" (which I think is in Perl), for example.
>>    The minimum "You need to have these to use Git" should be made more
>>    portable by doing *less* in shell or Perl, not by adding more in the higher-
>>    level languages, and certainly not by adding other languages, be it Ruby or
>>    Lua.
>
> I can certainly go for that.  C is faster and the codebase can be more
> consistent (and more portable to non-Unix).  My concern was that if
> we're going to be adding additional languages, some previous warning
> would be appropriate.  As I said, I wouldn't be able to deploy a git
> using Ruby immediately, and I'm sure I'm not the only one.  If we're not
> going to be adding another language, then obviously the issue becomes
> moot.

You could just build with NO_RUBY=y. Problem solved.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH/RFC 0/7] Support for Ruby
  2013-09-21 23:56     ` brian m. carlson
  2013-09-22  5:36       ` Felipe Contreras
  2013-09-23  0:00       ` Junio C Hamano
@ 2013-09-28 23:06       ` Felipe Contreras
  2 siblings, 0 replies; 26+ messages in thread
From: Felipe Contreras @ 2013-09-28 23:06 UTC (permalink / raw)
  To: brian m. carlson; +Cc: git, Ramkumar Ramachandra

On Sat, Sep 21, 2013 at 6:56 PM, brian m. carlson
<sandals@crustytoothpaste.net> wrote:
> On Sat, Sep 21, 2013 at 05:52:05PM -0500, Felipe Contreras wrote:
>> On Sat, Sep 21, 2013 at 4:29 PM, brian m. carlson
>> <sandals@crustytoothpaste.net> wrote:

>> Now, if anybody has ideas into how the bindings could be more object
>> oriented, I'm all ears, but unfortunately what I foresee is that
>> nobody will consider this proposal seriously.
>
> My concern is that the Ruby code will end up not being idiomatic, and
> people will view it as bizarre and unmaintainable.
>
> for_each_ref could end up being something like REPOSITORY.refs.each,
> which would be more idiomatic.  repository.refs would probably be an
> Enumerator in that case.  If the decision is made to incorporate Ruby
> code, I'm happy to submit some patches to help provide a sane interface,
> even though I'm not that familiar with Ruby.

I think my proposed bindings are quite idiomatic.

git ruby - master origin/master <<EOF
commits = ARGV.map { |id| Git::Commit.get(get_sha1(id)) }
puts get_merge_bases(commits, 0).map { |commit| sha1_to_hex(commit.sha1) }
EOF

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2013-09-28 23:06 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-21 18:48 [PATCH/RFC 0/7] Support for Ruby Felipe Contreras
2013-09-21 18:48 ` [PATCH/RFC 1/7] Add support for ruby commands Felipe Contreras
2013-09-21 18:48 ` [PATCH/RFC 2/7] ruby: add setup script Felipe Contreras
2013-09-21 18:48 ` [PATCH/RFC 3/7] ruby: add simple wrappers Felipe Contreras
2013-09-21 18:48 ` [PATCH/RFC 4/7] ruby: rewrite 'request-pull' Felipe Contreras
2013-09-21 18:48 ` [PATCH/RFC 5/7] ruby: rewrite perl script Felipe Contreras
2013-09-21 18:48 ` [PATCH/RFC 6/7] ruby: remove one fork Felipe Contreras
2013-09-21 18:48 ` [PATCH/RFC 7/7] ruby: rewrite 'reset' Felipe Contreras
2013-09-21 21:29 ` [PATCH/RFC 0/7] Support for Ruby brian m. carlson
2013-09-21 22:52   ` Felipe Contreras
2013-09-21 23:56     ` brian m. carlson
2013-09-22  5:36       ` Felipe Contreras
2013-09-22  7:31         ` Fredrik Gustafsson
2013-09-22  7:43           ` Felipe Contreras
2013-09-22  8:12             ` Fredrik Gustafsson
2013-09-22  8:29               ` Felipe Contreras
2013-09-23 18:20                 ` Patrick Donnelly
2013-09-23 18:53                   ` Felipe Contreras
2013-09-23 19:20                     ` Patrick Donnelly
2013-09-23 19:47                       ` Felipe Contreras
2013-09-23  0:00       ` Junio C Hamano
2013-09-23  1:41         ` brian m. carlson
2013-09-28 22:57           ` Felipe Contreras
2013-09-23 18:17         ` Felipe Contreras
2013-09-28 22:56           ` Felipe Contreras
2013-09-28 23:06       ` Felipe Contreras

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).