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

Hi,

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

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

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

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

== Syntax ==

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

C:

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

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

  count += 1

Shell:

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

  str = <<EOF
  multi
  line
  string
  EOF

Perl

  var ||= 'default'

The following Perl code:

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

Looks like this in Ruby:

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

== C bindings ==

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

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

  rb_define_global_function("get_git_dir", git_rb_get_git_dir, 0);

Then in Ruby:

  dir = get_git_dir()

== Much more ==

Ruby's power allows for plenty of extensibility.

For example:

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

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

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

Now:

  p `echo yes`
  => "yes"

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

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

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

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

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

Finally, Ruby has the concept of blocks:

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

  branch = 'master'

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

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

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

== Upgrade path ==

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

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

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

== Community ==

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

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

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

== Conclusion ==

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

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

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

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

-- 
1.8.4-fc

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

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

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

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