foreman 0.36.1 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Foreman
2
+
3
+ Manage Procfile-based applications
4
+
5
+ <table>
6
+ <tr>
7
+ <th>If you have...</th>
8
+ <th>Install with...</th>
9
+ </tr>
10
+ <tr>
11
+ <td>Ruby (MRI, JRuby, Windows)</td>
12
+ <td><pre>$ gem install foreman</pre></td>
13
+ </tr>
14
+ <tr>
15
+ <td>Mac OS X</td>
16
+ <td><a href="http://assets.foreman.io/foreman/foreman.pkg">foreman.pkg</a></td>
17
+ </tr>
18
+ </table>
19
+
20
+ ## Getting Started
21
+
22
+ * http://blog.daviddollar.org/2011/05/06/introducing-foreman.html
23
+
24
+ ## Documentation
25
+
26
+ * [man page](http://ddollar.github.com/foreman)
27
+ * [wiki](http://github.com/ddollar/foreman/wiki)
28
+
29
+ ## Authors
30
+
31
+ #### Created and maintained by
32
+ David Dollar
33
+
34
+ #### Patches contributed by
35
+ Adam Wiggins, Chris Continanza, Chris Lowder, Craig R Webster, Dan Farina, Dan Peterson, David Dollar, Fletcher Nichol, Gabriel Burt, Gamaliel Toro, Greg Reinacker, Hugues Le Gendre, Hunter Nield, Iain Hecker, Jay Zeschin, Keith Rarick, Khaja Minhajuddin, Lincoln Stoll, Marcos Muino Garcia, Mark McGranaghan, Matt Griffin, Matt Haynes, Matthijs Langenberg, Michael Dwan, Michael van Rooijen, Mike Javorski, Nathan Broadbent, Nathan L Smith, Nick Zadrozny, Phil Hagelberg, Ricardo Chimal, Jr, Thom May, Tom Ward, brainopia, clifff, jc00ke
36
+
37
+ ## License
38
+
39
+ MIT
data/bin/runner CHANGED
@@ -1,2 +1,36 @@
1
1
  #!/bin/sh
2
- exec $1 2>&1
2
+ #
3
+ #/ Usage: runner [-d <dir>] <command>
4
+ #/
5
+ #/ Run a command with exec, optionally changing directory first
6
+
7
+ set -e
8
+
9
+ error() {
10
+ echo $@ >&2
11
+ exit 1
12
+ }
13
+
14
+ usage() {
15
+ cat $0 | grep '^#/' | cut -c4-
16
+ exit
17
+ }
18
+
19
+ while getopts ":hd:" OPT; do
20
+ case $OPT in
21
+ d) cd $OPTARG ;;
22
+ h) usage ;;
23
+ \?) error "invalid option: -$OPTARG" ;;
24
+ :) error "option -$OPTARG requires an argument" ;;
25
+ esac
26
+ done
27
+
28
+ shift $((OPTIND-1))
29
+
30
+ command=$1
31
+
32
+ if [ -z "$1" ]; then
33
+ usage
34
+ fi
35
+
36
+ exec $1
@@ -5,7 +5,7 @@ Bluepill.application("<%= app %>", :foreground => false, :log_file => "/var/log/
5
5
 
6
6
  <% engine.procfile.entries.each do |process| %>
7
7
  <% 1.upto(concurrency[process.name]) do |num| %>
8
- <% port = engine.port_for(process, num, options[:port]) %>
8
+ <% port = engine.port_for(process, num, self.port) %>
9
9
  app.process("<%= process.name %>-<%=num%>") do |process|
10
10
  process.start_command = "<%= process.command.gsub("$PORT", port.to_s) %>"
11
11
 
data/lib/foreman/cli.rb CHANGED
@@ -1,10 +1,14 @@
1
1
  require "foreman"
2
+ require "foreman/helpers"
2
3
  require "foreman/engine"
3
4
  require "foreman/export"
4
5
  require "thor"
5
6
  require "yaml"
6
7
 
7
8
  class Foreman::CLI < Thor
9
+ include Foreman::Helpers
10
+
11
+ class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile"
8
12
 
9
13
  desc "start", "Start the application"
10
14
 
@@ -36,22 +40,12 @@ class Foreman::CLI < Thor
36
40
  method_option :port, :type => :numeric, :aliases => "-p"
37
41
  method_option :user, :type => :string, :aliases => "-u"
38
42
  method_option :template, :type => :string, :aliases => "-t"
39
- method_option :concurrency, :type => :string, :aliases => "-c",
40
- :banner => '"alpha=5,bar=3"'
43
+ method_option :concurrency, :type => :string, :aliases => "-c", :banner => '"alpha=5,bar=3"'
41
44
 
42
45
  def export(format, location=nil)
43
46
  check_procfile!
44
-
45
- formatter = case format
46
- when "inittab" then Foreman::Export::Inittab
47
- when "upstart" then Foreman::Export::Upstart
48
- when "bluepill" then Foreman::Export::Bluepill
49
- when "runit" then Foreman::Export::Runit
50
- else error "Unknown export format: #{format}."
51
- end
52
-
53
- formatter.new(engine).export(location, options)
54
-
47
+ formatter = Foreman::Export.formatter(format)
48
+ formatter.new(location, engine, options).export
55
49
  rescue Foreman::Export::Exception => ex
56
50
  error ex.message
57
51
  end
@@ -60,7 +54,7 @@ class Foreman::CLI < Thor
60
54
 
61
55
  def check
62
56
  error "no processes defined" unless engine.procfile.entries.length > 0
63
- display "valid procfile detected (#{engine.procfile.process_names.join(', ')})"
57
+ puts "valid procfile detected (#{engine.procfile.process_names.join(', ')})"
64
58
  end
65
59
 
66
60
  desc "run COMMAND", "Run a command using your application's environment"
@@ -90,19 +84,11 @@ private ######################################################################
90
84
  options[:procfile] || "Procfile"
91
85
  end
92
86
 
93
- def display(message)
94
- puts message
95
- end
96
-
97
87
  def error(message)
98
88
  puts "ERROR: #{message}"
99
89
  exit 1
100
90
  end
101
91
 
102
- def procfile_exists?(procfile)
103
- File.exist?(procfile)
104
- end
105
-
106
92
  def options
107
93
  original_options = super
108
94
  return original_options unless File.exists?(".foreman")
@@ -2,7 +2,6 @@ require "foreman"
2
2
  require "foreman/process"
3
3
  require "foreman/procfile"
4
4
  require "foreman/utils"
5
- require "pty"
6
5
  require "tempfile"
7
6
  require "timeout"
8
7
  require "term/ansicolor"
@@ -74,14 +73,22 @@ private ######################################################################
74
73
  def kill_all(signal="SIGTERM")
75
74
  running_processes.each do |pid, process|
76
75
  info "sending #{signal} to pid #{pid}"
77
- Process.kill(signal, pid) rescue Errno::ESRCH
76
+ process.kill signal
78
77
  end
79
78
  end
80
79
 
81
80
  def terminate_gracefully
81
+ return if @terminating
82
+ @terminating = true
82
83
  info "sending SIGTERM to all processes"
83
84
  kill_all "SIGTERM"
84
- Timeout.timeout(5) { Process.waitall }
85
+ Timeout.timeout(5) do
86
+ while running_processes.length > 0
87
+ pid, status = Process.wait2
88
+ process = running_processes.delete(pid)
89
+ info "process terminated", process.name
90
+ end
91
+ end
85
92
  rescue Timeout::Error
86
93
  info "sending SIGKILL to all processes"
87
94
  kill_all "SIGKILL"
@@ -89,11 +96,14 @@ private ######################################################################
89
96
 
90
97
  def watch_for_output
91
98
  Thread.new do
99
+ require "win32console" if Foreman.windows?
92
100
  begin
93
101
  loop do
94
102
  rs, ws = IO.select(readers.values, [], [], 1)
95
103
  (rs || []).each do |r|
96
- ps, message = r.gets.split(",", 2)
104
+ data = r.gets
105
+ next unless data
106
+ ps, message = data.split(",", 2)
97
107
  color = colors[ps.split(".").first]
98
108
  info message, ps, color
99
109
  end
@@ -110,16 +120,16 @@ private ######################################################################
110
120
  process = running_processes.delete(pid)
111
121
  info "process terminated", process.name
112
122
  terminate_gracefully
113
- kill_all
114
123
  rescue Errno::ECHILD
115
124
  end
116
125
 
117
126
  def info(message, name="system", color=Term::ANSIColor.white)
118
- print color
119
- print "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
120
- print Term::ANSIColor.reset
121
- print message.chomp
122
- puts ""
127
+ output = ""
128
+ output += color
129
+ output += "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
130
+ output += Term::ANSIColor.reset
131
+ output += message.chomp
132
+ puts output
123
133
  end
124
134
 
125
135
  def print(message=nil)
@@ -134,11 +144,6 @@ private ######################################################################
134
144
  end
135
145
  end
136
146
 
137
- def error(message)
138
- puts "ERROR: #{message}"
139
- exit 1
140
- end
141
-
142
147
  def longest_process_name
143
148
  @longest_process_name ||= begin
144
149
  longest = procfile.process_names.map { |name| name.length }.sort.last
@@ -156,7 +161,7 @@ private ######################################################################
156
161
  end
157
162
 
158
163
  def termtitle(title)
159
- printf("\033]0;#{title}\007")
164
+ printf("\033]0;#{title}\007") unless Foreman.windows?
160
165
  end
161
166
 
162
167
  def running_processes
@@ -217,6 +222,11 @@ private ######################################################################
217
222
  def apply_environment!
218
223
  @environment.each { |k,v| ENV[k] = v }
219
224
  end
225
+
226
+ def error(message)
227
+ puts "ERROR: #{message}"
228
+ exit 1
229
+ end
220
230
  end
221
231
 
222
232
  include Env
@@ -3,10 +3,17 @@ require "foreman/utils"
3
3
 
4
4
  class Foreman::Export::Base
5
5
 
6
- attr_reader :engine
7
-
8
- def initialize(engine)
9
- @engine = engine
6
+ attr_reader :location, :engine, :app, :log, :port, :user, :template, :concurrency
7
+
8
+ def initialize(location, engine, options={})
9
+ @location = location
10
+ @engine = engine
11
+ @app = options[:app]
12
+ @log = options[:log]
13
+ @port = options[:port]
14
+ @user = options[:user]
15
+ @template = options[:template]
16
+ @concurrency = Foreman::Utils.parse_concurrency(options[:concurrency])
10
17
  end
11
18
 
12
19
  def export
@@ -3,23 +3,21 @@ require "foreman/export"
3
3
 
4
4
  class Foreman::Export::Bluepill < Foreman::Export::Base
5
5
 
6
- def export(location, options={})
6
+ def export
7
7
  error("Must specify a location") unless location
8
8
 
9
9
  FileUtils.mkdir_p location
10
10
 
11
- app = options[:app] || File.basename(engine.directory)
12
- user = options[:user] || app
13
- log_root = options[:log] || "/var/log/#{app}"
14
- template_root = options[:template]
11
+ app = self.app || File.basename(engine.directory)
12
+ user = self.user || app
13
+ log_root = self.log || "/var/log/#{app}"
14
+ template_root = self.template
15
15
 
16
16
  Dir["#{location}/#{app}.pill"].each do |file|
17
17
  say "cleaning up: #{file}"
18
18
  FileUtils.rm(file)
19
19
  end
20
20
 
21
- concurrency = Foreman::Utils.parse_concurrency(options[:concurrency])
22
-
23
21
  master_template = export_template("bluepill", "master.pill.erb", template_root)
24
22
  master_config = ERB.new(master_template).result(binding)
25
23
  write_file "#{location}/#{app}.pill", master_config
@@ -2,20 +2,18 @@ require "foreman/export"
2
2
 
3
3
  class Foreman::Export::Inittab < Foreman::Export::Base
4
4
 
5
- def export(fname=nil, options={})
6
- app = options[:app] || File.basename(engine.directory)
7
- user = options[:user] || app
8
- log_root = options[:log] || "/var/log/#{app}"
9
-
10
- concurrency = Foreman::Utils.parse_concurrency(options[:concurrency])
5
+ def export
6
+ app = self.app || File.basename(engine.directory)
7
+ user = self.user || app
8
+ log_root = self.log || "/var/log/#{app}"
11
9
 
12
10
  inittab = []
13
11
  inittab << "# ----- foreman #{app} processes -----"
14
12
 
15
13
  engine.procfile.entries.inject(1) do |index, process|
16
- 1.upto(concurrency[process.name]) do |num|
14
+ 1.upto(self.concurrency[process.name]) do |num|
17
15
  id = app.slice(0, 2).upcase + sprintf("%02d", index)
18
- port = engine.port_for(process, num, options[:port])
16
+ port = engine.port_for(process, num, self.port)
19
17
  inittab << "#{id}:4:respawn:/bin/su - #{user} -c 'PORT=#{port} #{process.command} >> #{log_root}/#{process.name}-#{num}.log 2>&1'"
20
18
  index += 1
21
19
  end
@@ -26,12 +24,12 @@ class Foreman::Export::Inittab < Foreman::Export::Base
26
24
 
27
25
  inittab = inittab.join("\n") + "\n"
28
26
 
29
- if fname
27
+ if location == "-"
28
+ puts inittab
29
+ else
30
30
  FileUtils.mkdir_p(log_root) rescue error "could not create #{log_root}"
31
31
  FileUtils.chown(user, nil, log_root) rescue error "could not chown #{log_root} to #{user}"
32
- write_file(fname, inittab)
33
- else
34
- puts inittab
32
+ write_file(location, inittab)
35
33
  end
36
34
  end
37
35
 
@@ -4,21 +4,19 @@ require "foreman/export"
4
4
  class Foreman::Export::Runit < Foreman::Export::Base
5
5
  ENV_VARIABLE_REGEX = /([a-zA-Z_]+[a-zA-Z0-9_]*)=(\S+)/
6
6
 
7
- def export(location, options={})
7
+ def export
8
8
  error("Must specify a location") unless location
9
9
 
10
- app = options[:app] || File.basename(engine.directory)
11
- user = options[:user] || app
12
- log_root = options[:log] || "/var/log/#{app}"
13
- template_root = options[:template]
14
-
15
- concurrency = Foreman::Utils.parse_concurrency(options[:concurrency])
10
+ app = self.app || File.basename(engine.directory)
11
+ user = self.user || app
12
+ log_root = self.log || "/var/log/#{app}"
13
+ template_root = self.template
16
14
 
17
15
  run_template = export_template('runit', 'run.erb', template_root)
18
16
  log_run_template = export_template('runit', 'log_run.erb', template_root)
19
17
 
20
18
  engine.procfile.entries.each do |process|
21
- 1.upto(concurrency[process.name]) do |num|
19
+ 1.upto(self.concurrency[process.name]) do |num|
22
20
  process_directory = "#{location}/#{app}-#{process.name}-#{num}"
23
21
  process_env_directory = "#{process_directory}/env"
24
22
  process_log_directory = "#{process_directory}/log"
@@ -31,7 +29,7 @@ class Foreman::Export::Runit < Foreman::Export::Base
31
29
  write_file "#{process_directory}/run", run
32
30
  FileUtils.chmod 0755, "#{process_directory}/run"
33
31
 
34
- port = engine.port_for(process, num, options[:port])
32
+ port = engine.port_for(process, num, self.port)
35
33
  environment_variables = {'PORT' => port}.
36
34
  merge(engine.environment).
37
35
  merge(inline_variables(process.command))
@@ -51,7 +49,7 @@ class Foreman::Export::Runit < Foreman::Export::Base
51
49
  private
52
50
  def create_directory(location)
53
51
  say "creating: #{location}"
54
- FileUtils.mkdir(location)
52
+ FileUtils.mkdir_p(location)
55
53
  end
56
54
 
57
55
  def inline_variables(command)
@@ -3,23 +3,21 @@ require "foreman/export"
3
3
 
4
4
  class Foreman::Export::Upstart < Foreman::Export::Base
5
5
 
6
- def export(location, options={})
6
+ def export
7
7
  error("Must specify a location") unless location
8
8
 
9
9
  FileUtils.mkdir_p location
10
10
 
11
- app = options[:app] || File.basename(engine.directory)
12
- user = options[:user] || app
13
- log_root = options[:log] || "/var/log/#{app}"
14
- template_root = options[:template]
11
+ app = self.app || File.basename(engine.directory)
12
+ user = self.user || app
13
+ log_root = self.log || "/var/log/#{app}"
14
+ template_root = self.template
15
15
 
16
16
  Dir["#{location}/#{app}*.conf"].each do |file|
17
17
  say "cleaning up: #{file}"
18
18
  FileUtils.rm(file)
19
19
  end
20
20
 
21
- concurrency = Foreman::Utils.parse_concurrency(options[:concurrency])
22
-
23
21
  master_template = export_template("upstart", "master.conf.erb", template_root)
24
22
  master_config = ERB.new(master_template).result(binding)
25
23
  write_file "#{location}/#{app}.conf", master_config
@@ -27,13 +25,13 @@ class Foreman::Export::Upstart < Foreman::Export::Base
27
25
  process_template = export_template("upstart", "process.conf.erb", template_root)
28
26
 
29
27
  engine.procfile.entries.each do |process|
30
- next if (conc = concurrency[process.name]) < 1
28
+ next if (conc = self.concurrency[process.name]) < 1
31
29
  process_master_template = export_template("upstart", "process_master.conf.erb", template_root)
32
30
  process_master_config = ERB.new(process_master_template).result(binding)
33
31
  write_file "#{location}/#{app}-#{process.name}.conf", process_master_config
34
32
 
35
- 1.upto(concurrency[process.name]) do |num|
36
- port = engine.port_for(process, num, options[:port])
33
+ 1.upto(self.concurrency[process.name]) do |num|
34
+ port = engine.port_for(process, num, self.port)
37
35
  process_config = ERB.new(process_template).result(binding)
38
36
  write_file "#{location}/#{app}-#{process.name}-#{num}.conf", process_config
39
37
  end
@@ -1,9 +1,30 @@
1
1
  require "foreman"
2
+ require "foreman/helpers"
2
3
 
3
4
  module Foreman::Export
5
+ extend Foreman::Helpers
6
+
4
7
  class Exception < ::Exception; end
8
+
9
+ def self.formatter(format)
10
+ begin
11
+ require "foreman/export/#{ format.tr('-', '_') }"
12
+ classy_format = classify(format)
13
+ formatter = constantize("Foreman::Export::#{ classy_format }")
14
+ rescue NameError => ex
15
+ error "Unknown export format: #{format} (no class Foreman::Export::#{ classy_format })."
16
+ rescue LoadError => ex
17
+ error "Unknown export format: #{format} (unable to load file 'foreman/export/#{ format.tr('-', '_') }')."
18
+ end
19
+ end
20
+
21
+ def self.error(message)
22
+ raise Foreman::Export::Exception.new(message)
23
+ end
24
+
5
25
  end
6
26
 
27
+
7
28
  require "foreman/export/base"
8
29
  require "foreman/export/inittab"
9
30
  require "foreman/export/upstart"
@@ -0,0 +1,45 @@
1
+ module Foreman::Helpers
2
+ # Copied whole sale from, https://github.com/defunkt/resque/
3
+
4
+ # Given a word with dashes, returns a camel cased version of it.
5
+ #
6
+ # classify('job-name') # => 'JobName'
7
+ def classify(dashed_word)
8
+ dashed_word.split('-').each { |part| part[0] = part[0].chr.upcase }.join
9
+ end # Tries to find a constant with the name specified in the argument string:
10
+
11
+ #
12
+ # constantize("Module") # => Module
13
+ # constantize("Test::Unit") # => Test::Unit
14
+ #
15
+ # The name is assumed to be the one of a top-level constant, no matter
16
+ # whether it starts with "::" or not. No lexical context is taken into
17
+ # account:
18
+ #
19
+ # C = 'outside'
20
+ # module M
21
+ # C = 'inside'
22
+ # C # => 'inside'
23
+ # constantize("C") # => 'outside', same as ::C
24
+ # end
25
+ #
26
+ # NameError is raised when the constant is unknown.
27
+ def constantize(camel_cased_word)
28
+ camel_cased_word = camel_cased_word.to_s
29
+
30
+ names = camel_cased_word.split('::')
31
+ names.shift if names.empty? || names.first.empty?
32
+
33
+ constant = Object
34
+ names.each do |name|
35
+ args = Module.method(:const_get).arity != 1 ? [false] : []
36
+
37
+ if constant.const_defined?(name, *args)
38
+ constant = constant.const_get(name)
39
+ else
40
+ constant = constant.const_missing(name)
41
+ end
42
+ end
43
+ constant
44
+ end
45
+ end
@@ -1,4 +1,5 @@
1
1
  require "foreman"
2
+ require "rubygems"
2
3
 
3
4
  class Foreman::Process
4
5
 
@@ -14,10 +15,8 @@ class Foreman::Process
14
15
  end
15
16
 
16
17
  def run(pipe, basedir, environment)
17
- Dir.chdir(basedir) do
18
- with_environment(environment.merge("PORT" => port.to_s)) do
19
- run_process entry.command, pipe
20
- end
18
+ with_environment(environment.merge("PORT" => port.to_s)) do
19
+ run_process basedir, entry.command, pipe
21
20
  end
22
21
  end
23
22
 
@@ -25,23 +24,52 @@ class Foreman::Process
25
24
  "%s.%s" % [ entry.name, num ]
26
25
  end
27
26
 
27
+ def kill(signal)
28
+ pid && Process.kill(signal, pid)
29
+ rescue Errno::ESRCH
30
+ false
31
+ end
32
+
33
+ def detach
34
+ pid && Process.detach(pid)
35
+ end
36
+
37
+ def alive?
38
+ kill(0)
39
+ end
40
+
41
+ def dead?
42
+ !alive?
43
+ end
44
+
28
45
  private
29
46
 
30
- def fork_with_io(command)
47
+ def fork_with_io(command, basedir)
31
48
  reader, writer = IO.pipe
32
- pid = fork do
33
- trap("INT", "IGNORE")
34
- writer.sync = true
35
- $stdout.reopen writer
36
- $stderr.reopen writer
37
- reader.close
38
- exec Foreman.runner, replace_command_env(command)
49
+ command = replace_command_env(command)
50
+ pid = if Foreman.windows?
51
+ Dir.chdir(basedir) do
52
+ Process.spawn command, :out => writer, :err => writer
53
+ end
54
+ elsif Foreman.jruby?
55
+ require "posix/spawn"
56
+ POSIX::Spawn.spawn(Foreman.runner, "-d", basedir, command, {
57
+ :out => writer, :err => writer
58
+ })
59
+ else
60
+ fork do
61
+ writer.sync = true
62
+ $stdout.reopen writer
63
+ $stderr.reopen writer
64
+ reader.close
65
+ exec Foreman.runner, "-d", basedir, command
66
+ end
39
67
  end
40
68
  [ reader, pid ]
41
69
  end
42
70
 
43
- def run_process(command, pipe)
44
- io, @pid = fork_with_io(command)
71
+ def run_process(basedir, command, pipe)
72
+ io, @pid = fork_with_io(command, basedir)
45
73
  output pipe, "started with pid %d" % @pid
46
74
  Thread.new do
47
75
  until io.eof?
@@ -59,12 +87,10 @@ private
59
87
  end
60
88
 
61
89
  def with_environment(environment)
62
- old_env = ENV.each_pair.inject({}) { |h,(k,v)| h.update(k => v) }
63
- environment.each { |k,v| ENV[k] = v }
64
- ret = yield
65
- ENV.clear
66
- old_env.each { |k,v| ENV[k] = v}
67
- ret
90
+ original = ENV.to_hash
91
+ ENV.update environment
92
+ yield
93
+ ensure
94
+ ENV.replace original
68
95
  end
69
-
70
96
  end
@@ -1,5 +1,5 @@
1
1
  module Foreman
2
2
 
3
- VERSION = "0.36.1"
3
+ VERSION = "0.37.0"
4
4
 
5
5
  end
data/lib/foreman.rb CHANGED
@@ -14,5 +14,12 @@ module Foreman
14
14
  File.expand_path("../../bin/runner", __FILE__)
15
15
  end
16
16
 
17
- end
17
+ def self.jruby?
18
+ defined?(RUBY_PLATFORM) and RUBY_PLATFORM == "java"
19
+ end
18
20
 
21
+ def self.windows?
22
+ defined?(RUBY_PLATFORM) and RUBY_PLATFORM =~ /(win|w)32$/
23
+ end
24
+
25
+ end