git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH/RFC 0/7] Support for Ruby

From
Felipe Contreras <felipe.contreras@gmail.com>
Date
Sep 21, 2013, 18:48 UTC
Message-ID
<1379789295-18519-1-git-send-email-felipe.contreras@gmail.com>
Hi,

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

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

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

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

== Syntax ==
First of all, the syntax of Ruby is very similar to other languages used by Git:
C:
  if (a && b || (c & FLAG) != 0)
    return 0
  else
    break
  end
  printf("format: %s: %i\n", "this string", 0)
  count += 1
Shell:
  out = `git rev-parse #{committish}`
  str = <<EOF
  multi
  line
  string
  EOF
Perl
  var ||= 'default'
The following Perl code:
  sub abbr {
    my $ref = shift;
    if ($ref =~ m{^refs/heads/(.*)$}) {
      return $1;
    }
    return $ref;
  }
Looks like this in Ruby:
  def abbr(ref)
    if (ref =~ %r{^refs/heads/(.*)$}m)
      return $1
    end
    return ref
  end
== C bindings ==
It's extremely easy to write wrappers for Git's C functions:
  static VALUE git_rb_get_git_dir(VALUE self)
  {
    return rb_str_new2(get_git_dir());
  }
  rb_define_global_function("get_git_dir", git_rb_get_git_dir, 0);
Then in Ruby:
  dir = get_git_dir()
== Much more ==
Ruby's power allows for plenty of extensibility.
For example:
  p `echo yes`
  => "yes\n"

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

  def `(cmd)
    IO.popen(cmd) { |pipe| pipe.read.chomp }
  end
Now:
  p `echo yes`
  => "yes"

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

  git command 1 &&
  git command 2 &&
  git command 3 ||
  error
This gets specially troublesome the bigger the sequence. In Ruby:
  def run(*args)
    system(*args)
    raise RuntimeError unless $?.success?
  end
  begin
    run('git command 1')
    run('git command 2')
    run('git command 3')
  rescue RuntimeError
    error
  end
Finally, Ruby has the concept of blocks:
  def run_with_lock()
    puts "lock"
    yield
    puts "unlock"
  end
  branch = 'master'
  run_with_lock() do
    puts "do stuff with #{branch}"
  end

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

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

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

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

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

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

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

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

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

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

Felipe Contreras (7):
  Add support for ruby commands
  ruby: add setup script
  ruby: add simple wrappers
  ruby: rewrite 'request-pull'
  ruby: rewrite perl script
  ruby: remove one fork
  ruby: rewrite 'reset'
 Makefile            |  16 +-
 cache.h             |   2 +
 git-rb-setup.rb     | 125 +++++++++++++
 git-refs.rb         |   7 +
 git-request-pull.rb | 159 ++++++++++++++++
 git-request-pull.sh | 162 -----------------
 git-reset.rb        | 223 +++++++++++++++++++++++
 git.c               |   4 +-
 ruby.c              | 511 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 1044 insertions(+), 165 deletions(-)
 create mode 100644 git-rb-setup.rb
 create mode 100644 git-refs.rb
 create mode 100644 git-request-pull.rb
 delete mode 100755 git-request-pull.sh
 create mode 100644 git-reset.rb
 create mode 100644 ruby.c
-- 
1.8.4-fc
Next: Felipe Contreras
Message 1 of 26 in “Support for Ruby”
  1. 0/7 Support for RubyFelipe Contreras, Sep 21, 2013
  2. 1/7 Add support for ruby commandsFelipe Contreras, Sep 21, 2013
  3. 2/7 ruby: add setup scriptFelipe Contreras, Sep 21, 2013
  4. 3/7 ruby: add simple wrappersFelipe Contreras, Sep 21, 2013
  5. 4/7 ruby: rewrite 'request-pull'Felipe Contreras, Sep 21, 2013
  6. 5/7 ruby: rewrite perl scriptFelipe Contreras, Sep 21, 2013
  7. 6/7 ruby: remove one forkFelipe Contreras, Sep 21, 2013
  8. 7/7 ruby: rewrite 'reset'Felipe Contreras, Sep 21, 2013
  9. brian m. carlsonSep 21, 2013
  10. Felipe ContrerasSep 21, 2013
  11. brian m. carlsonSep 21, 2013
  12. Felipe ContrerasSep 22, 2013
  13. Fredrik GustafssonSep 22, 2013
  14. Felipe ContrerasSep 22, 2013
  15. Fredrik GustafssonSep 22, 2013
  16. Felipe ContrerasSep 22, 2013
  17. Patrick DonnellySep 23, 2013
  18. Felipe ContrerasSep 23, 2013
  19. Patrick DonnellySep 23, 2013
  20. Felipe ContrerasSep 23, 2013
  21. Junio C HamanoSep 23, 2013
  22. brian m. carlsonSep 23, 2013
  23. Felipe ContrerasSep 28, 2013
  24. Felipe ContrerasSep 23, 2013
  25. Felipe ContrerasSep 28, 2013
  26. Felipe ContrerasSep 28, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.