6

This is how I detect git in ruby:

`which git 2>/dev/null` and $?.success?

However, this is not cross-platform. It fails on non-unix systems or those without the which command (although I'm not sure what those are).

I need a way to detect git that satisfies these conditions:

  1. works reliably cross-platform, even on Windows
  2. doesn't output anything to $stdout or $stderr
  3. small amount of code

Update: the solution is to avoid using which altogether and to redirect output to NUL on Windows.

require 'rbconfig'
void = RbConfig::CONFIG['host_os'] =~ /msdos|mswin|djgpp|mingw/ ? 'NUL' : '/dev/null'
system "git --version >>#{void} 2>&1"

The system command returns true on success and false on failure, saving us the trip to $?.success? which is needed when using backticks.

mislav
  • 13,971
  • 7
  • 44
  • 63
  • Maybe http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby/2108757#2108757 could help? – VonC Jan 04 '11 at 19:32
  • Forgive my potential foolishness, but doesn't `which` write to stdout? – Steven Jan 04 '11 at 19:37
  • @Steven: of course it does, but in its own subshell, and you can see that I used backticks which captures that output in a return value which I then discard. If `which` wrote something to STDERR, ruby would forward that to $stderr of the main program (something I don't wish to happen) so I used `2>/dev/null` to handle that. – mislav Jan 04 '11 at 19:59
  • @mislav: I'm afraid I'm not familiar with the techniques you're using, but if you can intercept both stdout and stderr, you can avoid relying on `which` and just run `git --version` instead. I suspect that I'm miles off... – Steven Jan 04 '11 at 20:02
  • One point about RUBY_PLATFORM is that will not detect Java properly. See this post: http://blog.emptyway.com/2009/11/03/proper-way-to-detect-windows-platform-in-ruby/ – Luis Lavena Jan 05 '11 at 12:08
  • Thanks Luis, didn't know that! Now corrected – mislav Jan 06 '11 at 11:46

4 Answers4

4

There is not such thing as /dev/null on Windows.

One approach we have been taking in different projects is define NULL based on RbConfig::CONFIG['host_os']

NULL = RbConfig::CONFIG['host_os'] =~ /mingw|mswin/ ? 'NUL' : '/dev/null'

Then use that to redirect both STDOUT and STDERR to it.

As for which, I made a trivial reference on my blog

But, if you just want to check git presence and not location, no need to do which, with a simple system call and check of the resulting in $? will be enough.

Hope this helps

Luis Lavena
  • 10,270
  • 1
  • 34
  • 40
  • When I call `git` and then check `$?.success?`, the result is always true, even if git is not installed. (ruby 1.9.2, i686-pc-mingw32 on Win XP) – mislav Jan 04 '11 at 20:06
  • BTW, had used this technique with rake-compiler to detect gmake/make across platforms: https://github.com/luislavena/rake-compiler/blob/master/lib/rake/extensiontask.rb#L352-354 – Luis Lavena Jan 04 '11 at 20:13
  • I can see that it works now. I must have done something wrong the first time around – mislav Jan 04 '11 at 22:51
1

This is a solution which avoids shelling out to detect executables and is also able to reliably detect where the executable is located. It's an alternative to which.

def which cmd
  exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
  ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
    exts.each { |ext|
      exe = "#{path}/#{cmd}#{ext}"
      return exe if File.executable? exe
    }
  end
  return nil
end

Usage:

# Mac OS X
where 'ruby'
#=> /opt/local/Cellar/ruby-enterprise-edition/2010.02/bin/ruby

# Windows
where 'ruby'
#=> C:\Program Files\Ruby192\bin/ruby.exe
mislav
  • 13,971
  • 7
  • 44
  • 63
0

Perhaps running on JRuby and using JGit could be an option to really go platform-independent.

Fabian Steeg
  • 42,835
  • 6
  • 79
  • 111
  • but 'which' won't run on windows. The prob. is not ruby portability. – zengr Jan 04 '11 at 19:42
  • @zengr: The idea would be not to use the native git implementation at all, but JGit, a pure Java implementation of git. – Fabian Steeg Jan 04 '11 at 19:45
  • but what if the end user is using git (and not jgit), it will go undetected and OPs app will install jgit WITH git which was already on the machine. – zengr Jan 04 '11 at 19:48
  • @zengr I don't know about the actual use case here, but if the app needs to make use of git it could bundle JGit, use that, and not install anything. – Fabian Steeg Jan 04 '11 at 19:53
  • limiting myself to just one Ruby implementation isn't something I had in mind when I asked for "platform-independent" :) – mislav Jan 04 '11 at 19:53
0

I think, you will need to do this:

  1. Check if machine is windows and unix based
  2. If Unix, use which
  3. If Windows, Is there an equivalent of 'which' on windows?
Community
  • 1
  • 1
zengr
  • 36,384
  • 37
  • 121
  • 187