{"thread":{"id":"34989","subject":"[PATCH/RFC 0/7] Support for Ruby","startedAt":"2013-09-21T18:48:08Z","lastAt":"2013-09-28T23:06:22Z","messageCount":26,"participants":["Felipe Contreras","brian m. carlson","Fredrik Gustafsson","Junio C Hamano","Patrick Donnelly"],"isPatch":true,"patchVersion":1,"patchTotal":7},"messages":[{"id":"228001","messageId":"1379789295-18519-1-git-send-email-felipe.contreras@gmail.com","threadId":"34989","inReplyTo":null,"subject":"[PATCH/RFC 0/7] Support for Ruby","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-21T18:48:08Z","receivedAt":"2013-09-21T18:48:08Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Hi,\n\nIt was discussed before that there was a need to replace Git scripts from perl\nand sh that utilize the 'git' binary to do everything they need, which requires\nmany forks, and that creates problems on platforms like Windows.\n\nThis is a first step meant to show how a solution using Ruby would look like.\n\nOther alternatives just don't cut it. Shell scripts are too simple, and\ninvariably require forks. Perl could use Git's internal C code, but it's syntax\nis too cumbersome and it's loosing more and more popularity. Python and Ruby\nare the only modern languages that could fit all the needs, but Python's syntax\nis not ideal, specially considering the background of the Git community, and\nalso, Ruby's C extensibility is simply superb.\n\nThis patch series introduces Ruby bindings for Git's C internal library, and\nadd example commands to show how it could be used, and how it resembles the\noriginal C code, shell code, and perl code. Basically, Ruby fits like a glove.\n\n== Syntax ==\n\nFirst of all, the syntax of Ruby is very similar to other languages used by Git:\n\nC:\n\n  if (a && b || (c & FLAG) != 0)\n    return 0\n  else\n    break\n  end\n\n  printf(\"format: %s: %i\\n\", \"this string\", 0)\n\n  count += 1\n\nShell:\n\n  out = `git rev-parse #{committish}`\n\n  str = <<EOF\n  multi\n  line\n  string\n  EOF\n\nPerl\n\n  var ||= 'default'\n\nThe following Perl code:\n\n  sub abbr {\n    my $ref = shift;\n    if ($ref =~ m{^refs/heads/(.*)$}) {\n      return $1;\n    }\n    return $ref;\n  }\n\nLooks like this in Ruby:\n\n  def abbr(ref)\n    if (ref =~ %r{^refs/heads/(.*)$}m)\n      return $1\n    end\n    return ref\n  end\n\n== C bindings ==\n\nIt's extremely easy to write wrappers for Git's C functions:\n\n  static VALUE git_rb_get_git_dir(VALUE self)\n  {\n    return rb_str_new2(get_git_dir());\n  }\n\n  rb_define_global_function(\"get_git_dir\", git_rb_get_git_dir, 0);\n\nThen in Ruby:\n\n  dir = get_git_dir()\n\n== Much more ==\n\nRuby's power allows for plenty of extensibility.\n\nFor example:\n\n  p `echo yes`\n  => \"yes\\n\"\n\nUsually we want to chomp the last new line. Fortunately everything is open in\nRuby, so it's possible to override the `() method:\n\n  def `(cmd)\n    IO.popen(cmd) { |pipe| pipe.read.chomp }\n  end\n\nNow:\n\n  p `echo yes`\n  => \"yes\"\n\nAlso, in shell, if we want to make sure a sequence of commands is executed, we\nwould do something like:\n\n  git command 1 &&\n  git command 2 &&\n  git command 3 ||\n  error\n\nThis gets specially troublesome the bigger the sequence. In Ruby:\n\n  def run(*args)\n    system(*args)\n    raise RuntimeError unless $?.success?\n  end\n\n  begin\n    run('git command 1')\n    run('git command 2')\n    run('git command 3')\n  rescue RuntimeError\n    error\n  end\n\nFinally, Ruby has the concept of blocks:\n\n  def run_with_lock()\n    puts \"lock\"\n    yield\n    puts \"unlock\"\n  end\n\n  branch = 'master'\n\n  run_with_lock() do\n    puts \"do stuff with #{branch}\"\n  end\n\nNotice how the block inside run_with_lock() is able to access the 'branch'\nvariable, because it's in it's context, but the block is not actually called\nuntil run_with_lock() calls 'yield'.\n\nPython has a similar concept, but not nearly as powerful.\n\n== Upgrade path ==\n\nRuby 2.0 didn't suffer the problems Python 3 is suffering because they have a\nsane upgrade path.\n\nRuby 1.9 changed the syntax, so people using 1.8 had to do minor changes to\nupgrade to 1.9, but they didn't miss many major features. After people updated\nto 1.9, 2.0 came along with major features, but it was compatible with 1.9, so\nnobody had to do any further changes.\n\nEither way, it's still possible to run code that works in 1.8, 1.9, and 2.0.\n\n== Community ==\n\nThe Ruby community is already heavily engaged in Git, as statistics in GitHub\nshow, plenty of Ruby projects use Git, outnumbering by far the Python ones.\n\nThere might be some correlation based on the fact that Mercurial is written in\nPython.\n\nhttp://adambard.com/blog/top-github-languages-for-2013-so-far/\n\n== Conclusion ==\n\nRuby is an extremly powerful modern language, it features object oriented\nparadigm, as well as functional, and procedural. It borrows from languages such\nas C, Perl, and many others.\n\nIt's possible that by opening the possibilities to write Ruby scripts, many\nRuby developers would join the effort to improve Git.\n\nFelipe Contreras (7):\n  Add support for ruby commands\n  ruby: add setup script\n  ruby: add simple wrappers\n  ruby: rewrite 'request-pull'\n  ruby: rewrite perl script\n  ruby: remove one fork\n  ruby: rewrite 'reset'\n\n Makefile            |  16 +-\n cache.h             |   2 +\n git-rb-setup.rb     | 125 +++++++++++++\n git-refs.rb         |   7 +\n git-request-pull.rb | 159 ++++++++++++++++\n git-request-pull.sh | 162 -----------------\n git-reset.rb        | 223 +++++++++++++++++++++++\n git.c               |   4 +-\n ruby.c              | 511 ++++++++++++++++++++++++++++++++++++++++++++++++++++\n 9 files changed, 1044 insertions(+), 165 deletions(-)\n create mode 100644 git-rb-setup.rb\n create mode 100644 git-refs.rb\n create mode 100644 git-request-pull.rb\n delete mode 100755 git-request-pull.sh\n create mode 100644 git-reset.rb\n create mode 100644 ruby.c\n\n-- \n1.8.4-fc\n"},{"id":"228003","messageId":"1379789295-18519-2-git-send-email-felipe.contreras@gmail.com","threadId":"34989","inReplyTo":"1379789295-18519-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH/RFC 1/7] Add support for ruby commands","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-21T18:48:09Z","receivedAt":"2013-09-21T18:48:09Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n Makefile |  4 ++++\n cache.h  |  2 ++\n git.c    |  3 +++\n ruby.c   | 48 ++++++++++++++++++++++++++++++++++++++++++++++++\n 4 files changed, 57 insertions(+)\n create mode 100644 ruby.c\n\ndiff --git a/Makefile b/Makefile\nindex 3588ca1..7cbcbcb 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -899,6 +899,7 @@ LIB_OBJS += ws.o\n LIB_OBJS += wt-status.o\n LIB_OBJS += xdiff-interface.o\n LIB_OBJS += zlib.o\n+LIB_OBJS += ruby.o\n \n BUILTIN_OBJS += builtin/add.o\n BUILTIN_OBJS += builtin/annotate.o\n@@ -1502,6 +1503,9 @@ ifneq (,$(XDL_FAST_HASH))\n \tBASIC_CFLAGS += -DXDL_FAST_HASH\n endif\n \n+EXTLIBS += $(shell pkg-config --libs ruby-2.0)\n+BASIC_CFLAGS += $(shell pkg-config --cflags ruby-2.0)\n+\n ifeq ($(TCLTK_PATH),)\n NO_TCLTK = NoThanks\n endif\ndiff --git a/cache.h b/cache.h\nindex 85b544f..4b1abd4 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1393,4 +1393,6 @@ int stat_validity_check(struct stat_validity *sv, const char *path);\n  */\n void stat_validity_update(struct stat_validity *sv, int fd);\n \n+extern void handle_ruby_command(int argc, const char **argv);\n+\n #endif /* CACHE_H */\ndiff --git a/git.c b/git.c\nindex 2025f77..0e1d97d 100644\n--- a/git.c\n+++ b/git.c\n@@ -499,6 +499,9 @@ static int run_argv(int *argcp, const char ***argv)\n \t\t/* See if it's an internal command */\n \t\thandle_internal_command(*argcp, *argv);\n \n+\t\t/* See if it's a ruby command */\n+\t\thandle_ruby_command(*argcp, *argv);\n+\n \t\t/* .. then try the external ones */\n \t\texecv_dashed_external(*argv);\n \ndiff --git a/ruby.c b/ruby.c\nnew file mode 100644\nindex 0000000..5701753\n--- /dev/null\n+++ b/ruby.c\n@@ -0,0 +1,48 @@\n+#include \"cache.h\"\n+#include \"exec_cmd.h\"\n+\n+#undef NORETURN\n+#undef PATH_SEP\n+\n+#include <ruby.h>\n+\n+static const char *commands[] = {\n+};\n+\n+static void run_ruby_command(int argc, const char **argv)\n+{\n+\tconst char *cmd = argv[0];\n+\tstatic char buf[PATH_MAX + 1];\n+\tconst char *dir;\n+\tchar *args[argc + 2];\n+\tvoid *node;\n+\tVALUE prefix;\n+\tint i;\n+\n+\tdir = git_exec_path();\n+\tsnprintf(buf, PATH_MAX, \"%s/git-%s.rb\", dir, cmd);\n+\n+\truby_init();\n+\n+\tprefix = Qnil;\n+\trb_define_variable(\"$prefix\", &prefix);\n+\n+\targs[0] = \"git\";\n+\targs[1] = buf;\n+\tfor (i = 0; i < argc; i++)\n+\t\targs[i + 2] = (char*)argv[i];\n+\tnode = ruby_options(argc + 2, args);\n+\n+\texit(ruby_run_node(node));\n+}\n+\n+void handle_ruby_command(int argc, const char **argv)\n+{\n+\tint i;\n+\tfor (i = 0; i < ARRAY_SIZE(commands); i++) {\n+\t\tif (strcmp(commands[i], argv[0]))\n+\t\t\tcontinue;\n+\n+\t\trun_ruby_command(argc, argv);\n+\t}\n+}\n-- \n1.8.4-fc\n"},{"id":"228002","messageId":"1379789295-18519-3-git-send-email-felipe.contreras@gmail.com","threadId":"34989","inReplyTo":"1379789295-18519-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH/RFC 2/7] ruby: add setup script","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-21T18:48:10Z","receivedAt":"2013-09-21T18:48:10Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n Makefile        |  8 +++++++-\n git-rb-setup.rb | 11 +++++++++++\n 2 files changed, 18 insertions(+), 1 deletion(-)\n create mode 100644 git-rb-setup.rb\n\ndiff --git a/Makefile b/Makefile\nindex 7cbcbcb..138f9bf 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -491,6 +491,8 @@ SCRIPT_PERL += git-svn.perl\n SCRIPT_PYTHON += git-remote-testpy.py\n SCRIPT_PYTHON += git-p4.py\n \n+SCRIPT_RUBY += git-rb-setup.rb\n+\n NO_INSTALL += git-remote-testgit\n NO_INSTALL += git-remote-testpy\n \n@@ -502,6 +504,7 @@ SCRIPT_PYTHON_GEN = $(patsubst %.py,%,$(SCRIPT_PYTHON))\n SCRIPT_SH_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_SH_GEN))\n SCRIPT_PERL_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_PERL_GEN))\n SCRIPT_PYTHON_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_PYTHON_GEN))\n+SCRIPT_RUBY_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_RUBY))\n \n # Individual rules to allow e.g.\n # \"make -C ../.. SCRIPT_PERL=contrib/foo/bar.perl build-perl-script\"\n@@ -511,13 +514,15 @@ build-perl-script: $(SCRIPT_PERL_GEN)\n build-sh-script: $(SCRIPT_SH_GEN)\n build-python-script: $(SCRIPT_PYTHON_GEN)\n \n-.PHONY: install-perl-script install-sh-script install-python-script\n+.PHONY: install-perl-script install-sh-script install-python-script install-ruby-script\n install-sh-script: $(SCRIPT_SH_INS)\n \t$(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'\n install-perl-script: $(SCRIPT_PERL_INS)\n \t$(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'\n install-python-script: $(SCRIPT_PYTHON_INS)\n \t$(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'\n+install-ruby-script: $(SCRIPT_RUBY_INS)\n+\t$(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'\n \n .PHONY: clean-perl-script clean-sh-script clean-python-script\n clean-sh-script:\n@@ -530,6 +535,7 @@ clean-python-script:\n SCRIPTS = $(SCRIPT_SH_INS) \\\n \t  $(SCRIPT_PERL_INS) \\\n \t  $(SCRIPT_PYTHON_INS) \\\n+\t  $(SCRIPT_RUBY_INS) \\\n \t  git-instaweb\n \n ETAGS_TARGET = TAGS\ndiff --git a/git-rb-setup.rb b/git-rb-setup.rb\nnew file mode 100644\nindex 0000000..969278a\n--- /dev/null\n+++ b/git-rb-setup.rb\n@@ -0,0 +1,11 @@\n+#!/usr/bin/env ruby\n+\n+def die(*args)\n+  fmt = args.shift\n+  $stderr.printf(\"fatal: %s\\n\" % fmt, *args)\n+  exit 128\n+end\n+\n+def sha1_to_hex(sha1)\n+  sha1.unpack('H*').first\n+end\n-- \n1.8.4-fc\n"},{"id":"228004","messageId":"1379789295-18519-4-git-send-email-felipe.contreras@gmail.com","threadId":"34989","inReplyTo":"1379789295-18519-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH/RFC 3/7] ruby: add simple wrappers","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-21T18:48:11Z","receivedAt":"2013-09-21T18:48:11Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"So that we can use for_each_ref() inside Ruby, and provide an example\nscript.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n Makefile    |  1 +\n git-refs.rb |  7 +++++++\n ruby.c      | 27 +++++++++++++++++++++++++++\n 3 files changed, 35 insertions(+)\n create mode 100644 git-refs.rb\n\ndiff --git a/Makefile b/Makefile\nindex 138f9bf..8a4e48f 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -492,6 +492,7 @@ SCRIPT_PYTHON += git-remote-testpy.py\n SCRIPT_PYTHON += git-p4.py\n \n SCRIPT_RUBY += git-rb-setup.rb\n+SCRIPT_RUBY += git-refs.rb\n \n NO_INSTALL += git-remote-testgit\n NO_INSTALL += git-remote-testpy\ndiff --git a/git-refs.rb b/git-refs.rb\nnew file mode 100644\nindex 0000000..b048714\n--- /dev/null\n+++ b/git-refs.rb\n@@ -0,0 +1,7 @@\n+#!/usr/bin/env ruby\n+\n+require_relative 'git-rb-setup'\n+\n+for_each_ref() do |name, sha1, flags|\n+  puts '%s: %s' % [name, sha1_to_hex(sha1)]\n+end\ndiff --git a/ruby.c b/ruby.c\nindex 5701753..7f0cc9d 100644\n--- a/ruby.c\n+++ b/ruby.c\n@@ -1,12 +1,38 @@\n #include \"cache.h\"\n #include \"exec_cmd.h\"\n+#include \"refs.h\"\n \n #undef NORETURN\n #undef PATH_SEP\n \n #include <ruby.h>\n \n+static inline VALUE sha1_to_str(const unsigned char *sha1)\n+{\n+\treturn rb_str_new((const char *)sha1, 20);\n+}\n+\n+static int for_each_ref_fn(const char *refname, const unsigned char *sha1, int flags, void *cb_data)\n+{\n+\tVALUE r;\n+\tr = rb_yield_values(3, rb_str_new2(refname), sha1_to_str(sha1), INT2FIX(flags));\n+\treturn r == Qfalse;\n+}\n+\n+static VALUE git_rb_for_each_ref(void)\n+{\n+\tint r;\n+\tr = for_each_ref(for_each_ref_fn, NULL);\n+\treturn INT2FIX(r);\n+}\n+\n+static void git_init(void)\n+{\n+\trb_define_global_function(\"for_each_ref\", git_rb_for_each_ref, 0);\n+}\n+\n static const char *commands[] = {\n+\t\"refs\",\n };\n \n static void run_ruby_command(int argc, const char **argv)\n@@ -23,6 +49,7 @@ static void run_ruby_command(int argc, const char **argv)\n \tsnprintf(buf, PATH_MAX, \"%s/git-%s.rb\", dir, cmd);\n \n \truby_init();\n+\tgit_init();\n \n \tprefix = Qnil;\n \trb_define_variable(\"$prefix\", &prefix);\n-- \n1.8.4-fc\n"},{"id":"228005","messageId":"1379789295-18519-5-git-send-email-felipe.contreras@gmail.com","threadId":"34989","inReplyTo":"1379789295-18519-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH/RFC 4/7] ruby: rewrite 'request-pull'","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-21T18:48:12Z","receivedAt":"2013-09-21T18:48:12Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n Makefile            |   2 +-\n git-rb-setup.rb     |  25 ++++++++\n git-request-pull.rb | 153 +++++++++++++++++++++++++++++++++++++++++++++++++\n git-request-pull.sh | 162 ----------------------------------------------------\n ruby.c              |   1 +\n 5 files changed, 180 insertions(+), 163 deletions(-)\n create mode 100644 git-request-pull.rb\n delete mode 100755 git-request-pull.sh\n\ndiff --git a/Makefile b/Makefile\nindex 8a4e48f..cb6bb4e 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -465,7 +465,6 @@ SCRIPT_SH += git-quiltimport.sh\n SCRIPT_SH += git-rebase.sh\n SCRIPT_SH += git-remote-testgit.sh\n SCRIPT_SH += git-repack.sh\n-SCRIPT_SH += git-request-pull.sh\n SCRIPT_SH += git-stash.sh\n SCRIPT_SH += git-submodule.sh\n SCRIPT_SH += git-web--browse.sh\n@@ -493,6 +492,7 @@ SCRIPT_PYTHON += git-p4.py\n \n SCRIPT_RUBY += git-rb-setup.rb\n SCRIPT_RUBY += git-refs.rb\n+SCRIPT_RUBY += git-request-pull.rb\n \n NO_INSTALL += git-remote-testgit\n NO_INSTALL += git-remote-testpy\ndiff --git a/git-rb-setup.rb b/git-rb-setup.rb\nindex 969278a..f3a2c99 100644\n--- a/git-rb-setup.rb\n+++ b/git-rb-setup.rb\n@@ -9,3 +9,28 @@ end\n def sha1_to_hex(sha1)\n   sha1.unpack('H*').first\n end\n+\n+def pager(msg)\n+  pager = ENV['GIT_PAGER'] || `git var GIT_PAGER`.chomp\n+  system(\"echo -n '#{msg}' | #{pager}\")\n+end\n+\n+class CommandError < RuntimeError\n+\n+  attr_reader :command, :output\n+\n+  def initialize(command, output)\n+     @command = command\n+     @output = output\n+  end\n+\n+  def to_s\n+    Array(@command).join(' ').inspect\n+  end\n+\n+end\n+\n+def run(cmd)\n+  system(cmd)\n+  raise CommandError.new(cmd, nil) unless $?.success?\n+end\ndiff --git a/git-request-pull.rb b/git-request-pull.rb\nnew file mode 100644\nindex 0000000..b6d0156\n--- /dev/null\n+++ b/git-request-pull.rb\n@@ -0,0 +1,153 @@\n+#!/usr/bin/env ruby\n+\n+require_relative 'git-rb-setup'\n+\n+patch = ''\n+\n+ARGV.shift\n+\n+def usage\n+  pager <<EOF\n+usage: git request-pull [options] start url [end]\n+\n+    -p                    show patch text as well\n+\n+EOF\n+  exit 1\n+end\n+\n+until ARGV.empty?\n+  case ARGV.first\n+  when '-p'\n+    patch = '-p'\n+  when '--'\n+    ARGV.shift\n+    break\n+  when /^-/\n+    usage\n+  else\n+    break\n+  end\n+  ARGV.shift\n+end\n+\n+base = ARGV[0]\n+url = ARGV[1]\n+head = ARGV[2] || 'HEAD'\n+status = 0\n+branch_name = nil\n+\n+headref = `git symbolic-ref -q \"#{head}\"`.chomp\n+\n+if system(%[git show-ref -q --verify \"#{headref}\"])\n+  branch_name = headref.gsub(/^refs\\/heads\\//, '')\n+  if branch_name == headref ||\n+    ! system(%[git config \"branch.#{branch_name}.description\" >/dev/null])\n+    branch_name = nil\n+  end\n+end\n+\n+tag_name = `git describe --exact \"#{head}^0\" 2>/dev/null`.chomp\n+\n+usage unless base or url\n+\n+baserev = `git rev-parse --verify --quiet \"#{base}\"^0`.chomp\n+die \"Not a valid revision: #{base}\" if baserev.empty?\n+\n+headrev = `git rev-parse --verify --quiet \"#{head}\"^0`.chomp\n+die \"Not a valid revision: #{head}\" if headrev.empty?\n+\n+merge_base = `git merge-base #{baserev} #{headrev}`.chomp\n+die \"No commits in common between #{base} and #{head}\" unless $?.success?\n+\n+# $head is the token given from the command line, and $tag_name, if\n+# exists, is the tag we are going to show the commit information for.\n+# If that tag exists at the remote and it points at the commit, use it.\n+# Otherwise, if a branch with the same name as $head exists at the remote\n+# and their values match, use that instead.\n+#\n+# Otherwise find a random ref that matches $headrev.\n+find_matching_ref='\n+  sub abbr {\n+    my $ref = shift;\n+    if ($ref =~ s|^refs/heads/|| || $ref =~ s|^refs/tags/|tags/|) {\n+      return $ref;\n+    } else {\n+      return $ref;\n+    }\n+  }\n+\n+  my ($tagged, $branch, $found);\n+  while (<STDIN>) {\n+    my ($sha1, $ref, $deref) = /^(\\S+)\\s+(\\S+?)(\\^\\{\\})?$/;\n+    next unless ($sha1 eq $ARGV[1]);\n+    $found = abbr($ref);\n+    if ($deref && $ref eq \"tags/$ARGV[2]\") {\n+      $tagged = $found;\n+      last;\n+    }\n+    if ($ref =~ m|/\\Q$ARGV[0]\\E$|) {\n+      $exact = $found;\n+    }\n+  }\n+  if ($tagged) {\n+    print \"$tagged\\n\";\n+  } elsif ($exact) {\n+    print \"$exact\\n\";\n+  } elsif ($found) {\n+    print \"$found\\n\";\n+  }\n+'\n+\n+ref = `git ls-remote \"#{url}\" | perl -e '#{find_matching_ref}' \"#{head}\" \"#{headrev}\" \"#{tag_name}\"`.chomp\n+url = `git ls-remote --get-url \"#{url}\"`.chomp\n+\n+begin\n+  run(%[git show -s --format='The following changes since commit %H:\n+\n+  %s (%ci)\n+\n+are available in the git repository at:\n+' #{merge_base}])\n+  puts \"  #{url}\" + (ref.empty? ? \"\" : \" #{ref}\")\n+  run(%[git show -s --format='\n+for you to fetch changes up to %H:\n+\n+  %s (%ci)\n+\n+----------------------------------------------------------------' #{headrev}])\n+\n+  if branch_name\n+    puts \"(from the branch description for #{branch_name} local branch)\"\n+    puts\n+    run(%[git config \"branch.#{branch_name}.description\"])\n+  end\n+\n+  if not tag_name.empty?\n+    if ref.empty? || ref != \"tags/#{tag_name}\"\n+      $stderr.puts \"warn: You locally have #{tag_name} but it does not (yet)\"\n+      $stderr.puts \"warn: appear to be at #{url}\"\n+      $stderr.puts \"warn: Do you want to push it there, perhaps?\"\n+    end\n+    run(%[git cat-file tag \"#{tag_name}\" | sed -n -e '1,/^$/d' -e '/^-----BEGIN PGP /q' -e p])\n+    puts\n+  end\n+\n+  if branch_name or not tag_name.empty?\n+    puts \"----------------------------------------------------------------\"\n+  end\n+\n+  run(%[git shortlog ^#{baserev} #{headrev}])\n+  run(%[git diff -M --stat --summary #{patch} #{merge_base}..#{headrev}])\n+\n+  if ref.empty?\n+    $stderr.puts \"warn: No branch of #{url} is at:\"\n+    run(\"git show -s --format='warn:   %h: %s' #{headrev} >&2\")\n+    $stderr.puts \"warn: Are you sure you pushed '#{head}' there?\"\n+    status = 1\n+  end\n+rescue CommandError\n+  status = 1\n+end\n+\n+exit status\ndiff --git a/git-request-pull.sh b/git-request-pull.sh\ndeleted file mode 100755\nindex ebf1269..0000000\n--- a/git-request-pull.sh\n+++ /dev/null\n@@ -1,162 +0,0 @@\n-#!/bin/sh\n-# Copyright 2005, Ryan Anderson <ryan@michonline.com>\n-#\n-# This file is licensed under the GPL v2, or a later version\n-# at the discretion of Linus Torvalds.\n-\n-USAGE='<start> <url> [<end>]'\n-LONG_USAGE='Summarizes the changes between two commits to the standard output,\n-and includes the given URL in the generated summary.'\n-SUBDIRECTORY_OK='Yes'\n-OPTIONS_KEEPDASHDASH=\n-OPTIONS_SPEC='git request-pull [options] start url [end]\n---\n-p    show patch text as well\n-'\n-\n-. git-sh-setup\n-\n-GIT_PAGER=\n-export GIT_PAGER\n-\n-patch=\n-while\tcase \"$#\" in 0) break ;; esac\n-do\n-\tcase \"$1\" in\n-\t-p)\n-\t\tpatch=-p ;;\n-\t--)\n-\t\tshift; break ;;\n-\t-*)\n-\t\tusage ;;\n-\t*)\n-\t\tbreak ;;\n-\tesac\n-\tshift\n-done\n-\n-base=$1 url=$2 head=${3-HEAD} status=0 branch_name=\n-\n-headref=$(git symbolic-ref -q \"$head\")\n-if git show-ref -q --verify \"$headref\"\n-then\n-\tbranch_name=${headref#refs/heads/}\n-\tif test \"z$branch_name\" = \"z$headref\" ||\n-\t\t! git config \"branch.$branch_name.description\" >/dev/null\n-\tthen\n-\t\tbranch_name=\n-\tfi\n-fi\n-\n-tag_name=$(git describe --exact \"$head^0\" 2>/dev/null)\n-\n-test -n \"$base\" && test -n \"$url\" || usage\n-\n-baserev=$(git rev-parse --verify --quiet \"$base\"^0)\n-if test -z \"$baserev\"\n-then\n-    die \"fatal: Not a valid revision: $base\"\n-fi\n-\n-headrev=$(git rev-parse --verify --quiet \"$head\"^0)\n-if test -z \"$headrev\"\n-then\n-    die \"fatal: Not a valid revision: $head\"\n-fi\n-\n-merge_base=$(git merge-base $baserev $headrev) ||\n-die \"fatal: No commits in common between $base and $head\"\n-\n-# $head is the token given from the command line, and $tag_name, if\n-# exists, is the tag we are going to show the commit information for.\n-# If that tag exists at the remote and it points at the commit, use it.\n-# Otherwise, if a branch with the same name as $head exists at the remote\n-# and their values match, use that instead.\n-#\n-# Otherwise find a random ref that matches $headrev.\n-find_matching_ref='\n-\tsub abbr {\n-\t\tmy $ref = shift;\n-\t\tif ($ref =~ s|^refs/heads/|| || $ref =~ s|^refs/tags/|tags/|) {\n-\t\t\treturn $ref;\n-\t\t} else {\n-\t\t\treturn $ref;\n-\t\t}\n-\t}\n-\n-\tmy ($tagged, $branch, $found);\n-\twhile (<STDIN>) {\n-\t\tmy ($sha1, $ref, $deref) = /^(\\S+)\\s+(\\S+?)(\\^\\{\\})?$/;\n-\t\tnext unless ($sha1 eq $ARGV[1]);\n-\t\t$found = abbr($ref);\n-\t\tif ($deref && $ref eq \"tags/$ARGV[2]\") {\n-\t\t\t$tagged = $found;\n-\t\t\tlast;\n-\t\t}\n-\t\tif ($ref =~ m|/\\Q$ARGV[0]\\E$|) {\n-\t\t\t$exact = $found;\n-\t\t}\n-\t}\n-\tif ($tagged) {\n-\t\tprint \"$tagged\\n\";\n-\t} elsif ($exact) {\n-\t\tprint \"$exact\\n\";\n-\t} elsif ($found) {\n-\t\tprint \"$found\\n\";\n-\t}\n-'\n-\n-ref=$(git ls-remote \"$url\" | perl -e \"$find_matching_ref\" \"$head\" \"$headrev\" \"$tag_name\")\n-\n-url=$(git ls-remote --get-url \"$url\")\n-\n-git show -s --format='The following changes since commit %H:\n-\n-  %s (%ci)\n-\n-are available in the git repository at:\n-' $merge_base &&\n-echo \"  $url${ref+ $ref}\" &&\n-git show -s --format='\n-for you to fetch changes up to %H:\n-\n-  %s (%ci)\n-\n-----------------------------------------------------------------' $headrev &&\n-\n-if test -n \"$branch_name\"\n-then\n-\techo \"(from the branch description for $branch_name local branch)\"\n-\techo\n-\tgit config \"branch.$branch_name.description\"\n-fi &&\n-\n-if test -n \"$tag_name\"\n-then\n-\tif test -z \"$ref\" || test \"$ref\" != \"tags/$tag_name\"\n-\tthen\n-\t\techo >&2 \"warn: You locally have $tag_name but it does not (yet)\"\n-\t\techo >&2 \"warn: appear to be at $url\"\n-\t\techo >&2 \"warn: Do you want to push it there, perhaps?\"\n-\tfi\n-\tgit cat-file tag \"$tag_name\" |\n-\tsed -n -e '1,/^$/d' -e '/^-----BEGIN PGP /q' -e p\n-\techo\n-fi &&\n-\n-if test -n \"$branch_name\" || test -n \"$tag_name\"\n-then\n-\techo \"----------------------------------------------------------------\"\n-fi &&\n-\n-git shortlog ^$baserev $headrev &&\n-git diff -M --stat --summary $patch $merge_base..$headrev || status=1\n-\n-if test -z \"$ref\"\n-then\n-\techo \"warn: No branch of $url is at:\" >&2\n-\tgit show -s --format='warn:   %h: %s' $headrev >&2\n-\techo \"warn: Are you sure you pushed '$head' there?\" >&2\n-\tstatus=1\n-fi\n-exit $status\ndiff --git a/ruby.c b/ruby.c\nindex 7f0cc9d..733215a 100644\n--- a/ruby.c\n+++ b/ruby.c\n@@ -33,6 +33,7 @@ static void git_init(void)\n \n static const char *commands[] = {\n \t\"refs\",\n+\t\"request-pull\",\n };\n \n static void run_ruby_command(int argc, const char **argv)\n-- \n1.8.4-fc\n"},{"id":"228006","messageId":"1379789295-18519-6-git-send-email-felipe.contreras@gmail.com","threadId":"34989","inReplyTo":"1379789295-18519-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH/RFC 5/7] ruby: rewrite perl script","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-21T18:48:13Z","receivedAt":"2013-09-21T18:48:13Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Ruby can do it just fine, no need for perl.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n git-request-pull.rb | 66 ++++++++++++++++++++++++++---------------------------\n 1 file changed, 33 insertions(+), 33 deletions(-)\n\ndiff --git a/git-request-pull.rb b/git-request-pull.rb\nindex b6d0156..6a96a98 100644\n--- a/git-request-pull.rb\n+++ b/git-request-pull.rb\n@@ -67,39 +67,39 @@ die \"No commits in common between #{base} and #{head}\" unless $?.success?\n # and their values match, use that instead.\n #\n # Otherwise find a random ref that matches $headrev.\n-find_matching_ref='\n-  sub abbr {\n-    my $ref = shift;\n-    if ($ref =~ s|^refs/heads/|| || $ref =~ s|^refs/tags/|tags/|) {\n-      return $ref;\n-    } else {\n-      return $ref;\n-    }\n-  }\n-\n-  my ($tagged, $branch, $found);\n-  while (<STDIN>) {\n-    my ($sha1, $ref, $deref) = /^(\\S+)\\s+(\\S+?)(\\^\\{\\})?$/;\n-    next unless ($sha1 eq $ARGV[1]);\n-    $found = abbr($ref);\n-    if ($deref && $ref eq \"tags/$ARGV[2]\") {\n-      $tagged = $found;\n-      last;\n-    }\n-    if ($ref =~ m|/\\Q$ARGV[0]\\E$|) {\n-      $exact = $found;\n-    }\n-  }\n-  if ($tagged) {\n-    print \"$tagged\\n\";\n-  } elsif ($exact) {\n-    print \"$exact\\n\";\n-  } elsif ($found) {\n-    print \"$found\\n\";\n-  }\n-'\n-\n-ref = `git ls-remote \"#{url}\" | perl -e '#{find_matching_ref}' \"#{head}\" \"#{headrev}\" \"#{tag_name}\"`.chomp\n+\n+def abbr(ref)\n+    if (ref =~ /^refs\\/heads\\/(.*)/ || ref =~ /^refs\\/(tags\\/.*)/)\n+      return $1\n+    end\n+    return ref\n+end\n+\n+found = tagged = exact = nil\n+IO.popen(%[git ls-remote \"#{url}\"]) do |out|\n+  out.each do |l|\n+    sha1, ref, deref = l.scan(/^(\\S+)\\s+(\\S+?)(\\^\\{\\})?$/).first\n+    next unless sha1 == headrev\n+    found = abbr(ref)\n+    if (deref && ref == \"tags/#{tag_name}\")\n+      tagged = found\n+      break\n+    end\n+    if (ref =~ /\\/#{Regexp.escape(head)}$/m)\n+      exact = found\n+    end\n+  end\n+end\n+\n+if tagged\n+  ref = tagged\n+elsif exact\n+  ref = exact\n+else\n+  ref = found\n+end\n+\n+ref = '' if ref == nil\n url = `git ls-remote --get-url \"#{url}\"`.chomp\n \n begin\n-- \n1.8.4-fc\n"},{"id":"228007","messageId":"1379789295-18519-7-git-send-email-felipe.contreras@gmail.com","threadId":"34989","inReplyTo":"1379789295-18519-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH/RFC 6/7] ruby: remove one fork","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-21T18:48:14Z","receivedAt":"2013-09-21T18:48:14Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"This is an example of how to start moving out of Git commands, towards\nusing Git's internal library.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n git-request-pull.rb |  8 +++++++-\n ruby.c              | 21 +++++++++++++++++++++\n 2 files changed, 28 insertions(+), 1 deletion(-)\n\ndiff --git a/git-request-pull.rb b/git-request-pull.rb\nindex 6a96a98..fc3175c 100644\n--- a/git-request-pull.rb\n+++ b/git-request-pull.rb\n@@ -37,7 +37,13 @@ head = ARGV[2] || 'HEAD'\n status = 0\n branch_name = nil\n \n-headref = `git symbolic-ref -q \"#{head}\"`.chomp\n+def get_symbolic_ref(refname)\n+  refname, sha1, flags = resolve_ref_unsafe(refname, 0)\n+  return nil if (flags & REF_ISSYMREF) == 0\n+  return refname\n+end\n+\n+headref = get_symbolic_ref(head)\n \n if system(%[git show-ref -q --verify \"#{headref}\"])\n   branch_name = headref.gsub(/^refs\\/heads\\//, '')\ndiff --git a/ruby.c b/ruby.c\nindex 733215a..b4e874d 100644\n--- a/ruby.c\n+++ b/ruby.c\n@@ -26,9 +26,30 @@ static VALUE git_rb_for_each_ref(void)\n \treturn INT2FIX(r);\n }\n \n+static VALUE git_rb_resolve_ref_unsafe(VALUE self, VALUE refname, VALUE reading)\n+{\n+\tVALUE a = rb_ary_new2(3);\n+\tunsigned char sha1[20];\n+\tint flag;\n+\tconst char *r;\n+\n+\tr = resolve_ref_unsafe(RSTRING_PTR(refname), sha1, FIX2INT(reading), &flag);\n+\tif (!r)\n+\t\treturn Qnil;\n+\trb_ary_store(a, 0, rb_str_new2(r));\n+\trb_ary_store(a, 1, sha1_to_str(sha1));\n+\trb_ary_store(a, 2, INT2FIX(flag));\n+\treturn a;\n+}\n+\n static void git_init(void)\n {\n+\trb_define_global_const(\"REF_ISSYMREF\", INT2FIX(REF_ISSYMREF));\n+\trb_define_global_const(\"REF_ISPACKED\", INT2FIX(REF_ISPACKED));\n+\trb_define_global_const(\"REF_ISBROKEN\", INT2FIX(REF_ISBROKEN));\n+\n \trb_define_global_function(\"for_each_ref\", git_rb_for_each_ref, 0);\n+\trb_define_global_function(\"resolve_ref_unsafe\", git_rb_resolve_ref_unsafe, 2);\n }\n \n static const char *commands[] = {\n-- \n1.8.4-fc\n"},{"id":"228008","messageId":"1379789295-18519-8-git-send-email-felipe.contreras@gmail.com","threadId":"34989","inReplyTo":"1379789295-18519-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH/RFC 7/7] ruby: rewrite 'reset'","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-21T18:48:15Z","receivedAt":"2013-09-21T18:48:15Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Purely for demonstration purposes.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n Makefile        |   1 +\n git-rb-setup.rb |  89 ++++++++++++\n git-reset.rb    | 223 ++++++++++++++++++++++++++++++\n git.c           |   1 -\n ruby.c          | 414 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 727 insertions(+), 1 deletion(-)\n create mode 100644 git-reset.rb\n\ndiff --git a/Makefile b/Makefile\nindex cb6bb4e..087b33d 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -493,6 +493,7 @@ SCRIPT_PYTHON += git-p4.py\n SCRIPT_RUBY += git-rb-setup.rb\n SCRIPT_RUBY += git-refs.rb\n SCRIPT_RUBY += git-request-pull.rb\n+SCRIPT_RUBY += git-reset.rb\n \n NO_INSTALL += git-remote-testgit\n NO_INSTALL += git-remote-testpy\ndiff --git a/git-rb-setup.rb b/git-rb-setup.rb\nindex f3a2c99..a789946 100644\n--- a/git-rb-setup.rb\n+++ b/git-rb-setup.rb\n@@ -6,10 +6,25 @@ def die(*args)\n   exit 128\n end\n \n+def warning(*args)\n+  fmt = args.shift\n+  $stderr.printf(\"warning: %s\\n\" % fmt, *args)\n+end\n+\n+def error(*args)\n+  fmt = args.shift\n+  $stderr.printf(\"fatal: %s\\n\" % fmt, *args)\n+  return -1\n+end\n+\n def sha1_to_hex(sha1)\n   sha1.unpack('H*').first\n end\n \n+def git_path(*path)\n+  File.join(get_git_dir, *path)\n+end\n+\n def pager(msg)\n   pager = ENV['GIT_PAGER'] || `git var GIT_PAGER`.chomp\n   system(\"echo -n '#{msg}' | #{pager}\")\n@@ -34,3 +49,77 @@ def run(cmd)\n   system(cmd)\n   raise CommandError.new(cmd, nil) unless $?.success?\n end\n+\n+class SimpleParser\n+  attr_writer :usage\n+\n+  class Option\n+    attr_reader :short, :long, :values, :help\n+\n+    def initialize(short, long, values, help, &block)\n+      @block = block\n+      @short = short\n+      @long = long\n+      @values = values\n+      @help = help\n+    end\n+\n+    def call(v)\n+      @block.call(v)\n+    end\n+  end\n+\n+  def initialize\n+    @list = {}\n+  end\n+\n+  def on(*args, &block)\n+    short = args.shift if args.first.is_a?(String) or args.first == nil\n+    long = args.shift if args.first.is_a?(String)\n+    values = args.shift if args.first.is_a?(Array)\n+    help = args.shift if args.first.is_a?(String)\n+    opt = Option.new(short, long, values, help, &block)\n+    @list[short] = opt if short\n+    @list[long] = opt if long\n+  end\n+\n+  def parse(args = ARGV)\n+    i = 0\n+    if args.member?('-h') or args.member?('--help')\n+      usage\n+      exit! 1\n+    end\n+    while cur = args[i] do\n+      if cur =~ /^(-.+?)(?:=(.*))?$/\n+        opt = @list[$1]\n+        if opt\n+          v = $2\n+          if not v\n+            if not opt.values\n+              extra = true\n+            else\n+              extra = !!opt.values.map(&:to_s).member?(args[i + 1])\n+            end\n+            extra = false\n+            v = extra ? args.delete_at(i + 1) : true\n+          end\n+          opt.call(v)\n+          args.delete_at(i)\n+          next\n+        end\n+      end\n+      i += 1\n+    end\n+  end\n+\n+  def usage\n+    puts 'usage: %s' % @usage\n+    @list.values.uniq.each do |opt|\n+      s = '    '\n+      s << [opt.short, opt.long].compact.join(', ')\n+      s << '%*s%s' % [26 - s.size, '', opt.help] if opt.help\n+      puts s\n+    end\n+  end\n+\n+end\ndiff --git a/git-reset.rb b/git-reset.rb\nnew file mode 100644\nindex 0000000..88697c8\n--- /dev/null\n+++ b/git-reset.rb\n@@ -0,0 +1,223 @@\n+#!/usr/bin/env ruby\n+\n+require_relative 'git-rb-setup'\n+\n+$quiet = false\n+$patch_mode = false\n+\n+def reflog_message(action, rev=nil)\n+  rla = ENV['GIT_REFLOG_ACTION']\n+  if rla\n+    '%s: %s' % [rla, action]\n+  elsif rev\n+    'reset: moving to %s' % rev\n+  else\n+    'reset: %s' % action\n+  end\n+end\n+\n+def update_refs(rev, sha1)\n+  sha1_old_orig = get_sha1('ORIG_HEAD')\n+  old_orig = sha1_old_orig if sha1_old_orig\n+  sha1_orig = get_sha1('HEAD')\n+  if sha1_orig\n+    orig = sha1_orig\n+    msg = reflog_message('updating ORIG_HEAD')\n+    update_ref(msg, 'ORIG_HEAD', orig, old_orig, 0, MSG_ON_ERR)\n+  elsif old_orig\n+    delete_ref('ORIG_HEAD', old_orig, 0)\n+  end\n+  msg = reflog_message('updating HEAD', rev)\n+  return update_ref(msg, 'HEAD', sha1, orig, 0, MSG_ON_ERR)\n+end\n+\n+def is_merge\n+  return test('e', git_path('MERGE_HEAD'))\n+end\n+\n+def parse_args(args)\n+  rev = 'HEAD'\n+  if args[0]\n+    if args[0] == '--'\n+      args.shift\n+    elsif args[1] == '--'\n+      rev = args.shift\n+      args.shift\n+    elsif (!args[1] && get_sha1_committish(args[0])) || (args[1] && get_sha1_treeish(args[0]))\n+      verify_non_filename($prefix, args[0])\n+      rev = args.shift\n+    else\n+      verify_filename($prefix, args[0], 1)\n+    end\n+  end\n+  pathspec = args[0] ? get_pathspec($prefix, args) : []\n+  return [rev, pathspec]\n+end\n+\n+def reset_index(sha1, reset_type)\n+  read_cache_unmerged\n+  opts = {}\n+\n+  case reset_type\n+  when :merge, :keep\n+    opts[:update] = true\n+  when :hard\n+    opts[:update] = true\n+    opts[:reset] = true\n+  else\n+    opts[:reset] = true\n+  end\n+\n+  opts[:verobse] = true unless $quiet\n+\n+  if reset_type == :keep\n+    head_sha1 = get_sha1('HEAD')\n+    return error('You do not have a valid HEAD.') unless head_sha1\n+    opts[:head] = head_sha1\n+  end\n+\n+  if unpack_trees(sha1, opts) != 0\n+    return -1\n+  end\n+\n+  if reset_type == :hard || reset_type == :mixed\n+    tree = parse_tree_indirect(sha1);\n+    prime_cache_tree(nil, tree);\n+  end\n+\n+  return 0\n+end\n+\n+def print_new_head_line(commit)\n+  hex = find_unique_abbrev(commit.sha1, DEFAULT_ABBREV)\n+  print('HEAD is now at %s' % hex)\n+\tmsg = logmsg_reencode(commit, get_log_output_encoding());\n+  _, body = msg.split(\"\\n\\n\", 2)\n+  if body\n+    puts [' ', body.lines.first].join\n+  else\n+    puts\n+  end\n+end\n+\n+def cmd(*args)\n+  args.shift\n+\n+  reset_type = :none\n+\n+  opts = SimpleParser.new\n+  opts.usage = 'git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]'\n+\n+  opts.on('-q', '--quiet', '') do |v|\n+    $quiet = true\n+  end\n+\n+  opts.on(nil, '--hard', 'reset HEAD, index and working tree') do |v|\n+    reset_type = :hard\n+  end\n+\n+  opts.on(nil, '--soft', 'reset only HEAD') do |v|\n+    reset_type = :soft\n+  end\n+\n+  opts.on(nil, '--mixed', 'reset HEAD and index') do |v|\n+    reset_type = :mixed\n+  end\n+\n+  opts.on(nil, '--merge', '') do |v|\n+    reset_type = :merge\n+  end\n+\n+  opts.on(nil, '--keep', '') do |v|\n+    reset_type = :keep\n+  end\n+\n+  opts.on('-p', '--patch', '') do |v|\n+    $patch_mode = true\n+  end\n+\n+  $prefix = setup_git_directory\n+  git_config\n+\n+  opts.parse(args)\n+  rev, pathspec = parse_args(args)\n+\n+  unborn = rev == 'HEAD' && !get_sha1('HEAD')\n+  if unborn\n+    sha1 = EMPTY_TREE_SHA1_BIN\n+  elsif pathspec.empty?\n+    sha1 = get_sha1_committish(rev)\n+    die(\"Failed to resolve '%s' as a valid revision.\" % rev) unless sha1\n+    commit = lookup_commit_reference(sha1)\n+    die(\"Could not parse object '%s'.\" % rev) unless commit\n+    sha1 = commit.sha1\n+  else\n+    sha1 = get_sha1_treeish(rev)\n+    die(\"Failed to resolve '%s' as a valid tree.\" % rev) unless sha1\n+    tree = parse_tree_indirect(sha1)\n+    die(\"Could not parse object '%s'.\", rev) unless tree\n+    sha1 = tree.sha1\n+  end\n+\n+  if $patch_mode\n+    args = []\n+    args << 'add--interactive'\n+    args << '--patch=reset'\n+    args << sha1_to_hex(sha1)\n+    args << '--'\n+    args += pathspec\n+    return run_command(args, RUN_GIT_CMD);\n+  end\n+\n+  if not pathspec.empty?\n+    if reset_type == :mixed\n+      warning(\"--mixed with paths is deprecated; use 'git reset -- <paths>' instead.\")\n+    elsif reset_type != :none\n+      die('Cannot do %s reset with paths.' % reset_type.to_s)\n+    end\n+  end\n+\n+  reset_type = :mixed if reset_type == :none\n+\n+  if reset_type != :soft && reset_type != :mixed\n+    setup_work_tree\n+  end\n+\n+  if reset_type == :mixed && is_bare_repository\n+    die('%s reset is not allowed in a bare repository' % reset_type.to_s);\n+  end\n+\n+  if reset_type == :soft || reset_type == :keep\n+    if is_merge || read_cache < 0 || unmerged_cache != 0\n+      die('Cannot do a %s reset in the middle of a merge.' % reset_type.to_s)\n+    end\n+  end\n+\n+  if reset_type != :soft\n+    do_locked_index(1) do |f|\n+      if reset_type == :mixed\n+        r = read_from_tree(pathspec, sha1)\n+        return 1 if not r\n+        flags = $quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN\n+        refresh_index(flags, nil, 'Unstaged changes after reset:')\n+      else\n+        err = reset_index(sha1, reset_type)\n+        err = reset_index(sha1, :mixed) if reset_type == :keep && err == 0\n+        die(\"Could not reset index file to revision '%s'.\" % rev) if err != 0\n+      end\n+      write_cache(f)\n+    end || die('Could not write new index file.')\n+  end\n+\n+  status = 0\n+  if pathspec.empty? && !unborn\n+    status = update_refs(rev, sha1)\n+    if reset_type == :hard && status == 0 && !$quiet\n+      print_new_head_line(lookup_commit_reference(sha1))\n+    end\n+  end\n+  remove_branch_state if pathspec.empty?\n+  return status\n+end\n+\n+exit cmd(*ARGV)\ndiff --git a/git.c b/git.c\nindex 0e1d97d..777a34a 100644\n--- a/git.c\n+++ b/git.c\n@@ -399,7 +399,6 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"replace\", cmd_replace, RUN_SETUP },\n \t\t{ \"repo-config\", cmd_repo_config, RUN_SETUP_GENTLY },\n \t\t{ \"rerere\", cmd_rerere, RUN_SETUP },\n-\t\t{ \"reset\", cmd_reset, RUN_SETUP },\n \t\t{ \"rev-list\", cmd_rev_list, RUN_SETUP },\n \t\t{ \"rev-parse\", cmd_rev_parse },\n \t\t{ \"revert\", cmd_revert, RUN_SETUP | NEED_WORK_TREE },\ndiff --git a/ruby.c b/ruby.c\nindex b4e874d..b3be386 100644\n--- a/ruby.c\n+++ b/ruby.c\n@@ -1,17 +1,40 @@\n #include \"cache.h\"\n #include \"exec_cmd.h\"\n #include \"refs.h\"\n+#include \"commit.h\"\n+#include \"tree-walk.h\"\n+#include \"unpack-trees.h\"\n+#include \"diff.h\"\n+#include \"diffcore.h\"\n+#include \"branch.h\"\n+#include \"run-command.h\"\n+#include \"cache-tree.h\"\n \n #undef NORETURN\n #undef PATH_SEP\n \n #include <ruby.h>\n \n+static VALUE git_rb_commit;\n+static VALUE git_rb_tree;\n+\n static inline VALUE sha1_to_str(const unsigned char *sha1)\n {\n \treturn rb_str_new((const char *)sha1, 20);\n }\n \n+static inline char *str_to_cstr(VALUE str)\n+{\n+\tif (str == Qnil)\n+\t\treturn NULL;\n+\treturn RSTRING_PTR(str);\n+}\n+\n+static inline unsigned char *str_to_sha1(VALUE str)\n+{\n+\treturn (unsigned char *)str_to_cstr(str);\n+}\n+\n static int for_each_ref_fn(const char *refname, const unsigned char *sha1, int flags, void *cb_data)\n {\n \tVALUE r;\n@@ -42,19 +65,410 @@ static VALUE git_rb_resolve_ref_unsafe(VALUE self, VALUE refname, VALUE reading)\n \treturn a;\n }\n \n+static VALUE git_rb_get_sha1(VALUE self, VALUE name)\n+{\n+\tunsigned char buf[20];\n+\tint r;\n+\tr = get_sha1(RSTRING_PTR(name), buf);\n+\tif (r)\n+\t\treturn Qnil;\n+\treturn sha1_to_str(buf);\n+}\n+\n+static VALUE git_rb_setup_git_directory(VALUE self)\n+{\n+\tconst char *prefix;\n+\tprefix = setup_git_directory();\n+\tif (!prefix)\n+\t\treturn Qnil;\n+\treturn rb_str_new2(prefix);\n+}\n+\n+static VALUE git_rb_setup_work_tree(VALUE self)\n+{\n+\tsetup_work_tree();\n+\treturn Qnil;\n+}\n+\n+static VALUE git_rb_is_bare_repository(VALUE self)\n+{\n+\treturn is_bare_repository() ? Qtrue : Qfalse;\n+}\n+\n+static VALUE git_rb_get_sha1_committish(VALUE self, VALUE str)\n+{\n+\tunsigned char buf[20];\n+\tif (get_sha1_committish(RSTRING_PTR(str), buf))\n+\t\treturn Qnil;\n+\treturn sha1_to_str(buf);\n+}\n+\n+static VALUE git_rb_get_sha1_treeish(VALUE self, VALUE str)\n+{\n+\tunsigned char buf[20];\n+\tif (get_sha1_treeish(RSTRING_PTR(str), buf))\n+\t\treturn Qnil;\n+\treturn sha1_to_str(buf);\n+}\n+\n+static VALUE git_rb_lookup_commit_reference(VALUE self, VALUE id)\n+{\n+\tstruct commit *commit;\n+\tcommit = lookup_commit_reference(str_to_sha1(id));\n+\tif (!commit)\n+\t\treturn Qnil;\n+\treturn Data_Wrap_Struct(git_rb_commit, NULL, NULL, commit);\n+}\n+\n+static VALUE git_rb_commit_sha1(VALUE self)\n+{\n+\tstruct commit *commit;\n+\tData_Get_Struct(self, struct commit, commit);\n+\treturn sha1_to_str(commit->object.sha1);\n+}\n+\n+static VALUE git_rb_commit_buffer(VALUE self)\n+{\n+\tstruct commit *commit;\n+\tData_Get_Struct(self, struct commit, commit);\n+\treturn rb_str_new2(commit->buffer);\n+}\n+\n+static VALUE git_rb_parse_tree_indirect(VALUE self, VALUE id)\n+{\n+\tstruct tree *tree;\n+\ttree = parse_tree_indirect(str_to_sha1(id));\n+\tif (!tree)\n+\t\treturn Qnil;\n+\treturn Data_Wrap_Struct(git_rb_tree, NULL, NULL, tree);\n+}\n+\n+static VALUE git_rb_tree_sha1(VALUE self)\n+{\n+\tstruct tree *tree;\n+\tData_Get_Struct(self, struct tree, tree);\n+\treturn sha1_to_str(tree->object.sha1);\n+}\n+\n+static VALUE git_rb_unpack_trees(VALUE self, VALUE sha1, VALUE uopts)\n+{\n+\tstruct tree_desc desc[2];\n+\tstruct unpack_trees_options opts;\n+\tint r;\n+\tint nr = 1;\n+\tVALUE head;\n+\n+\tmemset(&opts, 0, sizeof(opts));\n+\n+\topts.head_idx = 1;\n+\topts.src_index = &the_index;\n+\topts.dst_index = &the_index;\n+\topts.fn = oneway_merge;\n+\topts.merge = 1;\n+\n+\tif (rb_hash_lookup(uopts, ID2SYM(rb_intern(\"update\"))) == Qtrue)\n+\t\topts.update = 1;\n+\tif (rb_hash_lookup(uopts, ID2SYM(rb_intern(\"reset\"))) == Qtrue)\n+\t\topts.reset = 1;\n+\tif (rb_hash_lookup(uopts, ID2SYM(rb_intern(\"verbose\"))) == Qtrue)\n+\t\topts.verbose_update = 1;\n+\n+\thead = rb_hash_lookup(uopts, ID2SYM(rb_intern(\"head\")));\n+\tif (head != Qnil) {\n+\t\tfill_tree_descriptor(desc, str_to_sha1(head));\n+\t\topts.fn = twoway_merge;\n+\t\tnr++;\n+\t}\n+\n+\tfill_tree_descriptor(desc + nr - 1, str_to_sha1(sha1));\n+\tr = unpack_trees(nr, desc, &opts);\n+\treturn INT2NUM(r);\n+}\n+\n+static VALUE git_rb_read_cache_unmerged(VALUE self)\n+{\n+\tread_cache_unmerged();\n+\treturn Qnil;\n+}\n+\n+static VALUE git_rb_read_cache(VALUE self)\n+{\n+\tint r;\n+\tr = read_cache();\n+\treturn INT2NUM(r);\n+}\n+\n+static VALUE git_rb_unmerged_cache(VALUE self)\n+{\n+\tint r;\n+\tr = unmerged_cache();\n+\treturn INT2NUM(r);\n+}\n+\n+static void update_index_from_diff(struct diff_queue_struct *q,\n+\t\tstruct diff_options *opt, void *data)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < q->nr; i++) {\n+\t\tstruct diff_filespec *one = q->queue[i]->one;\n+\t\tif (one->mode && !is_null_sha1(one->sha1)) {\n+\t\t\tstruct cache_entry *ce;\n+\t\t\tce = make_cache_entry(one->mode, one->sha1, one->path,\n+\t\t\t\t0, 0);\n+\t\t\tif (!ce)\n+\t\t\t\tdie(_(\"make_cache_entry failed for path '%s'\"),\n+\t\t\t\t    one->path);\n+\t\t\tadd_cache_entry(ce, ADD_CACHE_OK_TO_ADD |\n+\t\t\t\tADD_CACHE_OK_TO_REPLACE);\n+\t\t} else\n+\t\t\tremove_file_from_cache(one->path);\n+\t}\n+}\n+\n+static VALUE git_rb_read_from_tree(VALUE self, VALUE paths, VALUE tree_sha1)\n+{\n+\tstruct diff_options opt;\n+\tconst char **pathspec = NULL;\n+\n+\tif (paths != Qnil && RARRAY_LEN(paths) > 0) {\n+\t\tint i;\n+\t\tVALUE *cpaths = RARRAY_PTR(paths);\n+\t\tpathspec = xcalloc(RARRAY_LEN(paths) + 1, sizeof(*pathspec));\n+\t\tfor (i = 0; i < RARRAY_LEN(paths); i++)\n+\t\t\tpathspec[i] = RSTRING_PTR(cpaths[i]);\n+\t\tpathspec[i] = NULL;\n+\t}\n+\n+\tmemset(&opt, 0, sizeof(opt));\n+\tdiff_tree_setup_paths(pathspec, &opt);\n+\topt.output_format = DIFF_FORMAT_CALLBACK;\n+\topt.format_callback = update_index_from_diff;\n+\n+\tread_cache();\n+\tif (do_diff_cache(str_to_sha1(tree_sha1), &opt))\n+\t\treturn Qfalse;\n+\tdiffcore_std(&opt);\n+\tdiff_flush(&opt);\n+\tdiff_tree_release_paths(&opt);\n+\n+\treturn Qtrue;\n+}\n+\n+static VALUE git_rb_refresh_index(VALUE self, VALUE flags, VALUE seen, VALUE header_msg)\n+{\n+\tint r;\n+\tr = refresh_index(&the_index, FIX2INT(flags), NULL, NULL, str_to_cstr(header_msg));\n+\treturn INT2NUM(r);\n+}\n+\n+static VALUE git_rb_update_ref(VALUE self, VALUE action, VALUE refname, VALUE sha1, VALUE oldval, VALUE flags, VALUE onerr)\n+{\n+\tint r;\n+\tr = update_ref(RSTRING_PTR(action), RSTRING_PTR(refname), str_to_sha1(sha1), str_to_sha1(oldval),\n+\t\t\tNUM2INT(flags), FIX2INT(onerr));\n+\treturn INT2NUM(r);\n+}\n+\n+static VALUE git_rb_delete_ref(VALUE self, VALUE refname, VALUE sha1, VALUE delopt)\n+{\n+\tint r;\n+\tr = delete_ref(RSTRING_PTR(refname), str_to_sha1(sha1), NUM2INT(delopt));\n+\treturn INT2NUM(r);\n+}\n+\n+static VALUE git_rb_remove_branch_state(VALUE self)\n+{\n+\tremove_branch_state();\n+\treturn Qnil;\n+}\n+\n+static VALUE git_rb_write_cache(VALUE self, VALUE fd)\n+{\n+\tint r;\n+\tr = write_index(&the_index, NUM2INT(fd));\n+\treturn INT2NUM(r);\n+}\n+\n+static VALUE git_rb_get_index_file(VALUE self)\n+{\n+\tchar *file;\n+\tfile = get_index_file();\n+\treturn rb_str_new2(file);\n+}\n+\n+static VALUE git_rb_do_locked_index(VALUE self, VALUE die_on_error)\n+{\n+\tstruct lock_file *lock = xcalloc(1, sizeof(*lock));\n+\tint fd, cr;\n+\tVALUE r;\n+\n+\tfd = hold_locked_index(lock, NUM2INT(die_on_error));\n+\tr = rb_yield(INT2NUM(fd));\n+\tcr = NUM2INT(r);\n+\tif (cr == 0)\n+\t\tcr = commit_locked_index(lock);\n+\treturn cr == 0 ? Qtrue : Qfalse;\n+}\n+\n+static VALUE git_rb_verify_filename(VALUE self, VALUE prefix, VALUE arg, VALUE diagnose_misspelt_rev)\n+{\n+\tverify_filename(str_to_cstr(prefix), str_to_cstr(arg), NUM2INT(diagnose_misspelt_rev));\n+\treturn Qnil;\n+}\n+\n+static VALUE git_rb_verify_non_filename(VALUE self, VALUE prefix, VALUE arg)\n+{\n+\tverify_non_filename(str_to_cstr(prefix), str_to_cstr(arg));\n+\treturn Qnil;\n+}\n+\n+static VALUE git_rb_git_config(VALUE self)\n+{\n+\tgit_config(git_default_config, NULL);\n+\treturn Qnil;\n+}\n+\n+static VALUE git_rb_run_command(VALUE self, VALUE args, VALUE opt)\n+{\n+\tconst char **argv;\n+\tint i, r;\n+\tVALUE *cargs;\n+\n+\tcargs = RARRAY_PTR(args);\n+\targv = xcalloc(RARRAY_LEN(args) + 1, sizeof(*argv));\n+\tfor (i = 0; i < RARRAY_LEN(args); i++)\n+\t\targv[i] = RSTRING_PTR(cargs[i]);\n+\targv[i] = NULL;\n+\n+\tr = run_command_v_opt(argv, FIX2INT(opt));\n+\treturn INT2NUM(r);\n+}\n+\n+static VALUE git_rb_prime_cache_tree(VALUE self, VALUE cache, VALUE rtree)\n+{\n+\tstruct tree *tree;\n+\tData_Get_Struct(rtree, struct tree, tree);\n+\tprime_cache_tree(&active_cache_tree, tree);\n+\treturn Qnil;\n+}\n+\n+static VALUE git_rb_get_pathspec(VALUE self, VALUE prefix, VALUE pathspec)\n+{\n+\tconst char **dst, **src;\n+\tVALUE *rsrc, *rdst;\n+\tint i, c;\n+\n+\tc = RARRAY_LEN(pathspec);\n+\trsrc = RARRAY_PTR(pathspec);\n+\n+\tsrc = xcalloc(c + 1, sizeof(*src));\n+\tfor (i = 0; i < c; i++)\n+\t\tsrc[i] = RSTRING_PTR(rsrc[i]);\n+\tsrc[i] = NULL;\n+\n+\tdst = get_pathspec(str_to_cstr(prefix), src);\n+\n+\trdst = xcalloc(c, sizeof(*rdst));\n+\tfor (i = 0; i < c; i++)\n+\t\trdst[i] = rb_str_new2(dst[i]);\n+\n+\treturn rb_ary_new4(c, rdst);\n+}\n+\n+static VALUE git_rb_get_git_dir(VALUE self)\n+{\n+\treturn rb_str_new2(get_git_dir());\n+}\n+\n+static VALUE git_rb_find_unique_abbrev(VALUE self, VALUE sha1, VALUE len)\n+{\n+\tconst char *abbrev;\n+\tabbrev = find_unique_abbrev(str_to_sha1(sha1), NUM2INT(len));\n+\treturn rb_str_new2(abbrev);\n+}\n+\n+static VALUE git_rb_get_log_output_encoding(VALUE self)\n+{\n+\treturn rb_str_new2(get_log_output_encoding());\n+}\n+\n+static VALUE git_rb_logmsg_reencode(VALUE self, VALUE commit, VALUE output_encoding)\n+{\n+\tstruct commit *g_commit;\n+\tchar *str;\n+\n+\tData_Get_Struct(commit, struct commit, g_commit);\n+\tstr = logmsg_reencode(g_commit, NULL, RSTRING_PTR(output_encoding));\n+\treturn rb_str_new2(str);\n+}\n+\n static void git_init(void)\n {\n+\tVALUE mod, tmp;\n+\n+\tmod = rb_define_module(\"Git\");\n+\n \trb_define_global_const(\"REF_ISSYMREF\", INT2FIX(REF_ISSYMREF));\n \trb_define_global_const(\"REF_ISPACKED\", INT2FIX(REF_ISPACKED));\n \trb_define_global_const(\"REF_ISBROKEN\", INT2FIX(REF_ISBROKEN));\n \n+\trb_define_global_const(\"MSG_ON_ERR\", INT2FIX(MSG_ON_ERR));\n+\trb_define_global_const(\"REFRESH_QUIET\", INT2FIX(REFRESH_QUIET));\n+\trb_define_global_const(\"REFRESH_IN_PORCELAIN\", INT2FIX(REFRESH_IN_PORCELAIN));\n+\trb_define_global_const(\"RUN_GIT_CMD\", INT2FIX(RUN_GIT_CMD));\n+\trb_define_global_const(\"DEFAULT_ABBREV\", INT2FIX(DEFAULT_ABBREV));\n+\n+\ttmp = rb_obj_freeze(rb_str_new((const char *)EMPTY_TREE_SHA1_BIN, 20));\n+\trb_define_global_const(\"EMPTY_TREE_SHA1_BIN\", tmp);\n+\n+\tgit_rb_commit = rb_define_class_under(mod, \"Commit\", rb_cData);\n+\trb_define_method(git_rb_commit, \"sha1\", git_rb_commit_sha1, 0);\n+\trb_define_method(git_rb_commit, \"buffer\", git_rb_commit_buffer, 0);\n+\n+\tgit_rb_tree = rb_define_class_under(mod, \"Tree\", rb_cData);\n+\trb_define_method(git_rb_tree, \"sha1\", git_rb_tree_sha1, 0);\n+\n \trb_define_global_function(\"for_each_ref\", git_rb_for_each_ref, 0);\n \trb_define_global_function(\"resolve_ref_unsafe\", git_rb_resolve_ref_unsafe, 2);\n+\n+\trb_define_global_function(\"get_sha1\", git_rb_get_sha1, 1);\n+\trb_define_global_function(\"setup_git_directory\", git_rb_setup_git_directory, 0);\n+\trb_define_global_function(\"setup_work_tree\", git_rb_setup_work_tree, 0);\n+\trb_define_global_function(\"is_bare_repository\", git_rb_is_bare_repository, 0);\n+\trb_define_global_function(\"get_sha1_committish\", git_rb_get_sha1_committish, 1);\n+\trb_define_global_function(\"get_sha1_treeish\", git_rb_get_sha1_treeish, 1);\n+\trb_define_global_function(\"lookup_commit_reference\", git_rb_lookup_commit_reference, 1);\n+\trb_define_global_function(\"parse_tree_indirect\", git_rb_parse_tree_indirect, 1);\n+\n+\trb_define_global_function(\"read_cache_unmerged\", git_rb_read_cache_unmerged, 0);\n+\trb_define_global_function(\"unpack_trees\", git_rb_unpack_trees, 2);\n+\trb_define_global_function(\"read_cache\", git_rb_read_cache, 0);\n+\trb_define_global_function(\"unmerged_cache\", git_rb_unmerged_cache, 0);\n+\trb_define_global_function(\"read_from_tree\", git_rb_read_from_tree, 2);\n+\trb_define_global_function(\"update_ref\", git_rb_update_ref, 6);\n+\trb_define_global_function(\"delete_ref\", git_rb_delete_ref, 3);\n+\trb_define_global_function(\"remove_branch_state\", git_rb_remove_branch_state, 0);\n+\trb_define_global_function(\"write_cache\", git_rb_write_cache, 1);\n+\trb_define_global_function(\"get_index_file\", git_rb_get_index_file, 0);\n+\trb_define_global_function(\"do_locked_index\", git_rb_do_locked_index, 1);\n+\trb_define_global_function(\"refresh_index\", git_rb_refresh_index, 3);\n+\trb_define_global_function(\"verify_filename\", git_rb_verify_filename, 3);\n+\trb_define_global_function(\"verify_non_filename\", git_rb_verify_non_filename, 2);\n+\trb_define_global_function(\"git_config\", git_rb_git_config, 0);\n+\trb_define_global_function(\"run_command\", git_rb_run_command, 2);\n+\trb_define_global_function(\"prime_cache_tree\", git_rb_prime_cache_tree, 2);\n+\trb_define_global_function(\"get_pathspec\", git_rb_get_pathspec, 2);\n+\trb_define_global_function(\"get_git_dir\", git_rb_get_git_dir, 0);\n+\trb_define_global_function(\"find_unique_abbrev\", git_rb_find_unique_abbrev, 2);\n+\trb_define_global_function(\"get_log_output_encoding\", git_rb_get_log_output_encoding, 0);\n+\trb_define_global_function(\"logmsg_reencode\", git_rb_logmsg_reencode, 2);\n }\n \n static const char *commands[] = {\n \t\"refs\",\n \t\"request-pull\",\n+\t\"reset\",\n };\n \n static void run_ruby_command(int argc, const char **argv)\n-- \n1.8.4-fc\n"},{"id":"228015","messageId":"20130921212904.GA235845@vauxhall.crustytoothpaste.net","threadId":"34989","inReplyTo":"1379789295-18519-1-git-send-email-felipe.contreras@gmail.com","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2013-09-21T21:29:05Z","receivedAt":"2013-09-21T21:29:05Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Sat, Sep 21, 2013 at 01:48:08PM -0500, Felipe Contreras wrote:\n> Hi,\n> \n> It was discussed before that there was a need to replace Git scripts\n> from perl and sh that utilize the 'git' binary to do everything they\n> need, which requires many forks, and that creates problems on\n> platforms like Windows.\n> \n> This is a first step meant to show how a solution using Ruby would look like.\n> \n> Other alternatives just don't cut it. Shell scripts are too simple, and\n> invariably require forks. Perl could use Git's internal C code, but it's syntax\n> is too cumbersome and it's loosing more and more popularity. Python and Ruby\n> are the only modern languages that could fit all the needs, but Python's syntax\n> is not ideal, specially considering the background of the Git community, and\n> also, Ruby's C extensibility is simply superb.\n> \n> This patch series introduces Ruby bindings for Git's C internal library, and\n> add example commands to show how it could be used, and how it resembles the\n> original C code, shell code, and perl code. Basically, Ruby fits like a glove.\n\nA couple of things: first, I'm not opposed in principle to using Ruby\nfor git.  As you say, it's a good language and it has much nicer C\nbindings.\n\nAs Junio has also pointed out in the past, there are people who aren't\nable to use Ruby in the same way that they are Perl and Python.  If it's\nannounced now, Git 2.0 might be a good time to start accepting Ruby\nscripts, as that will give people time to plan for its inclusion.\n\nOn a more technical note, my objection to your binding implementation is\nthat fundamentally, Ruby is an object-oriented language, but your\nbindings don't take advantage of that; they're completely procedural.  I\nrealize most of the git codebase is as well, but that's because it's\nwritten in C.  It seems a shame not to take advantage of what the\nlanguage offers, especially since I know others are going to want to\ntake advantage of the provided bindings.\n\n-- \nbrian m. carlson / brian with sandals: Houston, Texas, US\n+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only\nOpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187\n"},{"id":"228017","messageId":"CAMP44s3Shdg40go-WyGV8QKwEGoXg8hvEe8tetMyxvx5Sb7evw@mail.gmail.com","threadId":"34989","inReplyTo":"20130921212904.GA235845@vauxhall.crustytoothpaste.net","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-21T22:52:05Z","receivedAt":"2013-09-21T22:52:05Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Sat, Sep 21, 2013 at 4:29 PM, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> On Sat, Sep 21, 2013 at 01:48:08PM -0500, Felipe Contreras wrote:\n>> Hi,\n>>\n>> It was discussed before that there was a need to replace Git scripts\n>> from perl and sh that utilize the 'git' binary to do everything they\n>> need, which requires many forks, and that creates problems on\n>> platforms like Windows.\n>>\n>> This is a first step meant to show how a solution using Ruby would look like.\n>>\n>> Other alternatives just don't cut it. Shell scripts are too simple, and\n>> invariably require forks. Perl could use Git's internal C code, but it's syntax\n>> is too cumbersome and it's loosing more and more popularity. Python and Ruby\n>> are the only modern languages that could fit all the needs, but Python's syntax\n>> is not ideal, specially considering the background of the Git community, and\n>> also, Ruby's C extensibility is simply superb.\n>>\n>> This patch series introduces Ruby bindings for Git's C internal library, and\n>> add example commands to show how it could be used, and how it resembles the\n>> original C code, shell code, and perl code. Basically, Ruby fits like a glove.\n>\n> A couple of things: first, I'm not opposed in principle to using Ruby\n> for git.  As you say, it's a good language and it has much nicer C\n> bindings.\n>\n> As Junio has also pointed out in the past, there are people who aren't\n> able to use Ruby in the same way that they are Perl and Python.  If it's\n> announced now, Git 2.0 might be a good time to start accepting Ruby\n> scripts, as that will give people time to plan for its inclusion.\n\nYes, and there are people who aren't able to use Perl/Python in the\nsame way they use Ruby. That's why I tried to show why Ruby makes a\nperfect choice.\n\n> On a more technical note, my objection to your binding implementation is\n> that fundamentally, Ruby is an object-oriented language, but your\n> bindings don't take advantage of that; they're completely procedural.  I\n> realize most of the git codebase is as well, but that's because it's\n> written in C.  It seems a shame not to take advantage of what the\n> language offers, especially since I know others are going to want to\n> take advantage of the provided bindings.\n\nFor the moment the bindings are only for Git commands, so the primary\nusers are Git developers, that's why I tried to leave them close to\nthe current C/shell/perl code.\n\nHaving said that, it does use a little bit of object-oriented stuff:\n\n  commit = lookup_commit_reference(sha1)\n  p commit.buffer\n\nNow, if anybody has ideas into how the bindings could be more object\noriented, I'm all ears, but unfortunately what I foresee is that\nnobody will consider this proposal seriously.\n\nCheers.\n\n-- \nFelipe Contreras\n"},{"id":"228018","messageId":"20130921235647.GC235845@vauxhall.crustytoothpaste.net","threadId":"34989","inReplyTo":"CAMP44s3Shdg40go-WyGV8QKwEGoXg8hvEe8tetMyxvx5Sb7evw@mail.gmail.com","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2013-09-21T23:56:48Z","receivedAt":"2013-09-21T23:56:48Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Sat, Sep 21, 2013 at 05:52:05PM -0500, Felipe Contreras wrote:\n> On Sat, Sep 21, 2013 at 4:29 PM, brian m. carlson\n> <sandals@crustytoothpaste.net> wrote:\n> > As Junio has also pointed out in the past, there are people who aren't\n> > able to use Ruby in the same way that they are Perl and Python.  If it's\n> > announced now, Git 2.0 might be a good time to start accepting Ruby\n> > scripts, as that will give people time to plan for its inclusion.\n> \n> Yes, and there are people who aren't able to use Perl/Python in the\n> same way they use Ruby. That's why I tried to show why Ruby makes a\n> perfect choice.\n\nI'm not arguing against Ruby.  As I said, it's a nice language.  I'm\njust saying that Ruby is not as common as Perl and Python.  For example,\nin Debian, Perl is Essential (cannot be removed), Python is priority\nstandard, and Ruby is priority optional.\n\nI think it's a bad idea to introduce an entirely new runtime, especially\none known to occasionally blow up on less-common architectures, without\nsome advance notice.  For example, at work I would not be able to deploy\na git using Ruby immediately because Git is an RPM and Ruby is compiled\nfrom source, if it is even present at all.\n\nAlso, the only Python script that is shipped with Git is git-p4, which\nis essentially optional, since most git users probably do not use\nPerforce.  Otherwise, all the scripts in git are shell or Perl.  So this\nwould be adding a significant additional dependency to core git, one\nwhich is likely not installed on many systems.  Of the systems in the\nDebian popularity contest, 41% have git installed and 23% have ruby1.8\ninstalled, with only 16% having the default ruby installed.\n\n> Now, if anybody has ideas into how the bindings could be more object\n> oriented, I'm all ears, but unfortunately what I foresee is that\n> nobody will consider this proposal seriously.\n\nMy concern is that the Ruby code will end up not being idiomatic, and\npeople will view it as bizarre and unmaintainable.\n\nfor_each_ref could end up being something like REPOSITORY.refs.each,\nwhich would be more idiomatic.  repository.refs would probably be an\nEnumerator in that case.  If the decision is made to incorporate Ruby\ncode, I'm happy to submit some patches to help provide a sane interface,\neven though I'm not that familiar with Ruby.\n\n-- \nbrian m. carlson / brian with sandals: Houston, Texas, US\n+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only\nOpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187\n"},{"id":"228026","messageId":"523e81f338f1e_547c41e7c166be@nysa.mail","threadId":"34989","inReplyTo":"20130921235647.GC235845@vauxhall.crustytoothpaste.net","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-22T05:36:51Z","receivedAt":"2013-09-22T05:36:51Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"brian m. carlson wrote:\n> On Sat, Sep 21, 2013 at 05:52:05PM -0500, Felipe Contreras wrote:\n> > On Sat, Sep 21, 2013 at 4:29 PM, brian m. carlson\n> > <sandals@crustytoothpaste.net> wrote:\n> > > As Junio has also pointed out in the past, there are people who aren't\n> > > able to use Ruby in the same way that they are Perl and Python.  If it's\n> > > announced now, Git 2.0 might be a good time to start accepting Ruby\n> > > scripts, as that will give people time to plan for its inclusion.\n> > \n> > Yes, and there are people who aren't able to use Perl/Python in the\n> > same way they use Ruby. That's why I tried to show why Ruby makes a\n> > perfect choice.\n> \n> I'm not arguing against Ruby.  As I said, it's a nice language.  I'm\n> just saying that Ruby is not as common as Perl and Python.\n\nIn my books Perl is only a tiny bit more common than Ruby.\n\nhttp://www.tiobe.com/content/paperinfo/tpci/index.html\n\n> I think it's a bad idea to introduce an entirely new runtime, especially\n> one known to occasionally blow up on less-common architectures, without\n> some advance notice.\n\nThis is just FUD. What do you mean blow up on less-common architectures? Do you\nhave actual evidence or can we just dismiss that as a baseless argument?\n\n> For example, at work I would not be able to deploy a git using Ruby\n> immediately because Git is an RPM and Ruby is compiled from source, if it is\n> even present at all.\n\nAgain, what do you mean? In all the distributions I've seen, vim is compiled\nwith Ruby support by default, so unless you think vim is an essoteric package,\nlibruby is almost definetly packaged and available.\n\n> Also, the only Python script that is shipped with Git is git-p4, which\n> is essentially optional, since most git users probably do not use\n> Perforce. Otherwise, all the scripts in git are shell or Perl.\n\nNeither perl, nor shell, nor python scripts solve the forking problem. My\nproposal does.\n\n> So this would be adding a significant additional dependency to core git, one\n> which is likely not installed on many systems.\n\nAnother claim without a shred of evidence. It's the other way around, it's\nlikely already installed, and it would not be an additional dependency if the\ncurrent scripts get phased out in favor Ruby ones, or even better, C code.\n\n> Of the systems in the Debian popularity contest, 41% have git installed and\n> 23% have ruby1.8 installed, with only 16% having the default ruby installed.\n\nPlus the 17% of ruby1.9.1, you get 41%, exactly the same as Git.\n\nBut we don't need ruby, all we need is libruby, which is 47%.\n\n> > Now, if anybody has ideas into how the bindings could be more object\n> > oriented, I'm all ears, but unfortunately what I foresee is that\n> > nobody will consider this proposal seriously.\n> \n> My concern is that the Ruby code will end up not being idiomatic, and\n> people will view it as bizarre and unmaintainable.\n\nThere is no such thing as idiomatic Ruby code. In Ruby there's no single best\nway to do something, there's many ways to do the same thing.\n\n> for_each_ref could end up being something like REPOSITORY.refs.each,\n> which would be more idiomatic.\n\nAnd how do you propose to achieve that if the C code doesn't support that?\n\nDo you have in mind the C code that would achieve that, or are you just saying?\n\n-- \nFelipe Contreras\n"},{"id":"228027","messageId":"20130922073120.GC13262@paksenarrion.iveqy.com","threadId":"34989","inReplyTo":"523e81f338f1e_547c41e7c166be@nysa.mail","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Fredrik Gustafsson","fromEmail":"iveqy@iveqy.com","sentAt":"2013-09-22T07:31:20Z","receivedAt":"2013-09-22T07:31:20Z","isPatch":true,"sender":{"key":"iveqy@iveqy.com","avatar":"https://avatars.githubusercontent.com/u/761743?v=4"},"body":"On Sun, Sep 22, 2013 at 12:36:51AM -0500, Felipe Contreras wrote:\n> > I think it's a bad idea to introduce an entirely new runtime, especially\n> > one known to occasionally blow up on less-common architectures, without\n> > some advance notice.\n> \n> This is just FUD. What do you mean blow up on less-common architectures? Do you\n> have actual evidence or can we just dismiss that as a baseless argument?\n> \n> > For example, at work I would not be able to deploy a git using Ruby\n> > immediately because Git is an RPM and Ruby is compiled from source, if it is\n> > even present at all.\n> \n> Again, what do you mean? In all the distributions I've seen, vim is compiled\n> with Ruby support by default, so unless you think vim is an essoteric package,\n> libruby is almost definetly packaged and available.\n\nIt would actually be usefull to know stats on where git is runned. In my\nworld of embedded computing, ruby support definitely isn't a standard,\nnor is glibc.\n\nAs for architecture speaking I think it's important that git works on\nARM since that architecture increases on the server market. I've no idea\nif this is a problem with ruby or not.\n\n> \n> > Also, the only Python script that is shipped with Git is git-p4, which\n> > is essentially optional, since most git users probably do not use\n> > Perforce. Otherwise, all the scripts in git are shell or Perl.\n> \n> Neither perl, nor shell, nor python scripts solve the forking problem. My\n> proposal does.\n\nIt does, and so does Lua, which can be bundled with git and used in the\nconfiguration files as well and is pure ansi C. However bundling\nsomething has it bad sides too. At least this will solve the dependency\nproblem. So let the language war begin =).\n\n-- \nMed vänliga hälsningar\nFredrik Gustafsson\n\ntel: 0733-608274\ne-post: iveqy@iveqy.com\n"},{"id":"228028","messageId":"CAMP44s0Lww+se6iA2NWSwkeuLdR9mc0ppnVBSjWu4d73YeP6oA@mail.gmail.com","threadId":"34989","inReplyTo":"20130922073120.GC13262@paksenarrion.iveqy.com","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-22T07:43:39Z","receivedAt":"2013-09-22T07:43:39Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Sun, Sep 22, 2013 at 2:31 AM, Fredrik Gustafsson <iveqy@iveqy.com> wrote:\n> On Sun, Sep 22, 2013 at 12:36:51AM -0500, Felipe Contreras wrote:\n>> > I think it's a bad idea to introduce an entirely new runtime, especially\n>> > one known to occasionally blow up on less-common architectures, without\n>> > some advance notice.\n>>\n>> This is just FUD. What do you mean blow up on less-common architectures? Do you\n>> have actual evidence or can we just dismiss that as a baseless argument?\n>>\n>> > For example, at work I would not be able to deploy a git using Ruby\n>> > immediately because Git is an RPM and Ruby is compiled from source, if it is\n>> > even present at all.\n>>\n>> Again, what do you mean? In all the distributions I've seen, vim is compiled\n>> with Ruby support by default, so unless you think vim is an essoteric package,\n>> libruby is almost definetly packaged and available.\n>\n> It would actually be usefull to know stats on where git is runned. In my\n> world of embedded computing, ruby support definitely isn't a standard,\n> nor is glibc.\n\nI come from the embedded world as well, and I've never seen Git used there.\n\nI'd say Windows support is much more important than embedded, and we\nare not supporting that properly.\n\n>> > Also, the only Python script that is shipped with Git is git-p4, which\n>> > is essentially optional, since most git users probably do not use\n>> > Perforce. Otherwise, all the scripts in git are shell or Perl.\n>>\n>> Neither perl, nor shell, nor python scripts solve the forking problem. My\n>> proposal does.\n>\n> It does,\n\nNo, it does not. All the **current** perl/shell/python scripts use\n'git foo' commands to achieve everything.\n\n> and so does Lua,\n\nThere is no lua in Git.\n\n> which can be bundled with git and used in the\n> configuration files as well and is pure ansi C. However bundling\n> something has it bad sides too. At least this will solve the dependency\n> problem. So let the language war begin =).\n\nTalk is cheap, show me the code.\n\n-- \nFelipe Contreras\n"},{"id":"228029","messageId":"20130922081250.GD13262@paksenarrion.iveqy.com","threadId":"34989","inReplyTo":"CAMP44s0Lww+se6iA2NWSwkeuLdR9mc0ppnVBSjWu4d73YeP6oA@mail.gmail.com","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Fredrik Gustafsson","fromEmail":"iveqy@iveqy.com","sentAt":"2013-09-22T08:12:50Z","receivedAt":"2013-09-22T08:12:50Z","isPatch":true,"sender":{"key":"iveqy@iveqy.com","avatar":"https://avatars.githubusercontent.com/u/761743?v=4"},"body":"On Sun, Sep 22, 2013 at 02:43:39AM -0500, Felipe Contreras wrote:\n> > It would actually be usefull to know stats on where git is runned. In my\n> > world of embedded computing, ruby support definitely isn't a standard,\n> > nor is glibc.\n> \n> I come from the embedded world as well, and I've never seen Git used there.\n> \n> I'd say Windows support is much more important than embedded, and we\n> are not supporting that properly.\n\nMe neither, it doesn't mean that it isn't used though... I agree with\nthe lack of windows support from git.git. However since Microsoft\nworking with libgit2 on a Visual Studio plugin this it might be that the\nneed for windows support decreases.\n\n> \n> >> > Also, the only Python script that is shipped with Git is git-p4, which\n> >> > is essentially optional, since most git users probably do not use\n> >> > Perforce. Otherwise, all the scripts in git are shell or Perl.\n> >>\n> >> Neither perl, nor shell, nor python scripts solve the forking problem. My\n> >> proposal does.\n> >\n> > It does,\n> \n> No, it does not. All the **current** perl/shell/python scripts use\n> 'git foo' commands to achieve everything.\n\nAs I said, \"It does\" meaning \"Your solution solves the forking problem\".\n\n> \n> > and so does Lua,\n> \n> There is no lua in Git.\n\nThere's no ruby in git either as far as I know... (and no, I don't think\ncontrib/ counts).\n\n> \n> > which can be bundled with git and used in the\n> > configuration files as well and is pure ansi C. However bundling\n> > something has it bad sides too. At least this will solve the dependency\n> > problem. So let the language war begin =).\n> \n> Talk is cheap, show me the code.\n\nSee this thread by Jeff King:\nhttp://thread.gmane.org/gmane.comp.version-control.git/206335/focus=206337\n\nAnd see my humble test of what the speedup would be for git-submodule\neven with a faulty lua integration (still forking... but huge\nperformance boost anyway):\nhttp://thread.gmane.org/gmane.comp.version-control.git/228031/focus=228051\n\nAs you can see a lua integration would increase the git binary with\n300kb.\n\n-- \nMed vänliga hälsningar\nFredrik Gustafsson\n\ntel: 0733-608274\ne-post: iveqy@iveqy.com\n"},{"id":"228030","messageId":"CAMP44s3OYjv2LsU+6FY_qESdCvJcD4zb46aJmKpruof3hYEGzQ@mail.gmail.com","threadId":"34989","inReplyTo":"20130922081250.GD13262@paksenarrion.iveqy.com","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-22T08:29:03Z","receivedAt":"2013-09-22T08:29:03Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Sun, Sep 22, 2013 at 3:12 AM, Fredrik Gustafsson <iveqy@iveqy.com> wrote:\n> On Sun, Sep 22, 2013 at 02:43:39AM -0500, Felipe Contreras wrote:\n>> > It would actually be usefull to know stats on where git is runned. In my\n>> > world of embedded computing, ruby support definitely isn't a standard,\n>> > nor is glibc.\n>>\n>> I come from the embedded world as well, and I've never seen Git used there.\n>>\n>> I'd say Windows support is much more important than embedded, and we\n>> are not supporting that properly.\n>\n> Me neither, it doesn't mean that it isn't used though... I agree with\n> the lack of windows support from git.git.\n\nSure, it *might* be used, but I don't understand this fascination\nabout worrying about hypothetical users, possibly non-existent, when\nwe have real users to worry about, and in big numbers.\n\n> However since Microsoft\n> working with libgit2 on a Visual Studio plugin this it might be that the\n> need for windows support decreases.\n\nI'll believe it when I see it. And then, when the users like it and\ndon't report brokenness.\n\nPersonally, I don't have much faith the in the libgit2 project, and\nit's ability to keep up with git.git.\n\n>> >> > Also, the only Python script that is shipped with Git is git-p4, which\n>> >> > is essentially optional, since most git users probably do not use\n>> >> > Perforce. Otherwise, all the scripts in git are shell or Perl.\n>> >>\n>> >> Neither perl, nor shell, nor python scripts solve the forking problem. My\n>> >> proposal does.\n>> >\n>> > It does,\n>>\n>> No, it does not. All the **current** perl/shell/python scripts use\n>> 'git foo' commands to achieve everything.\n>\n> As I said, \"It does\" meaning \"Your solution solves the forking problem\".\n\nOh.\n\n>> > and so does Lua,\n>>\n>> There is no lua in Git.\n>\n> There's no ruby in git either as far as I know... (and no, I don't think\n> contrib/ counts).\n\nThere is when you apply this patch.\n\n>> > which can be bundled with git and used in the\n>> > configuration files as well and is pure ansi C. However bundling\n>> > something has it bad sides too. At least this will solve the dependency\n>> > problem. So let the language war begin =).\n>>\n>> Talk is cheap, show me the code.\n>\n> See this thread by Jeff King:\n> http://thread.gmane.org/gmane.comp.version-control.git/206335/focus=206337\n\nThat is very very far from what I'm doing.\n\n> And see my humble test of what the speedup would be for git-submodule\n> even with a faulty lua integration (still forking... but huge\n> performance boost anyway):\n> http://thread.gmane.org/gmane.comp.version-control.git/228031/focus=228051\n\nI don't see how that is relevant, but I'm certain the same can be done\nwith Ruby.\n\n> As you can see a lua integration would increase the git binary with\n> 300kb.\n\nAnd my patch would increase it 49Kb.\n\nIMO the problem with lua is that it's too simple, it's syntax doesn't\nresemble c, perl, python, shell, or ruby, it's just weird. Also, it's\nmuch less popular, it's not as powerful, and there isn't a big\ncommunity involved with Git like with Ruby.\n\nSure, for a couple of simple scripts lua bindings would be great, but\nfor the future, better maintainability, and to grab future developers,\nRuby is simply a better option.\n\n-- \nFelipe Contreras\n"},{"id":"228040","messageId":"CAPc5daWa0BPXdrYqek=WzixVVfh0DvHhxjtOh2LW6bgR0MAOPw@mail.gmail.com","threadId":"34989","inReplyTo":"20130921235647.GC235845@vauxhall.crustytoothpaste.net","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-09-23T00:00:44Z","receivedAt":"2013-09-23T00:00:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"[on vacaion, with only gmail webmail UI; please excuse me if this message comes\nout badly formatted or gets dropped by vger.kernel.org]\n\nOn Sat, Sep 21, 2013 at 4:56 PM, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> On Sat, Sep 21, 2013 at 05:52:05PM -0500, Felipe Contreras wrote:\n>> On Sat, Sep 21, 2013 at 4:29 PM, brian m. carlson\n>> <sandals@crustytoothpaste.net> wrote:\n>> > As Junio has also pointed out in the past, there are people who aren't\n>> > able to use Ruby in the same way that they are Perl and Python.  If it's\n>> > announced now, Git 2.0 might be a good time to start accepting Ruby\n>> > scripts, as that will give people time to plan for its inclusion.\n\nIn the very beginning, the codebase and development community of Git was\nvery small. In order to give usability and also easy availability of minimally\nsufficient features, we used shell and Perl for quicker turn-around and\nimplementation and included these Porcelain scripts written in higher level\nlanguages in the same package as the core Git.\n\nWe should look at use of shell and Perl as necessary evil in that context,\nnot as an enabler for people who do not want to write in C. It is no longer\n2005 and the \"enabler\" side has a much more suited project for it these days.\n\nNamely, it is better served by various language-binding efforts around libgit2.\nBinding that takes advantage of each specific language is better done over\nthere, I think. Cf. http://www.youtube.com/watch?v=4ZWqr6iih3s\n\nIf anything, I think the core side should be focused on three things\n(in addition\nto bug-fixes, of course) in the longer term:\n\n - Defining and implementing necessary improvements to the core on-file and\n   on-the-wire data structures and the protocols to serve as the canonical\n   implementation.\n\n - Moving away from higher-level scripting languages such as shell and Perl.\n   Recent \"clean --interactive\" may have added some code that could be\n   reused for a rewrite of \"add -i\" (which I think is in Perl), for example.\n   The minimum \"You need to have these to use Git\" should be made more\n   portable by doing *less* in shell or Perl, not by adding more in the higher-\n   level languages, and certainly not by adding other languages, be it Ruby or\n   Lua.\n\n - Giving solid interface to the outside world, e.g. remote-helpers, credential-\n   helpers API, and let the users and developers that want to use them do their\n   own projects, without adding things to contrib/.\n\nIn other words, now the Git user and developer community are strong\nand thriving,\nwe should strive to make the core smaller, not larger, and encourage people to\nform more third party communities that specialise in the areas the\nparticipant of\nthese communities are stronger than those who are involved in the core\n(e.g. like\nmyself, Peff, Nico, Jonathan, etc.). For programs that talk remote-helper or\ncredential-helper protocols, for example, it is wasteful to have them\nin our contrib/\nand have the changes to them go through my tree, with the same coding style\nstandard applied to the core, which would in the longer term only add\nunnecessary overhead to what they want to do and what their effort supply the\nusers with.\n\nFor that, defining a good inter-system interface boundary is essential\non the core\nside, but we do not need to (and I do not want to see us on the core side doing)\ndesign and implement the other side that talks to us, which people may write in\ntheir favorite higher-level languages.\n\nWe define a reasonably robust object & history transfer mechanism over SSH\nconnection with set of necessary hooks to customize what happens when a push\nand a fetch is requested, and Sitaram built Gitolite totally outside\nthe core. I think\nthat is the kind of thing we want to see *more* in this community. Was it better\nif we defined in the core how \"hosting\" service is to be done and implemented\none ourselves? I do not think so. Similarly for Michael Haggerty's iMerge, which\nwas done outside the core.\n"},{"id":"228041","messageId":"20130923014157.GE235845@vauxhall.crustytoothpaste.net","threadId":"34989","inReplyTo":"CAPc5daWa0BPXdrYqek=WzixVVfh0DvHhxjtOh2LW6bgR0MAOPw@mail.gmail.com","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2013-09-23T01:41:57Z","receivedAt":"2013-09-23T01:41:57Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Sun, Sep 22, 2013 at 05:00:44PM -0700, Junio C Hamano wrote:\n>  - Moving away from higher-level scripting languages such as shell and Perl.\n>    Recent \"clean --interactive\" may have added some code that could be\n>    reused for a rewrite of \"add -i\" (which I think is in Perl), for example.\n>    The minimum \"You need to have these to use Git\" should be made more\n>    portable by doing *less* in shell or Perl, not by adding more in the higher-\n>    level languages, and certainly not by adding other languages, be it Ruby or\n>    Lua.\n\nI can certainly go for that.  C is faster and the codebase can be more\nconsistent (and more portable to non-Unix).  My concern was that if\nwe're going to be adding additional languages, some previous warning\nwould be appropriate.  As I said, I wouldn't be able to deploy a git\nusing Ruby immediately, and I'm sure I'm not the only one.  If we're not\ngoing to be adding another language, then obviously the issue becomes\nmoot.\n\n-- \nbrian m. carlson / brian with sandals: Houston, Texas, US\n+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only\nOpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187\n"},{"id":"228077","messageId":"524085ba39049_3a6f81e84193b3@nysa.mail","threadId":"34989","inReplyTo":"CAPc5daWa0BPXdrYqek=WzixVVfh0DvHhxjtOh2LW6bgR0MAOPw@mail.gmail.com","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-23T18:17:30Z","receivedAt":"2013-09-23T18:17:30Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Junio C Hamano wrote:\n> [on vacaion, with only gmail webmail UI; please excuse me if this message comes\n> out badly formatted or gets dropped by vger.kernel.org]\n> \n> On Sat, Sep 21, 2013 at 4:56 PM, brian m. carlson\n> <sandals@crustytoothpaste.net> wrote:\n> > On Sat, Sep 21, 2013 at 05:52:05PM -0500, Felipe Contreras wrote:\n> >> On Sat, Sep 21, 2013 at 4:29 PM, brian m. carlson\n> >> <sandals@crustytoothpaste.net> wrote:\n> >> > As Junio has also pointed out in the past, there are people who aren't\n> >> > able to use Ruby in the same way that they are Perl and Python.  If it's\n> >> > announced now, Git 2.0 might be a good time to start accepting Ruby\n> >> > scripts, as that will give people time to plan for its inclusion.\n> \n> In the very beginning, the codebase and development community of Git was\n> very small. In order to give usability and also easy availability of minimally\n> sufficient features, we used shell and Perl for quicker turn-around and\n> implementation and included these Porcelain scripts written in higher level\n> languages in the same package as the core Git.\n> \n> We should look at use of shell and Perl as necessary evil in that context,\n> not as an enabler for people who do not want to write in C. It is no longer\n> 2005 and the \"enabler\" side has a much more suited project for it these days.\n> \n> Namely, it is better served by various language-binding efforts around libgit2.\n> Binding that takes advantage of each specific language is better done over\n> there, I think. Cf. http://www.youtube.com/watch?v=4ZWqr6iih3s\n\nIf libgit2 is so good as a library to interact with Git repositories, why isn't\nGit using it?\n\nBecause it's not. It is a necessary evil due to the fact that Git developers\nneglected to write code in a reusable manner so other people could utilize\nlibgit. So somebody else had to step up, so now we have two code-bases.\n\n> If anything, I think the core side should be focused on three things\n> (in addition\n> to bug-fixes, of course) in the longer term:\n> \n>  - Defining and implementing necessary improvements to the core on-file and\n>    on-the-wire data structures and the protocols to serve as the canonical\n>    implementation.\n> \n>  - Moving away from higher-level scripting languages such as shell and Perl.\n>    Recent \"clean --interactive\" may have added some code that could be\n>    reused for a rewrite of \"add -i\" (which I think is in Perl), for example.\n>    The minimum \"You need to have these to use Git\" should be made more\n>    portable by doing *less* in shell or Perl, not by adding more in the higher-\n>    level languages, and certainly not by adding other languages, be it Ruby or\n>    Lua.\n> \n>  - Giving solid interface to the outside world, e.g. remote-helpers, credential-\n>    helpers API, and let the users and developers that want to use them do their\n>    own projects, without adding things to contrib/.\n\nIt's interesting how none of these goals reflect what the users want:\n\nhttps://www.survs.com/results/QPESOB10/ME8UTHXM4M\n\n1. Better user-interface\n2. Better documentation\n3. GUI tools\n\nDo you deny this is what users want? Or you just don't care?\n\nI'm not trying to antagonize you, I just truly don't understand how something\nso obvious for so many users just doesn't even factor into your decision making\nas what needs to be done.\n\n> In other words, now the Git user and developer community are strong\n> and thriving,\n> we should strive to make the core smaller, not larger, and encourage people to\n> form more third party communities that specialise in the areas the\n> participant of\n> these communities are stronger than those who are involved in the core\n> (e.g. like\n> myself, Peff, Nico, Jonathan, etc.). For programs that talk remote-helper or\n> credential-helper protocols, for example, it is wasteful to have them\n> in our contrib/\n> and have the changes to them go through my tree, with the same coding style\n> standard applied to the core, which would in the longer term only add\n> unnecessary overhead to what they want to do and what their effort supply the\n> users with.\n\nOf course, we can make the core smaller, by replacing all the perl/shell\nscripts with ruby ones.\n\nSure, it would be better if all the scripts were rewritten in C, but that has\nbeen going on for years, and there's no end in sight, and not that much\nprogress at all.\n\nSo, it's fair to say that the rewrite to C is just not going to happen any time\nsoon, and if we accept that, we should accept that an interim solution is\nneeded, because Windows users are important and they are hurting right now, and\nthat solution could definitely be Ruby.\n\nRewriting scripts to C is hard, rewriting them to Ruby is easy, and one of the\nadvantages of rewriting to Ruby, is that having the C->Ruby bindings available\nwould make it easy to replace part of the scripts chunk by chunk, so we could\nhave a half Ruby, half C script, and eventually 100% C.\n\nThis is a practical solution, it's a realistic path to move forward, not one\nbased on wishful thinking and intentions that never get realized.\n\nOnce again, the perfect being the enemy of the good in the Git project, even\nwhen the good leads to perfect.\n\n-- \nFelipe Contreras\n"},{"id":"228075","messageId":"CACh33FpP_Afb-9eke8m282saUZEDA_ZVbUQvKc6R3EF3P1ZvTA@mail.gmail.com","threadId":"34989","inReplyTo":"CAMP44s3OYjv2LsU+6FY_qESdCvJcD4zb46aJmKpruof3hYEGzQ@mail.gmail.com","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Patrick Donnelly","fromEmail":"batrick@batbytes.com","sentAt":"2013-09-23T18:20:44Z","receivedAt":"2013-09-23T18:20:44Z","isPatch":true,"sender":{"key":"batrick@batbytes.com","avatar":null},"body":"Hello Felipe,\n\nOn Sun, Sep 22, 2013 at 4:29 AM, Felipe Contreras\n<felipe.contreras@gmail.com> wrote:\n> On Sun, Sep 22, 2013 at 3:12 AM, Fredrik Gustafsson <iveqy@iveqy.com> wrote:\n>> And see my humble test of what the speedup would be for git-submodule\n>> even with a faulty lua integration (still forking... but huge\n>> performance boost anyway):\n>> http://thread.gmane.org/gmane.comp.version-control.git/228031/focus=228051\n>\n> I don't see how that is relevant, but I'm certain the same can be done\n> with Ruby.\n>\n>> As you can see a lua integration would increase the git binary with\n>> 300kb.\n>\n> And my patch would increase it 49Kb.\n\nUnless you statically compile in Ruby (which is what the above quoted\n300kb implied for Lua, in actually it is less than 200kb). [Also good\nluck statically compiling Python/Ruby into an executable.]\n\n> IMO the problem with lua is that it's too simple, it's syntax doesn't\n> resemble c, perl, python, shell, or ruby, it's just weird. Also, it's\n> much less popular, it's not as powerful, and there isn't a big\n> community involved with Git like with Ruby.\n\n*sigh*. At this point you've really cemented your purpose here as a\nlanguage evangelist. It's unfortunate I have to reply to dismiss this\nFUD (which you complained about earlier, ironically) otherwise\ncommunity accepts it as fact (\"oh, I remember some guys saying Lua was\na language for idiots...\").\n\nLua is by no means *simple*. Try \"small\" or \"lightweight\". Its syntax\nis engineered to be readable and amateur friendly. You've placed Ruby\non a pedestal alongside those other major languages but its syntax\ndoesn't resemble any of those.\n\n>Also, it's much less popular\n\nhttps://sites.google.com/site/marbux/home/where-lua-is-used\n\nThe hallmark of a good embedded language is your users don't even know\nit is there.\n\n>  it's not as powerful,\n\nThis is really funny to me. Despite Lua's small size, it has lead the\nway for modern dynamic language features, such as coroutines, block\nlevel scoping and real closure, incremental GC, a simple and usable C\nAPI (*yes* this is a feature), and a register based VM [1]. It is\nconsistently placed as the *fastest* dynamic language in existence\n[e.g. 2]? The LuaJIT compiler often achieves competitive or better\nperformance than C [3]. What about this isn't powerful?\n\n[1] Ierusalimschy, Roberto, Luiz Henrique De Figueiredo, and Waldemar\nCeles Filho. \"The Implementation of Lua 5.0.\" J. UCS 11.7 (2005):\n1159-1176.\n[2] http://benchmarksgame.alioth.debian.org/u32/benchmark.php?test=all&lang=lua&lang2=yarv&data=u32\n[3] http://luajit.org/performance_x86.html\n\n-- \nPatrick Donnelly\n"},{"id":"228095","messageId":"CAMP44s2DfdqCLnp=CGf2O4tWi8LkoV=J2GTJiRORUGQjyrBnhg@mail.gmail.com","threadId":"34989","inReplyTo":"CACh33FpP_Afb-9eke8m282saUZEDA_ZVbUQvKc6R3EF3P1ZvTA@mail.gmail.com","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-23T18:53:49Z","receivedAt":"2013-09-23T18:53:49Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Mon, Sep 23, 2013 at 1:20 PM, Patrick Donnelly <batrick@batbytes.com> wrote:\n> Hello Felipe,\n>\n> On Sun, Sep 22, 2013 at 4:29 AM, Felipe Contreras\n> <felipe.contreras@gmail.com> wrote:\n>> On Sun, Sep 22, 2013 at 3:12 AM, Fredrik Gustafsson <iveqy@iveqy.com> wrote:\n>>> And see my humble test of what the speedup would be for git-submodule\n>>> even with a faulty lua integration (still forking... but huge\n>>> performance boost anyway):\n>>> http://thread.gmane.org/gmane.comp.version-control.git/228031/focus=228051\n>>\n>> I don't see how that is relevant, but I'm certain the same can be done\n>> with Ruby.\n>>\n>>> As you can see a lua integration would increase the git binary with\n>>> 300kb.\n>>\n>> And my patch would increase it 49Kb.\n>\n> Unless you statically compile in Ruby (which is what the above quoted\n> 300kb implied for Lua, in actually it is less than 200kb). [Also good\n> luck statically compiling Python/Ruby into an executable.]\n\nYes, but that's not what the words said, the words said 'lua\nintegration' and 'ruby integration' would take that much. Either way\nit doesn't matter, shared libraries exist for a reason. We don't need\nto statically compile openssl do we? No? Good.\n\n>> IMO the problem with lua is that it's too simple, it's syntax doesn't\n>> resemble c, perl, python, shell, or ruby, it's just weird. Also, it's\n>> much less popular, it's not as powerful, and there isn't a big\n>> community involved with Git like with Ruby.\n>\n> *sigh*. At this point you've really cemented your purpose here as a\n> language evangelist. It's unfortunate I have to reply to dismiss this\n> FUD (which you complained about earlier, ironically) otherwise\n> community accepts it as fact (\"oh, I remember some guys saying Lua was\n> a language for idiots...\").\n\nI dismissed the claim as FUD, when the conclusion was exaggerated, and\nthere was no evidence in sight.\n\nWhen I say Ruby is a superior alternative, I provide evidence.\n\n> Lua is by no means *simple*. Try \"small\" or \"lightweight\". Its syntax\n> is engineered to be readable and amateur friendly. You've placed Ruby\n> on a pedestal alongside those other major languages but its syntax\n> doesn't resemble any of those.\n>\n>>Also, it's much less popular\n>\n> https://sites.google.com/site/marbux/home/where-lua-is-used\n>\n> The hallmark of a good embedded language is your users don't even know\n> it is there.\n\nUsers don't even know in what language those projects are programmed,\nthat's irrelevant. If MediaWiki does indeed use Lua, it must be a tiny\nfraction of it.\n\nLua is #25 in the tiobe index with 0.518%, Ruby is #13 with 1.382%,\nright next to Perl. Ruby is 54 times used more in GitHub than Lua.\nThese are the numbers I have, if you have other numbers, please, share\nthem.\n\n>>  it's not as powerful,\n>\n> This is really funny to me. Despite Lua's small size, it has lead the\n> way for modern dynamic language features, such as coroutines, block\n> level scoping and real closure, incremental GC, a simple and usable C\n> API (*yes* this is a feature), and a register based VM [1]. It is\n> consistently placed as the *fastest* dynamic language in existence\n> [e.g. 2]? The LuaJIT compiler often achieves competitive or better\n> performance than C [3]. What about this isn't powerful?\n\nTalk is cheap, show me the code.\n\nDo what I did. Add lua bindings for several C functions, replace a\nscript with a Lua script (like git request-pull), replace a major\nbuiltin (like git reset), and show how this succinct example I\nprovided in Ruby would look like:\n\ncb_data = 'foo'\nfor_each_ref() do |name, sha1, flags|\n  puts '%s: %s: %s' % [cb_data, name, sha1_to_hex(sha1)]\nend\n\nLet's see how it looks.\n\nUntil you do that, I'd say you are the one that is language\nevangelizing, I'm providing an actual real solution to a very\nimportant problem.\n\n-- \nFelipe Contreras\n"},{"id":"228098","messageId":"CACh33Fqm4C9BJhzatm9j1JBY8iY+gEafpnnhgnL2JJ2ff_xzKQ@mail.gmail.com","threadId":"34989","inReplyTo":"CAMP44s2DfdqCLnp=CGf2O4tWi8LkoV=J2GTJiRORUGQjyrBnhg@mail.gmail.com","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Patrick Donnelly","fromEmail":"batrick@batbytes.com","sentAt":"2013-09-23T19:20:31Z","receivedAt":"2013-09-23T19:20:31Z","isPatch":true,"sender":{"key":"batrick@batbytes.com","avatar":null},"body":"On Mon, Sep 23, 2013 at 2:53 PM, Felipe Contreras\n<felipe.contreras@gmail.com> wrote:\n> Yes, but that's not what the words said, the words said 'lua\n> integration' and 'ruby integration' would take that much. Either way\n> it doesn't matter, shared libraries exist for a reason. We don't need\n> to statically compile openssl do we? No? Good.\n\nUh, you're willfully ignoring the conversation about avoiding\ndependencies. One way to do that is to include and statically link Lua\nalong with Git. The cost of doing that is 200kb. I know this because I\nactually do it for Nmap.\n\n>>> IMO the problem with lua is that it's too simple, it's syntax doesn't\n>>> resemble c, perl, python, shell, or ruby, it's just weird. Also, it's\n>>> much less popular, it's not as powerful, and there isn't a big\n>>> community involved with Git like with Ruby.\n>>\n>> *sigh*. At this point you've really cemented your purpose here as a\n>> language evangelist. It's unfortunate I have to reply to dismiss this\n>> FUD (which you complained about earlier, ironically) otherwise\n>> community accepts it as fact (\"oh, I remember some guys saying Lua was\n>> a language for idiots...\").\n>\n> I dismissed the claim as FUD, when the conclusion was exaggerated, and\n> there was no evidence in sight.\n>\n> When I say Ruby is a superior alternative, I provide evidence.\n\nYou have provided *no* evidence.\n\n>> Lua is by no means *simple*. Try \"small\" or \"lightweight\". Its syntax\n>> is engineered to be readable and amateur friendly. You've placed Ruby\n>> on a pedestal alongside those other major languages but its syntax\n>> doesn't resemble any of those.\n>>\n>>>Also, it's much less popular\n>>\n>> https://sites.google.com/site/marbux/home/where-lua-is-used\n>>\n>> The hallmark of a good embedded language is your users don't even know\n>> it is there.\n>\n> Users don't even know in what language those projects are programmed,\n> that's irrelevant.\n\n*Absolutely relevant*: as normal git user *never* wants to know, care,\nor be exposed to the details of how `git` operates.\n\n> If MediaWiki does indeed use Lua, it must be a tiny\n> fraction of it.\n\nThey just started using it. Well done cherry-picking 1 example from a\nhost for your dismissal.\n\n>>>  it's not as powerful,\n>>\n>> This is really funny to me. Despite Lua's small size, it has lead the\n>> way for modern dynamic language features, such as coroutines, block\n>> level scoping and real closure, incremental GC, a simple and usable C\n>> API (*yes* this is a feature), and a register based VM [1]. It is\n>> consistently placed as the *fastest* dynamic language in existence\n>> [e.g. 2]? The LuaJIT compiler often achieves competitive or better\n>> performance than C [3]. What about this isn't powerful?\n>\n> Talk is cheap, show me the code.\n>\n> Do what I did. Add lua bindings for several C functions, replace a\n> script with a Lua script (like git request-pull), replace a major\n> builtin (like git reset), and show how this succinct example I\n> provided in Ruby would look like:\n>\n> cb_data = 'foo'\n> for_each_ref() do |name, sha1, flags|\n>   puts '%s: %s: %s' % [cb_data, name, sha1_to_hex(sha1)]\n> end\n>\n> Let's see how it looks.\n\nI address your performance claims, you dismiss them and then ask for\ncode to compare? Code which is primarily bindings to C which does all\nthe work? No thanks, that circle jerk doesn't interest me.\n\n> Until you do that, I'd say you are the one that is language\n> evangelizing, I'm providing an actual real solution to a very\n> important problem.\n\nAs mentioned elsewhere, the solution Git is using is to move porcelain\ncommands to C. You're manufacturing problems and spreading FUD.\n\nI'm letting this thread die as I only wanted to confront your baseless\ndismissal of Lua. If you want to continue this, I'll do it offlist.\n\n-- \nPatrick Donnelly\n"},{"id":"228099","messageId":"CAMP44s2YeeE8zHha2sOEtKfOJJcDPBuX2c2ceDnnhK_g=DmjRA@mail.gmail.com","threadId":"34989","inReplyTo":"CACh33Fqm4C9BJhzatm9j1JBY8iY+gEafpnnhgnL2JJ2ff_xzKQ@mail.gmail.com","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-23T19:47:13Z","receivedAt":"2013-09-23T19:47:13Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Mon, Sep 23, 2013 at 2:20 PM, Patrick Donnelly <batrick@batbytes.com> wrote:\n> On Mon, Sep 23, 2013 at 2:53 PM, Felipe Contreras\n> <felipe.contreras@gmail.com> wrote:\n>> Yes, but that's not what the words said, the words said 'lua\n>> integration' and 'ruby integration' would take that much. Either way\n>> it doesn't matter, shared libraries exist for a reason. We don't need\n>> to statically compile openssl do we? No? Good.\n>\n> Uh, you're willfully ignoring the conversation about avoiding\n> dependencies. One way to do that is to include and statically link Lua\n> along with Git. The cost of doing that is 200kb. I know this because I\n> actually do it for Nmap.\n\nDependencies are avoided when it's possible and sensible to do so.\nYet, we still depend on a bunch of things.\n\nMy proposal to replace perl/shell with ruby would actually remove two\ndependencies and add one, so in effect would remove one dependency. Of\ncourse, people could still build with NO_RUBY=y, just like they can\nbuild with NO_PERL=y, and deal with the consequences.\n\n>>>> IMO the problem with lua is that it's too simple, it's syntax doesn't\n>>>> resemble c, perl, python, shell, or ruby, it's just weird. Also, it's\n>>>> much less popular, it's not as powerful, and there isn't a big\n>>>> community involved with Git like with Ruby.\n>>>\n>>> *sigh*. At this point you've really cemented your purpose here as a\n>>> language evangelist. It's unfortunate I have to reply to dismiss this\n>>> FUD (which you complained about earlier, ironically) otherwise\n>>> community accepts it as fact (\"oh, I remember some guys saying Lua was\n>>> a language for idiots...\").\n>>\n>> I dismissed the claim as FUD, when the conclusion was exaggerated, and\n>> there was no evidence in sight.\n>>\n>> When I say Ruby is a superior alternative, I provide evidence.\n>\n> You have provided *no* evidence.\n\nI have, you just chose to ignore it.\n\n>>> Lua is by no means *simple*. Try \"small\" or \"lightweight\". Its syntax\n>>> is engineered to be readable and amateur friendly. You've placed Ruby\n>>> on a pedestal alongside those other major languages but its syntax\n>>> doesn't resemble any of those.\n>>>\n>>>>Also, it's much less popular\n>>>\n>>> https://sites.google.com/site/marbux/home/where-lua-is-used\n>>>\n>>> The hallmark of a good embedded language is your users don't even know\n>>> it is there.\n>>\n>> Users don't even know in what language those projects are programmed,\n>> that's irrelevant.\n>\n> *Absolutely relevant*: as normal git user *never* wants to know, care,\n> or be exposed to the details of how `git` operates.\n\nSo? Before and after this patch they still wouldn't be exposed.\n\nThis is a total red herring.\n\n>> If MediaWiki does indeed use Lua, it must be a tiny\n>> fraction of it.\n>\n> They just started using it. Well done cherry-picking 1 example from a\n> host for your dismissal.\n\nI didn't cherry pick anything, I used the project I'm more familiar\nwith, replace MediaWiki with any other of your examples, and the claim\nstill stands.\n\n>>>>  it's not as powerful,\n>>>\n>>> This is really funny to me. Despite Lua's small size, it has lead the\n>>> way for modern dynamic language features, such as coroutines, block\n>>> level scoping and real closure, incremental GC, a simple and usable C\n>>> API (*yes* this is a feature), and a register based VM [1]. It is\n>>> consistently placed as the *fastest* dynamic language in existence\n>>> [e.g. 2]? The LuaJIT compiler often achieves competitive or better\n>>> performance than C [3]. What about this isn't powerful?\n>>\n>> Talk is cheap, show me the code.\n>>\n>> Do what I did. Add lua bindings for several C functions, replace a\n>> script with a Lua script (like git request-pull), replace a major\n>> builtin (like git reset), and show how this succinct example I\n>> provided in Ruby would look like:\n>>\n>> cb_data = 'foo'\n>> for_each_ref() do |name, sha1, flags|\n>>   puts '%s: %s: %s' % [cb_data, name, sha1_to_hex(sha1)]\n>> end\n>>\n>> Let's see how it looks.\n>\n> I address your performance claims, you dismiss them and then ask for\n> code to compare? Code which is primarily bindings to C which does all\n> the work? No thanks, that circle jerk doesn't interest me.\n\nI didn't make any performance claims, you made claims about being a\npowerful language, well, let's see how powerful it is.\n\nRuby is so powerful I was able to write these patches with moderate\neffort, surely if Lua is so powerful you can do the same.\n\n>> Until you do that, I'd say you are the one that is language\n>> evangelizing, I'm providing an actual real solution to a very\n>> important problem.\n>\n> As mentioned elsewhere, the solution Git is using is to move porcelain\n> commands to C. You're manufacturing problems and spreading FUD.\n\nThis effort has no end in sight, and as I've explained, using Ruby as\nan interim solution would actually speed up the move to pure C.\n\nIn fact, I would know much more about the impediments since I sent\ntwenty eight patches to start replacing 'git rebase' with C code:\n\nhttp://thread.gmane.org/gmane.comp.version-control.git/233396\n\nThey got rejected without so much as a reply. Why if it's so important\nto move the scripts to C did these patches get ignored? Because it's\nnot. None of the core developers are interested in this, because they\ndon't use Windows, so it's not a priority for them.\n\n> I'm letting this thread die as I only wanted to confront your baseless\n> dismissal of Lua. If you want to continue this, I'll do it offlist.\n\nUntil you, or anyone, shows me the code, I'll continue to dismiss Lua,\nor any other proposed solution.\n\nI know doing what I did in Ruby would be very difficult in Lua, or any\nother language for that matter, which is why I ask you to actually do\nit, because I know you won't do it, because it's hard, which proves my\npoint.\n\nI've proved other people wrong on this list by writing the code, if\nyou are not willing to walk the talk, then there's no point in\ndiscussing. Even if I were to agree that Lua is a better option (which\nI'm not), what have we achieved? Nothing. Who is going to implement\nthat? Not you, not me... So?\n\n-- \nFelipe Contreras\n"},{"id":"228423","messageId":"CAMP44s3xqcxanLaNkowXyXEFejdr4QFkkks4FkA_TxwjE0mjAA@mail.gmail.com","threadId":"34989","inReplyTo":"524085ba39049_3a6f81e84193b3@nysa.mail","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-28T22:56:26Z","receivedAt":"2013-09-28T22:56:26Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Mon, Sep 23, 2013 at 1:17 PM, Felipe Contreras\n<felipe.contreras@gmail.com> wrote:\n> Junio C Hamano wrote:\n\n>> In other words, now the Git user and developer community are strong\n>> and thriving,\n>> we should strive to make the core smaller, not larger, and encourage people to\n>> form more third party communities that specialise in the areas the\n>> participant of\n>> these communities are stronger than those who are involved in the core\n>> (e.g. like\n>> myself, Peff, Nico, Jonathan, etc.). For programs that talk remote-helper or\n>> credential-helper protocols, for example, it is wasteful to have them\n>> in our contrib/\n>> and have the changes to them go through my tree, with the same coding style\n>> standard applied to the core, which would in the longer term only add\n>> unnecessary overhead to what they want to do and what their effort supply the\n>> users with.\n>\n> Of course, we can make the core smaller, by replacing all the perl/shell\n> scripts with ruby ones.\n>\n> Sure, it would be better if all the scripts were rewritten in C, but that has\n> been going on for years, and there's no end in sight, and not that much\n> progress at all.\n>\n> So, it's fair to say that the rewrite to C is just not going to happen any time\n> soon, and if we accept that, we should accept that an interim solution is\n> needed, because Windows users are important and they are hurting right now, and\n> that solution could definitely be Ruby.\n>\n> Rewriting scripts to C is hard, rewriting them to Ruby is easy, and one of the\n> advantages of rewriting to Ruby, is that having the C->Ruby bindings available\n> would make it easy to replace part of the scripts chunk by chunk, so we could\n> have a half Ruby, half C script, and eventually 100% C.\n>\n> This is a practical solution, it's a realistic path to move forward, not one\n> based on wishful thinking and intentions that never get realized.\n>\n> Once again, the perfect being the enemy of the good in the Git project, even\n> when the good leads to perfect.\n\nI think I've pretty much demonstrated that Ruby would be an excellent\ntool to make the code smaller with my 44 patch series.\n\n-- \nFelipe Contreras\n"},{"id":"228424","messageId":"CAMP44s2Fg2NwinKTDrHjKhKQkniwAZD041n8QYrN5oOjOJ8osQ@mail.gmail.com","threadId":"34989","inReplyTo":"20130923014157.GE235845@vauxhall.crustytoothpaste.net","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-28T22:57:45Z","receivedAt":"2013-09-28T22:57:45Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Sun, Sep 22, 2013 at 8:41 PM, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> On Sun, Sep 22, 2013 at 05:00:44PM -0700, Junio C Hamano wrote:\n>>  - Moving away from higher-level scripting languages such as shell and Perl.\n>>    Recent \"clean --interactive\" may have added some code that could be\n>>    reused for a rewrite of \"add -i\" (which I think is in Perl), for example.\n>>    The minimum \"You need to have these to use Git\" should be made more\n>>    portable by doing *less* in shell or Perl, not by adding more in the higher-\n>>    level languages, and certainly not by adding other languages, be it Ruby or\n>>    Lua.\n>\n> I can certainly go for that.  C is faster and the codebase can be more\n> consistent (and more portable to non-Unix).  My concern was that if\n> we're going to be adding additional languages, some previous warning\n> would be appropriate.  As I said, I wouldn't be able to deploy a git\n> using Ruby immediately, and I'm sure I'm not the only one.  If we're not\n> going to be adding another language, then obviously the issue becomes\n> moot.\n\nYou could just build with NO_RUBY=y. Problem solved.\n\n-- \nFelipe Contreras\n"},{"id":"228425","messageId":"CAMP44s0JnG8wQ6DhHxbrdoxhdt3UTC8WG6R2yVmctGntEx0yzQ@mail.gmail.com","threadId":"34989","inReplyTo":"20130921235647.GC235845@vauxhall.crustytoothpaste.net","subject":"Re: [PATCH/RFC 0/7] Support for Ruby","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-28T23:06:22Z","receivedAt":"2013-09-28T23:06:22Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Sat, Sep 21, 2013 at 6:56 PM, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> On Sat, Sep 21, 2013 at 05:52:05PM -0500, Felipe Contreras wrote:\n>> On Sat, Sep 21, 2013 at 4:29 PM, brian m. carlson\n>> <sandals@crustytoothpaste.net> wrote:\n\n>> Now, if anybody has ideas into how the bindings could be more object\n>> oriented, I'm all ears, but unfortunately what I foresee is that\n>> nobody will consider this proposal seriously.\n>\n> My concern is that the Ruby code will end up not being idiomatic, and\n> people will view it as bizarre and unmaintainable.\n>\n> for_each_ref could end up being something like REPOSITORY.refs.each,\n> which would be more idiomatic.  repository.refs would probably be an\n> Enumerator in that case.  If the decision is made to incorporate Ruby\n> code, I'm happy to submit some patches to help provide a sane interface,\n> even though I'm not that familiar with Ruby.\n\nI think my proposed bindings are quite idiomatic.\n\ngit ruby - master origin/master <<EOF\ncommits = ARGV.map { |id| Git::Commit.get(get_sha1(id)) }\nputs get_merge_bases(commits, 0).map { |commit| sha1_to_hex(commit.sha1) }\nEOF\n\n-- \nFelipe Contreras\n"}]}