diff options
author | Ho-Sheng Hsiao <hosheng.hsiao@gmail.com> | 2012-04-02 18:45:02 -0400 |
---|---|---|
committer | Ho-Sheng Hsiao <hosh@opscode.com> | 2012-05-10 14:51:43 -0400 |
commit | ec7dfe16926ebb7ecfefda365e5706954b761c3a (patch) | |
tree | cf062be53e0a451870a8c27accbb175a95c8afc7 | |
parent | 146de90bee9a19f97a2b13595d39cbd99cb7eb77 (diff) | |
download | mixlib-shellout-ec7dfe16926ebb7ecfefda365e5706954b761c3a.tar.gz |
[CHEF-2994][WINDOWS] Expanded Utils.should_run_under_cmd?() to work like Ruby system()
-rw-r--r-- | lib/mixlib/shellout/windows.rb | 35 | ||||
-rw-r--r-- | spec/mixlib/shellout/windows_spec.rb | 60 |
2 files changed, 78 insertions, 17 deletions
diff --git a/lib/mixlib/shellout/windows.rb b/lib/mixlib/shellout/windows.rb index 1703236..7bebb3b 100644 --- a/lib/mixlib/shellout/windows.rb +++ b/lib/mixlib/shellout/windows.rb @@ -231,8 +231,41 @@ module Mixlib # api: semi-private # If there are special characters parsable by cmd.exe (such as file redirection), then # this method should return true. + # + # This parser is based on + # https://github.com/ruby/ruby/blob/9073db5cb1d3173aff62be5b48d00f0fb2890991/win32/win32.c#L1437 def self.should_run_under_cmd?(command) - !!(command =~ /[%&|<>{}@^]/) + return true if command =~ /^@/ + + quote = nil + env = false + env_first_char = false + + command.dup.each_char do |c| + case c + when "'", '"' + if (!quote) + quote = c + elsif quote == c + quote = nil + end + next + when '>', '<', '|', '&', "\n" + return true unless quote + when '%' + return true if env + env = env_first_char = true + next + else + next unless env + if env_first_char + env_first_char = false + env = false and next if c !~ /[A-Za-z_]/ + end + env = false if c !~ /[A-Za-z1-9_]/ + end + end + return false end def self.pathext diff --git a/spec/mixlib/shellout/windows_spec.rb b/spec/mixlib/shellout/windows_spec.rb index 4e6b83f..f35c398 100644 --- a/spec/mixlib/shellout/windows_spec.rb +++ b/spec/mixlib/shellout/windows_spec.rb @@ -13,22 +13,50 @@ describe 'Mixlib::ShellOut::Windows', :windows_only => true do end end - with_command(%q{ruby -e 'prints "foobar"'}) { should_not be_true } - - # https://github.com/opscode/mixlib-shellout/pull/2#issuecomment-4825574 - with_command(%q{"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\gacutil.exe" /i "C:\Program Files (x86)\NUnit 2.6\bin\framework\nunit.framework.dll"}) { should_not be_true } - - with_command(%q{ruby -e 'exit 1' | ruby -e 'exit 0'}) { should be_true } - with_command(%q{ruby -e 'exit 1' > out.txt}) { should be_true } - with_command(%q{ruby -e 'exit 1' > out.txt 2>&1}) { should be_true } - with_command(%q{ruby -e 'exit 1' < in.txt}) { should be_true } - with_command(%q{ruby -e 'exit 1' || ruby -e 'exit 0'}) { should be_true } - with_command(%q{ruby -e 'exit 1' && ruby -e 'exit 0'}) { should be_true } - with_command(%q{@echo TRUE}) { should be_true } - with_command(%q{echo %PATH%}) { should be_true } - - # TODO: It would be awesome if it can detect quoted special characters - with_command(%q{echo "ruby -e 'exit 1' || ruby -e 'exit 0'"}) { should be_true } + context 'when unquoted' do + with_command(%q{ruby -e 'prints "foobar"'}) { should_not be_true } + + # https://github.com/opscode/mixlib-shellout/pull/2#issuecomment-4825574 + with_command(%q{"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\gacutil.exe" /i "C:\Program Files (x86)\NUnit 2.6\bin\framework\nunit.framework.dll"}) { should_not be_true } + + with_command(%q{ruby -e 'exit 1' | ruby -e 'exit 0'}) { should be_true } + with_command(%q{ruby -e 'exit 1' > out.txt}) { should be_true } + with_command(%q{ruby -e 'exit 1' > out.txt 2>&1}) { should be_true } + with_command(%q{ruby -e 'exit 1' < in.txt}) { should be_true } + with_command(%q{ruby -e 'exit 1' || ruby -e 'exit 0'}) { should be_true } + with_command(%q{ruby -e 'exit 1' && ruby -e 'exit 0'}) { should be_true } + with_command(%q{@echo TRUE}) { should be_true } + + with_command(%q{echo %PATH%}) { should be_true } + with_command(%q{run.exe %A}) { should be_false } + with_command(%q{run.exe B%}) { should be_false } + with_command(%q{run.exe %A B%}) { should be_false } + with_command(%q{run.exe %A B% %PATH%}) { should be_true } + with_command(%q{run.exe %A B% %_PATH%}) { should be_true } + with_command(%q{run.exe %A B% %PATH_EXT%}) { should be_true } + with_command(%q{run.exe %A B% %1%}) { should be_false } + with_command(%q{run.exe %A B% %PATH1%}) { should be_true } + with_command(%q{run.exe %A B% %_PATH1%}) { should be_true } + end + + context 'when quoted' do + with_command(%q{run.exe "ruby -e 'exit 1' || ruby -e 'exit 0'"}) { should be_false } + with_command(%q{run.exe "ruby -e 'exit 1' > out.txt"}) { should be_false } + with_command(%q{run.exe "ruby -e 'exit 1' > out.txt 2>&1"}) { should be_false } + with_command(%q{run.exe "ruby -e 'exit 1' < in.txt"}) { should be_false } + with_command(%q{run.exe "ruby -e 'exit 1' || ruby -e 'exit 0'"}) { should be_false } + with_command(%q{run.exe "ruby -e 'exit 1' && ruby -e 'exit 0'"}) { should be_false } + with_command(%q{run.exe "%PATH%"}) { should be_true } + with_command(%q{run.exe "%A"}) { should be_false } + with_command(%q{run.exe "B%"}) { should be_false } + with_command(%q{run.exe "%A B%"}) { should be_false } + with_command(%q{run.exe "%A B% %PATH%"}) { should be_true } + with_command(%q{run.exe "%A B% %_PATH%"}) { should be_true } + with_command(%q{run.exe "%A B% %PATH_EXT%"}) { should be_true } + with_command(%q{run.exe "%A B% %1%"}) { should be_false } + with_command(%q{run.exe "%A B% %PATH1%"}) { should be_true } + with_command(%q{run.exe "%A B% %_PATH1%"}) { should be_true } + end end end |