1# 2# Copyright (c) 2008 James M. Lawrence 3# 4# Permission is hereby granted, free of charge, to any person 5# obtaining a copy of this software and associated documentation files 6# (the "Software"), to deal in the Software without restriction, 7# including without limitation the rights to use, copy, modify, merge, 8# publish, distribute, sublicense, and/or sell copies of the Software, 9# and to permit persons to whom the Software is furnished to do so, 10# subject to the following conditions: 11# 12# The above copyright notice and this permission notice shall be 13# included in all copies or substantial portions of the Software. 14# 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22# SOFTWARE. 23# 24 25require 'rbconfig' 26 27# 28# Alternate implementations of system() and backticks `` on Windows 29# for ruby-1.8 and earlier. 30# 31module Rake::AltSystem 32 WINDOWS = RbConfig::CONFIG["host_os"] =~ 33 %r!(msdos|mswin|djgpp|mingw|[Ww]indows)! 34 35 class << self 36 def define_module_function(name, &block) 37 define_method(name, &block) 38 module_function(name) 39 end 40 end 41 42 if WINDOWS and RUBY_VERSION < "1.9.0" 43 RUNNABLE_EXTS = %w[com exe bat cmd] 44 RUNNABLE_PATTERN = %r!\.(#{RUNNABLE_EXTS.join('|')})\Z!i 45 46 define_module_function :kernel_system, &Kernel.method(:system) 47 define_module_function :kernel_backticks, &Kernel.method(:'`') 48 49 module_function 50 51 def repair_command(cmd) 52 "call " + ( 53 if cmd =~ %r!\A\s*\".*?\"! 54 # already quoted 55 cmd 56 elsif match = cmd.match(%r!\A\s*(\S+)!) 57 if match[1] =~ %r!/! 58 # avoid x/y.bat interpretation as x with option /y 59 %Q!"#{match[1]}"! + match.post_match 60 else 61 # a shell command will fail if quoted 62 cmd 63 end 64 else 65 # empty or whitespace 66 cmd 67 end 68 ) 69 end 70 71 def find_runnable(file) 72 if file =~ RUNNABLE_PATTERN 73 file 74 else 75 RUNNABLE_EXTS.each { |ext| 76 if File.exist?(test = "#{file}.#{ext}") 77 return test 78 end 79 } 80 nil 81 end 82 end 83 84 def system(cmd, *args) 85 repaired = ( 86 if args.empty? 87 [repair_command(cmd)] 88 elsif runnable = find_runnable(cmd) 89 [File.expand_path(runnable), *args] 90 else 91 # non-existent file 92 [cmd, *args] 93 end 94 ) 95 kernel_system(*repaired) 96 end 97 98 def backticks(cmd) 99 kernel_backticks(repair_command(cmd)) 100 end 101 102 define_module_function :'`', &method(:backticks) 103 else 104 # Non-Windows or ruby-1.9+: same as Kernel versions 105 define_module_function :system, &Kernel.method(:system) 106 define_module_function :backticks, &Kernel.method(:'`') 107 define_module_function :'`', &Kernel.method(:'`') 108 end 109end 110