forked from jruby/jruby
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpath_helper.rb
More file actions
113 lines (107 loc) · 3.27 KB
/
path_helper.rb
File metadata and controls
113 lines (107 loc) · 3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
require 'rbconfig'
module JRuby
module PathHelper
WINDOWS = RbConfig::CONFIG['host_os'] =~ /mswin/
WINDOWS_EXE_SUFFIXES = [".exe", ".com", ".bat" , ".cmd"]
# This function does a semi-smart split of a space-separated command line.
# It is aware of single- and double-quotes as word delimiters, and use of backslash
# as an escape character.
def self.quote_sensitive_split(cmd)
parts = [""]
in_quote = nil
escape = false
# this needed to handle weird cases of empty quoted strings,
# like jrubyc -p "" blah.rb
were_quotes = false
cmd.each_char do |c|
if escape
# escaped quote -- add as is
if (c == "\"" || c == "'")
parts.last << c
else
# bare slash, not escaping quotes, add it back
parts.last << "\\" << c
end
escape = false
else
case c
when "\\"
escape = true
when "\"", "'"
if in_quote && in_quote == c
in_quote = nil
were_quotes = true
elsif in_quote.nil?
in_quote = c
else
parts.last << c
end
when " " # space
if in_quote
parts.last << c
else
if (!parts.last.empty?)
parts << ""
elsif (were_quotes)
if (parts.last.empty?)
# to workaround issue with launching jrubyc -p "",
# or java launching code would eat "".
parts.last << '""'
end
parts << ""
end
were_quotes = false
end
else
parts.last << c
end
end
end
if (were_quotes && parts.last.empty?)
parts.last << '""'
end
parts
end
def self.find_file(exe)
# puts "FindFile: looking for #{exe}"
if (WINDOWS && exe !~ /\.(exe|com|cmd|bat)$/i)
WINDOWS_EXE_SUFFIXES.each do |sfx|
if find_file(exe + sfx)
return true
end
end
end
# TODO: should we find files like 'foo' on Windows,
# or should we only deal with .EXE/.BAT, etc.?
File.exist?(exe) && !File.directory?(exe)
end
# Split the command string into parts, but also check if the first argument
# looks like an absolute path, and if so, try to reconstruct it even in the
# case where there are spaces in the directory name. It does this by joining
# successive parts of the front of the split array together until the path
# exists.
# NOTE: this is not foolproof, as someone could have a directory and a file:
# c:/Program Files/
# c:/Program.bat
# but hopefully good enough!
def self.smart_split_command(cmd)
orig_parts = quote_sensitive_split(cmd.strip)
parts = orig_parts.dup
exe = parts.shift.dup
if exe =~ %r{^([a-zA-Z]:)?[/\\]} && (!(found = find_file(exe)))
until (found)
break if parts.empty?
exe << " #{parts.shift}"
found = find_file(exe)
end
if found
[exe, *parts]
else
orig_parts
end
else
orig_parts
end
end
end
end