erails 2.1.2
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/CHANGELOG +3 -0
- data/MIT-LICENSE +20 -0
- data/README +309 -0
- data/Rakefile +339 -0
- data/bin/about +4 -0
- data/bin/console +3 -0
- data/bin/dbconsole +3 -0
- data/bin/destroy +3 -0
- data/bin/erails +19 -0
- data/bin/generate +3 -0
- data/bin/performance/benchmarker +3 -0
- data/bin/performance/profiler +3 -0
- data/bin/performance/request +3 -0
- data/bin/plugin +3 -0
- data/bin/process/inspector +3 -0
- data/bin/process/reaper +3 -0
- data/bin/process/spawner +3 -0
- data/bin/runner +3 -0
- data/bin/server +3 -0
- data/builtin/rails_info/rails/info.rb +125 -0
- data/builtin/rails_info/rails/info_controller.rb +9 -0
- data/builtin/rails_info/rails/info_helper.rb +2 -0
- data/builtin/rails_info/rails_info_controller.rb +2 -0
- data/configs/apache.conf +40 -0
- data/configs/databases/frontbase.yml +28 -0
- data/configs/databases/mysql.yml +54 -0
- data/configs/databases/oracle.yml +39 -0
- data/configs/databases/postgresql.yml +48 -0
- data/configs/databases/sqlite2.yml +16 -0
- data/configs/databases/sqlite3.yml +19 -0
- data/configs/empty.log +0 -0
- data/configs/initializers/inflections.rb +10 -0
- data/configs/initializers/mime_types.rb +5 -0
- data/configs/initializers/new_rails_defaults.rb +17 -0
- data/configs/lighttpd.conf +54 -0
- data/configs/routes.rb +43 -0
- data/dispatches/dispatch.fcgi +24 -0
- data/dispatches/dispatch.rb +10 -0
- data/dispatches/gateway.cgi +97 -0
- data/doc/README_FOR_APP +2 -0
- data/environments/boot.rb +109 -0
- data/environments/development.rb +16 -0
- data/environments/environment.rb +71 -0
- data/environments/production.rb +22 -0
- data/environments/test.rb +22 -0
- data/fresh_rakefile +10 -0
- data/helpers/application.rb +15 -0
- data/helpers/application_helper.rb +3 -0
- data/helpers/test_helper.rb +38 -0
- data/html/404.html +30 -0
- data/html/422.html +30 -0
- data/html/500.html +30 -0
- data/html/favicon.ico +0 -0
- data/html/images/rails.png +0 -0
- data/html/index.html +274 -0
- data/html/javascripts/application.js +2 -0
- data/html/robots.txt +5 -0
- data/lib/code_statistics.rb +107 -0
- data/lib/commands/about.rb +3 -0
- data/lib/commands/console.rb +32 -0
- data/lib/commands/dbconsole.rb +67 -0
- data/lib/commands/destroy.rb +6 -0
- data/lib/commands/generate.rb +6 -0
- data/lib/commands/ncgi/listener +86 -0
- data/lib/commands/ncgi/tracker +69 -0
- data/lib/commands/performance/benchmarker.rb +24 -0
- data/lib/commands/performance/profiler.rb +50 -0
- data/lib/commands/performance/request.rb +6 -0
- data/lib/commands/plugin.rb +950 -0
- data/lib/commands/process/inspector.rb +68 -0
- data/lib/commands/process/reaper.rb +149 -0
- data/lib/commands/process/spawner.rb +219 -0
- data/lib/commands/process/spinner.rb +57 -0
- data/lib/commands/runner.rb +48 -0
- data/lib/commands/server.rb +39 -0
- data/lib/commands/servers/base.rb +31 -0
- data/lib/commands/servers/lighttpd.rb +94 -0
- data/lib/commands/servers/mongrel.rb +69 -0
- data/lib/commands/servers/new_mongrel.rb +16 -0
- data/lib/commands/servers/webrick.rb +66 -0
- data/lib/commands/update.rb +4 -0
- data/lib/commands.rb +17 -0
- data/lib/console_app.rb +30 -0
- data/lib/console_sandbox.rb +6 -0
- data/lib/console_with_helpers.rb +26 -0
- data/lib/dispatcher.rb +24 -0
- data/lib/fcgi_handler.rb +239 -0
- data/lib/initializer.rb +926 -0
- data/lib/rails/gem_builder.rb +21 -0
- data/lib/rails/gem_dependency.rb +129 -0
- data/lib/rails/mongrel_server/commands.rb +342 -0
- data/lib/rails/mongrel_server/handler.rb +55 -0
- data/lib/rails/plugin/loader.rb +152 -0
- data/lib/rails/plugin/locator.rb +100 -0
- data/lib/rails/plugin.rb +116 -0
- data/lib/rails/version.rb +9 -0
- data/lib/rails_generator/base.rb +263 -0
- data/lib/rails_generator/commands.rb +622 -0
- data/lib/rails_generator/generated_attribute.rb +42 -0
- data/lib/rails_generator/generators/applications/app/USAGE +9 -0
- data/lib/rails_generator/generators/applications/app/app_generator.rb +174 -0
- data/lib/rails_generator/generators/components/controller/USAGE +29 -0
- data/lib/rails_generator/generators/components/controller/controller_generator.rb +37 -0
- data/lib/rails_generator/generators/components/controller/templates/controller.rb +7 -0
- data/lib/rails_generator/generators/components/controller/templates/functional_test.rb +8 -0
- data/lib/rails_generator/generators/components/controller/templates/helper.rb +2 -0
- data/lib/rails_generator/generators/components/controller/templates/view.html.erb +2 -0
- data/lib/rails_generator/generators/components/integration_test/USAGE +8 -0
- data/lib/rails_generator/generators/components/integration_test/integration_test_generator.rb +16 -0
- data/lib/rails_generator/generators/components/integration_test/templates/integration_test.rb +10 -0
- data/lib/rails_generator/generators/components/mailer/USAGE +16 -0
- data/lib/rails_generator/generators/components/mailer/mailer_generator.rb +30 -0
- data/lib/rails_generator/generators/components/mailer/templates/fixture.erb +3 -0
- data/lib/rails_generator/generators/components/mailer/templates/fixture.rhtml +0 -0
- data/lib/rails_generator/generators/components/mailer/templates/mailer.rb +15 -0
- data/lib/rails_generator/generators/components/mailer/templates/unit_test.rb +21 -0
- data/lib/rails_generator/generators/components/mailer/templates/view.erb +3 -0
- data/lib/rails_generator/generators/components/mailer/templates/view.rhtml +0 -0
- data/lib/rails_generator/generators/components/migration/USAGE +29 -0
- data/lib/rails_generator/generators/components/migration/migration_generator.rb +20 -0
- data/lib/rails_generator/generators/components/migration/templates/migration.rb +11 -0
- data/lib/rails_generator/generators/components/model/USAGE +27 -0
- data/lib/rails_generator/generators/components/model/model_generator.rb +45 -0
- data/lib/rails_generator/generators/components/model/templates/fixtures.yml +19 -0
- data/lib/rails_generator/generators/components/model/templates/migration.rb +16 -0
- data/lib/rails_generator/generators/components/model/templates/model.rb +2 -0
- data/lib/rails_generator/generators/components/model/templates/unit_test.rb +8 -0
- data/lib/rails_generator/generators/components/observer/USAGE +13 -0
- data/lib/rails_generator/generators/components/observer/observer_generator.rb +16 -0
- data/lib/rails_generator/generators/components/observer/templates/observer.rb +2 -0
- data/lib/rails_generator/generators/components/observer/templates/unit_test.rb +8 -0
- data/lib/rails_generator/generators/components/plugin/USAGE +25 -0
- data/lib/rails_generator/generators/components/plugin/plugin_generator.rb +39 -0
- data/lib/rails_generator/generators/components/plugin/templates/MIT-LICENSE +20 -0
- data/lib/rails_generator/generators/components/plugin/templates/README +13 -0
- data/lib/rails_generator/generators/components/plugin/templates/Rakefile +22 -0
- data/lib/rails_generator/generators/components/plugin/templates/USAGE +8 -0
- data/lib/rails_generator/generators/components/plugin/templates/generator.rb +8 -0
- data/lib/rails_generator/generators/components/plugin/templates/init.rb +1 -0
- data/lib/rails_generator/generators/components/plugin/templates/install.rb +1 -0
- data/lib/rails_generator/generators/components/plugin/templates/plugin.rb +1 -0
- data/lib/rails_generator/generators/components/plugin/templates/tasks.rake +4 -0
- data/lib/rails_generator/generators/components/plugin/templates/uninstall.rb +1 -0
- data/lib/rails_generator/generators/components/plugin/templates/unit_test.rb +8 -0
- data/lib/rails_generator/generators/components/resource/USAGE +23 -0
- data/lib/rails_generator/generators/components/resource/resource_generator.rb +74 -0
- data/lib/rails_generator/generators/components/resource/templates/controller.rb +2 -0
- data/lib/rails_generator/generators/components/resource/templates/functional_test.rb +8 -0
- data/lib/rails_generator/generators/components/resource/templates/helper.rb +2 -0
- data/lib/rails_generator/generators/components/scaffold/USAGE +25 -0
- data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +93 -0
- data/lib/rails_generator/generators/components/scaffold/templates/controller.rb +85 -0
- data/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb +45 -0
- data/lib/rails_generator/generators/components/scaffold/templates/helper.rb +2 -0
- data/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb +17 -0
- data/lib/rails_generator/generators/components/scaffold/templates/style.css +54 -0
- data/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb +18 -0
- data/lib/rails_generator/generators/components/scaffold/templates/view_index.html.erb +24 -0
- data/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb +17 -0
- data/lib/rails_generator/generators/components/scaffold/templates/view_show.html.erb +10 -0
- data/lib/rails_generator/generators/components/session_migration/USAGE +10 -0
- data/lib/rails_generator/generators/components/session_migration/session_migration_generator.rb +18 -0
- data/lib/rails_generator/generators/components/session_migration/templates/migration.rb +16 -0
- data/lib/rails_generator/lookup.rb +249 -0
- data/lib/rails_generator/manifest.rb +53 -0
- data/lib/rails_generator/options.rb +150 -0
- data/lib/rails_generator/scripts/destroy.rb +30 -0
- data/lib/rails_generator/scripts/generate.rb +7 -0
- data/lib/rails_generator/scripts/update.rb +12 -0
- data/lib/rails_generator/scripts.rb +89 -0
- data/lib/rails_generator/secret_key_generator.rb +164 -0
- data/lib/rails_generator/simple_logger.rb +46 -0
- data/lib/rails_generator/spec.rb +44 -0
- data/lib/rails_generator.rb +43 -0
- data/lib/railties_path.rb +1 -0
- data/lib/ruby_version_check.rb +17 -0
- data/lib/rubyprof_ext.rb +35 -0
- data/lib/source_annotation_extractor.rb +102 -0
- data/lib/tasks/annotations.rake +23 -0
- data/lib/tasks/databases.rake +389 -0
- data/lib/tasks/documentation.rake +80 -0
- data/lib/tasks/framework.rake +105 -0
- data/lib/tasks/gems.rake +64 -0
- data/lib/tasks/log.rake +9 -0
- data/lib/tasks/misc.rake +57 -0
- data/lib/tasks/rails.rb +8 -0
- data/lib/tasks/routes.rake +17 -0
- data/lib/tasks/statistics.rake +18 -0
- data/lib/tasks/testing.rake +118 -0
- data/lib/tasks/tmp.rake +37 -0
- data/lib/test_help.rb +28 -0
- data/lib/webrick_server.rb +165 -0
- metadata +356 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rubygems/installer'
|
|
3
|
+
|
|
4
|
+
module Rails
|
|
5
|
+
|
|
6
|
+
# this class hijacks the functionality of Gem::Installer by overloading its
|
|
7
|
+
# initializer to only provide the information needed by
|
|
8
|
+
# Gem::Installer#build_extensions (which happens to be what we have)
|
|
9
|
+
class GemBuilder < Gem::Installer
|
|
10
|
+
|
|
11
|
+
def initialize(spec, gem_dir)
|
|
12
|
+
@spec = spec
|
|
13
|
+
@gem_dir = gem_dir
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# silence the underlying builder
|
|
17
|
+
def say(message)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
class GemDependency
|
|
3
|
+
attr_accessor :name, :requirement, :version, :lib, :source
|
|
4
|
+
|
|
5
|
+
def self.unpacked_path
|
|
6
|
+
@unpacked_path ||= File.join(RAILS_ROOT, 'vendor', 'gems')
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def initialize(name, options = {})
|
|
10
|
+
require 'rubygems' unless Object.const_defined?(:Gem)
|
|
11
|
+
|
|
12
|
+
if options[:requirement]
|
|
13
|
+
@requirement = options[:requirement]
|
|
14
|
+
elsif options[:version]
|
|
15
|
+
@requirement = Gem::Requirement.create(options[:version])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
@version = @requirement.instance_variable_get("@requirements").first.last if @requirement
|
|
19
|
+
@name = name.to_s
|
|
20
|
+
@lib = options[:lib]
|
|
21
|
+
@source = options[:source]
|
|
22
|
+
@loaded = @frozen = @load_paths_added = false
|
|
23
|
+
@unpack_directory = nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def unpacked_paths
|
|
27
|
+
Dir[File.join(self.class.unpacked_path, "#{@name}-#{@version || "*"}")]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def add_load_paths
|
|
31
|
+
return if @loaded || @load_paths_added
|
|
32
|
+
unpacked_paths = self.unpacked_paths
|
|
33
|
+
if unpacked_paths.empty?
|
|
34
|
+
args = [@name]
|
|
35
|
+
args << @requirement.to_s if @requirement
|
|
36
|
+
gem *args
|
|
37
|
+
else
|
|
38
|
+
$LOAD_PATH.unshift File.join(unpacked_paths.first, 'lib')
|
|
39
|
+
ext = File.join(unpacked_paths.first, 'ext')
|
|
40
|
+
$LOAD_PATH.unshift(ext) if File.exist?(ext)
|
|
41
|
+
@frozen = true
|
|
42
|
+
end
|
|
43
|
+
@load_paths_added = true
|
|
44
|
+
rescue Gem::LoadError
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def dependencies
|
|
48
|
+
all_dependencies = specification.dependencies.map do |dependency|
|
|
49
|
+
GemDependency.new(dependency.name, :requirement => dependency.version_requirements)
|
|
50
|
+
end
|
|
51
|
+
all_dependencies += all_dependencies.map(&:dependencies).flatten
|
|
52
|
+
all_dependencies.uniq
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def gem_dir(base_directory)
|
|
56
|
+
File.join(base_directory, specification.full_name)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def load
|
|
60
|
+
return if @loaded || @load_paths_added == false
|
|
61
|
+
require(@lib || @name) unless @lib == false
|
|
62
|
+
@loaded = true
|
|
63
|
+
rescue LoadError
|
|
64
|
+
puts $!.to_s
|
|
65
|
+
$!.backtrace.each { |b| puts b }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def frozen?
|
|
69
|
+
@frozen
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def loaded?
|
|
73
|
+
@loaded
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def load_paths_added?
|
|
77
|
+
@load_paths_added
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def install
|
|
81
|
+
cmd = "#{gem_command} #{install_command.join(' ')}"
|
|
82
|
+
puts cmd
|
|
83
|
+
puts %x(#{cmd})
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def unpack_to(directory)
|
|
87
|
+
FileUtils.mkdir_p directory
|
|
88
|
+
Dir.chdir directory do
|
|
89
|
+
Gem::GemRunner.new.run(unpack_command)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# copy the gem's specification into GEMDIR/.specification so that
|
|
93
|
+
# we can access information about the gem on deployment systems
|
|
94
|
+
# without having the gem installed
|
|
95
|
+
spec_filename = File.join(gem_dir(directory), '.specification')
|
|
96
|
+
File.open(spec_filename, 'w') do |file|
|
|
97
|
+
file.puts specification.to_yaml
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def ==(other)
|
|
102
|
+
self.name == other.name && self.requirement == other.requirement
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def specification
|
|
106
|
+
@spec ||= Gem.source_index.search(Gem::Dependency.new(@name, @requirement)).sort_by { |s| s.version }.last
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
private
|
|
110
|
+
def gem_command
|
|
111
|
+
RUBY_PLATFORM =~ /win32/ ? 'gem.bat' : 'gem'
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def install_command
|
|
115
|
+
cmd = %w(install) << @name
|
|
116
|
+
cmd << "--version" << %("#{@requirement.to_s}") if @requirement
|
|
117
|
+
cmd << "--source" << @source if @source
|
|
118
|
+
cmd
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def unpack_command
|
|
122
|
+
cmd = %w(unpack) << @name
|
|
123
|
+
# We don't quote this requirement as it's run through GemRunner instead
|
|
124
|
+
# of shelling out to gem
|
|
125
|
+
cmd << "--version" << @requirement.to_s if @requirement
|
|
126
|
+
cmd
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# Copyright (c) 2005 Zed A. Shaw
|
|
2
|
+
# You can redistribute it and/or modify it under the same terms as Ruby.
|
|
3
|
+
#
|
|
4
|
+
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
|
5
|
+
# for more information.
|
|
6
|
+
|
|
7
|
+
require 'optparse'
|
|
8
|
+
require 'yaml'
|
|
9
|
+
require 'etc'
|
|
10
|
+
|
|
11
|
+
require 'mongrel'
|
|
12
|
+
require 'rails/mongrel_server/handler'
|
|
13
|
+
|
|
14
|
+
module Rails
|
|
15
|
+
module MongrelServer
|
|
16
|
+
def self.send_signal(signal, pid_file)
|
|
17
|
+
pid = open(pid_file).read.to_i
|
|
18
|
+
print "Sending #{signal} to Mongrel at PID #{pid}..."
|
|
19
|
+
begin
|
|
20
|
+
Process.kill(signal, pid)
|
|
21
|
+
rescue Errno::ESRCH
|
|
22
|
+
puts "Process does not exist. Not running."
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
puts "Done."
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class RailsConfigurator < Mongrel::Configurator
|
|
29
|
+
def setup_mime_types
|
|
30
|
+
mime = {}
|
|
31
|
+
|
|
32
|
+
if defaults[:mime_map]
|
|
33
|
+
Mongrel.log("Loading additional MIME types from #{defaults[:mime_map]}")
|
|
34
|
+
mime = load_mime_map(defaults[:mime_map], mime)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
mime.each {|k,v| Mongrel::DirHandler::add_mime_type(k,v) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def mount_rails(prefix)
|
|
41
|
+
ENV['RAILS_ENV'] = defaults[:environment]
|
|
42
|
+
::RAILS_ENV.replace(defaults[:environment]) if defined?(::RAILS_ENV)
|
|
43
|
+
|
|
44
|
+
env_location = "#{defaults[:cwd]}/config/environment"
|
|
45
|
+
require env_location
|
|
46
|
+
|
|
47
|
+
ActionController::AbstractRequest.relative_url_root = defaults[:prefix]
|
|
48
|
+
uri prefix, :handler => Rails::MongrelServer::RailsHandler.new
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class Start < GemPlugin::Plugin "/commands"
|
|
53
|
+
include Mongrel::Command::Base
|
|
54
|
+
|
|
55
|
+
def configure
|
|
56
|
+
options [
|
|
57
|
+
["-e", "--environment ENV", "Rails environment to run as", :@environment, ENV['RAILS_ENV'] || "development"],
|
|
58
|
+
["-d", "--daemonize", "Run daemonized in the background", :@daemon, false],
|
|
59
|
+
['-p', '--port PORT', "Which port to bind to", :@port, 3000],
|
|
60
|
+
['-a', '--address ADDR', "Address to bind to", :@address, "0.0.0.0"],
|
|
61
|
+
['-l', '--log FILE', "Where to write log messages", :@log_file, "log/mongrel.log"],
|
|
62
|
+
['-P', '--pid FILE', "Where to write the PID", :@pid_file, "tmp/pids/mongrel.pid"],
|
|
63
|
+
['-n', '--num-procs INT', "Number of processors active before clients denied", :@num_procs, 1024],
|
|
64
|
+
['-o', '--timeout TIME', "Time to wait (in seconds) before killing a stalled thread", :@timeout, 60],
|
|
65
|
+
['-t', '--throttle TIME', "Time to pause (in hundredths of a second) between accepting clients", :@throttle, 0],
|
|
66
|
+
['-m', '--mime PATH', "A YAML file that lists additional MIME types", :@mime_map, nil],
|
|
67
|
+
['-c', '--chdir PATH', "Change to dir before starting (will be expanded)", :@cwd, RAILS_ROOT],
|
|
68
|
+
['-r', '--root PATH', "Set the document root (default 'public')", :@docroot, "public"],
|
|
69
|
+
['-B', '--debug', "Enable debugging mode", :@debug, false],
|
|
70
|
+
['-C', '--config PATH', "Use a config file", :@config_file, nil],
|
|
71
|
+
['-S', '--script PATH', "Load the given file as an extra config script", :@config_script, nil],
|
|
72
|
+
['-G', '--generate PATH', "Generate a config file for use with -C", :@generate, nil],
|
|
73
|
+
['', '--user USER', "User to run as", :@user, nil],
|
|
74
|
+
['', '--group GROUP', "Group to run as", :@group, nil],
|
|
75
|
+
['', '--prefix PATH', "URL prefix for Rails app", :@prefix, nil],
|
|
76
|
+
|
|
77
|
+
['-b', '--binding ADDR', "Address to bind to (deprecated, use -a)", :@address, "0.0.0.0"],
|
|
78
|
+
['-u', '--debugger', "Enable debugging mode (deprecated, use -B)", :@debug, false]
|
|
79
|
+
]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def validate
|
|
83
|
+
if @config_file
|
|
84
|
+
valid_exists?(@config_file, "Config file not there: #@config_file")
|
|
85
|
+
return false unless @valid
|
|
86
|
+
@config_file = File.expand_path(@config_file)
|
|
87
|
+
load_config
|
|
88
|
+
return false unless @valid
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
@cwd = File.expand_path(@cwd)
|
|
92
|
+
valid_dir? @cwd, "Invalid path to change to during daemon mode: #@cwd"
|
|
93
|
+
|
|
94
|
+
# Change there to start, then we'll have to come back after daemonize
|
|
95
|
+
Dir.chdir(@cwd)
|
|
96
|
+
|
|
97
|
+
valid?(@prefix[0] == ?/ && @prefix[-1] != ?/, "Prefix must begin with / and not end in /") if @prefix
|
|
98
|
+
valid_dir? File.dirname(@log_file), "Path to log file not valid: #@log_file"
|
|
99
|
+
valid_dir? File.dirname(@pid_file), "Path to pid file not valid: #@pid_file"
|
|
100
|
+
valid_dir? @docroot, "Path to docroot not valid: #@docroot"
|
|
101
|
+
valid_exists? @mime_map, "MIME mapping file does not exist: #@mime_map" if @mime_map
|
|
102
|
+
valid_exists? @config_file, "Config file not there: #@config_file" if @config_file
|
|
103
|
+
valid_dir? File.dirname(@generate), "Problem accessing directory to #@generate" if @generate
|
|
104
|
+
valid_user? @user if @user
|
|
105
|
+
valid_group? @group if @group
|
|
106
|
+
|
|
107
|
+
return @valid
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def run
|
|
111
|
+
if @generate
|
|
112
|
+
@generate = File.expand_path(@generate)
|
|
113
|
+
Mongrel.log(:error, "** Writing config to \"#@generate\".")
|
|
114
|
+
open(@generate, "w") {|f| f.write(settings.to_yaml) }
|
|
115
|
+
Mongrel.log(:error, "** Finished. Run \"mongrel_rails start -C #@generate\" to use the config file.")
|
|
116
|
+
exit 0
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
config = RailsConfigurator.new(settings) do
|
|
120
|
+
defaults[:log] = $stdout if defaults[:environment] == 'development'
|
|
121
|
+
|
|
122
|
+
Mongrel.log("=> Enhanced Rails #{Rails.version} application starting on http://#{defaults[:host]}:#{defaults[:port]}")
|
|
123
|
+
|
|
124
|
+
unless defaults[:daemon]
|
|
125
|
+
Mongrel.log("=> Call with -d to detach")
|
|
126
|
+
Mongrel.log("=> Ctrl-C to shutdown server")
|
|
127
|
+
start_debugger if defaults[:debug]
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
if defaults[:daemon]
|
|
131
|
+
if File.exist? defaults[:pid_file]
|
|
132
|
+
Mongrel.log(:error, "!!! PID file #{defaults[:pid_file]} already exists. Mongrel could be running already. Check your #{defaults[:log_file]} for errors.")
|
|
133
|
+
Mongrel.log(:error, "!!! Exiting with error. You must stop mongrel and clear the .pid before I'll attempt a start.")
|
|
134
|
+
exit 1
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
daemonize
|
|
138
|
+
|
|
139
|
+
Mongrel.log("Daemonized, any open files are closed. Look at #{defaults[:pid_file]} and #{defaults[:log_file]} for info.")
|
|
140
|
+
Mongrel.log("Settings loaded from #{@config_file} (they override command line).") if @config_file
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
Mongrel.log("Starting Mongrel listening at #{defaults[:host]}:#{defaults[:port]}, further information can be found in log/mongrel-#{defaults[:host]}-#{defaults[:port]}.log")
|
|
144
|
+
|
|
145
|
+
listener do
|
|
146
|
+
prefix = defaults[:prefix] || '/'
|
|
147
|
+
|
|
148
|
+
if defaults[:debug]
|
|
149
|
+
Mongrel.log("Installing debugging prefixed filters. Look in log/mongrel_debug for the files.")
|
|
150
|
+
debug(prefix)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
setup_mime_types
|
|
154
|
+
dir_handler = Mongrel::DirHandler.new(defaults[:docroot], false)
|
|
155
|
+
dir_handler.passthrough_missing_files = true
|
|
156
|
+
|
|
157
|
+
unless defaults[:environment] == 'production'
|
|
158
|
+
Mongrel.log("Mounting DirHandler at #{prefix}...")
|
|
159
|
+
uri prefix, :handler => dir_handler
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
Mongrel.log("Starting Rails with #{defaults[:environment]} environment...")
|
|
164
|
+
Mongrel.log("Mounting Rails at #{prefix}...")
|
|
165
|
+
mount_rails(prefix)
|
|
166
|
+
Mongrel.log("Rails loaded.")
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
Mongrel.log("Loading any Rails specific GemPlugins" )
|
|
170
|
+
load_plugins
|
|
171
|
+
|
|
172
|
+
if defaults[:config_script]
|
|
173
|
+
Mongrel.log("Loading #{defaults[:config_script]} external config script")
|
|
174
|
+
run_config(defaults[:config_script])
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
setup_signals
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
config.run
|
|
182
|
+
Mongrel.log("Mongrel #{Mongrel::Const::MONGREL_VERSION} available at #{@address}:#{@port}")
|
|
183
|
+
|
|
184
|
+
if config.defaults[:daemon]
|
|
185
|
+
config.write_pid_file
|
|
186
|
+
else
|
|
187
|
+
Mongrel.log("Use CTRL-C to stop.")
|
|
188
|
+
tail "log/#{config.defaults[:environment]}.log"
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
config.join
|
|
192
|
+
|
|
193
|
+
if config.needs_restart
|
|
194
|
+
unless RUBY_PLATFORM =~ /djgpp|(cyg|ms|bcc)win|mingw/
|
|
195
|
+
cmd = "ruby #{__FILE__} start #{original_args.join(' ')}"
|
|
196
|
+
Mongrel.log("Restarting with arguments: #{cmd}")
|
|
197
|
+
config.stop(false, true)
|
|
198
|
+
config.remove_pid_file
|
|
199
|
+
|
|
200
|
+
if config.defaults[:daemon]
|
|
201
|
+
system cmd
|
|
202
|
+
else
|
|
203
|
+
Mongrel.log(:error, "Can't restart unless in daemon mode.")
|
|
204
|
+
exit 1
|
|
205
|
+
end
|
|
206
|
+
else
|
|
207
|
+
Mongrel.log("Win32 does not support restarts. Exiting.")
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def load_config
|
|
213
|
+
settings = {}
|
|
214
|
+
begin
|
|
215
|
+
settings = YAML.load_file(@config_file)
|
|
216
|
+
ensure
|
|
217
|
+
Mongrel.log(:error, "** Loading settings from #{@config_file} (they override command line).") unless @daemon || settings[:daemon]
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
settings[:includes] ||= ["mongrel"]
|
|
221
|
+
|
|
222
|
+
# Config file settings will override command line settings
|
|
223
|
+
settings.each do |key, value|
|
|
224
|
+
key = key.to_s
|
|
225
|
+
if config_keys.include?(key)
|
|
226
|
+
key = 'address' if key == 'host'
|
|
227
|
+
self.instance_variable_set("@#{key}", value)
|
|
228
|
+
else
|
|
229
|
+
failure "Unknown configuration setting: #{key}"
|
|
230
|
+
@valid = false
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def config_keys
|
|
236
|
+
@config_keys ||=
|
|
237
|
+
%w(address host port cwd log_file pid_file environment docroot mime_map daemon debug includes config_script num_processors timeout throttle user group prefix)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def settings
|
|
241
|
+
config_keys.inject({}) do |hash, key|
|
|
242
|
+
value = self.instance_variable_get("@#{key}")
|
|
243
|
+
key = 'host' if key == 'address'
|
|
244
|
+
hash[key.to_sym] ||= value
|
|
245
|
+
hash
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def start_debugger
|
|
250
|
+
require_library_or_gem 'ruby-debug'
|
|
251
|
+
Debugger.start
|
|
252
|
+
Debugger.settings[:autoeval] = true if Debugger.respond_to?(:settings)
|
|
253
|
+
Mongrel.log("=> Debugger enabled")
|
|
254
|
+
rescue Exception
|
|
255
|
+
Mongrel.log(:error, "You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'")
|
|
256
|
+
exit
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def tail(log_file)
|
|
260
|
+
cursor = File.size(log_file)
|
|
261
|
+
last_checked = Time.now
|
|
262
|
+
tail_thread = Thread.new do
|
|
263
|
+
File.open(log_file, 'r') do |f|
|
|
264
|
+
loop do
|
|
265
|
+
f.seek cursor
|
|
266
|
+
if f.mtime > last_checked
|
|
267
|
+
last_checked = f.mtime
|
|
268
|
+
contents = f.read
|
|
269
|
+
cursor += contents.length
|
|
270
|
+
print contents
|
|
271
|
+
end
|
|
272
|
+
sleep 1
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
tail_thread
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
class Stop < GemPlugin::Plugin "/commands"
|
|
281
|
+
include Mongrel::Command::Base
|
|
282
|
+
|
|
283
|
+
def configure
|
|
284
|
+
options [
|
|
285
|
+
['-c', '--chdir PATH', "Change to dir before starting (will be expanded).", :@cwd, "."],
|
|
286
|
+
['-f', '--force', "Force the shutdown (kill -9).", :@force, false],
|
|
287
|
+
['-w', '--wait SECONDS', "Wait SECONDS before forcing shutdown", :@wait, "0"],
|
|
288
|
+
['-P', '--pid FILE', "Where the PID file is located.", :@pid_file, "log/mongrel.pid"]
|
|
289
|
+
]
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def validate
|
|
293
|
+
@cwd = File.expand_path(@cwd)
|
|
294
|
+
valid_dir? @cwd, "Invalid path to change to during daemon mode: #@cwd"
|
|
295
|
+
|
|
296
|
+
Dir.chdir @cwd
|
|
297
|
+
|
|
298
|
+
valid_exists? @pid_file, "PID file #@pid_file does not exist. Not running?"
|
|
299
|
+
return @valid
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def run
|
|
303
|
+
if @force
|
|
304
|
+
@wait.to_i.times do |waiting|
|
|
305
|
+
exit(0) if not File.exist? @pid_file
|
|
306
|
+
sleep 1
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
Mongrel::send_signal("KILL", @pid_file) if File.exist? @pid_file
|
|
310
|
+
else
|
|
311
|
+
Mongrel::send_signal("TERM", @pid_file)
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
class Restart < GemPlugin::Plugin "/commands"
|
|
318
|
+
include Mongrel::Command::Base
|
|
319
|
+
|
|
320
|
+
def configure
|
|
321
|
+
options [
|
|
322
|
+
['-c', '--chdir PATH', "Change to dir before starting (will be expanded)", :@cwd, '.'],
|
|
323
|
+
['-P', '--pid FILE', "Where the PID file is located", :@pid_file, "log/mongrel.pid"]
|
|
324
|
+
]
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
def validate
|
|
328
|
+
@cwd = File.expand_path(@cwd)
|
|
329
|
+
valid_dir? @cwd, "Invalid path to change to during daemon mode: #@cwd"
|
|
330
|
+
|
|
331
|
+
Dir.chdir @cwd
|
|
332
|
+
|
|
333
|
+
valid_exists? @pid_file, "PID file #@pid_file does not exist. Not running?"
|
|
334
|
+
return @valid
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def run
|
|
338
|
+
MongrelServer::send_signal("USR2", @pid_file)
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Copyright (c) 2005 Zed A. Shaw
|
|
2
|
+
# You can redistribute it and/or modify it under the same terms as Ruby.
|
|
3
|
+
#
|
|
4
|
+
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
|
5
|
+
# for more information.
|
|
6
|
+
|
|
7
|
+
require 'mongrel'
|
|
8
|
+
require 'cgi'
|
|
9
|
+
require 'action_controller/dispatcher'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
module Rails
|
|
13
|
+
module MongrelServer
|
|
14
|
+
# Implements a handler that can run Rails and serve files out of the
|
|
15
|
+
# Rails application's public directory. This lets you run your Rails
|
|
16
|
+
# application with Mongrel during development and testing, then use it
|
|
17
|
+
# also in production behind a server that's better at serving the
|
|
18
|
+
# static files.
|
|
19
|
+
#
|
|
20
|
+
# The RailsHandler takes a mime_map parameter which is a simple suffix=mimetype
|
|
21
|
+
# mapping that it should add to the list of valid mime types.
|
|
22
|
+
#
|
|
23
|
+
# It also supports page caching directly and will try to resolve a request
|
|
24
|
+
# in the following order:
|
|
25
|
+
#
|
|
26
|
+
# * If the requested exact PATH_INFO exists as a file then serve it.
|
|
27
|
+
# * If it exists at PATH_INFO+".html" exists then serve that.
|
|
28
|
+
# * Finally, construct a Mongrel::CGIWrapper and run Dispatcher.dispatch to have Rails go.
|
|
29
|
+
#
|
|
30
|
+
# This means that if you are using page caching it will actually work with Mongrel
|
|
31
|
+
# and you should see a decent speed boost (but not as fast as if you use a static
|
|
32
|
+
# server like Apache or Litespeed).
|
|
33
|
+
class RailsHandler < Mongrel::HttpHandler
|
|
34
|
+
# Construct a Mongrel::CGIWrapper and dispatch.
|
|
35
|
+
def process(request, response)
|
|
36
|
+
return if response.socket.closed?
|
|
37
|
+
|
|
38
|
+
cgi = Mongrel::CGIWrapper.new(request, response)
|
|
39
|
+
cgi.handler = self
|
|
40
|
+
# We don't want the output to be really final until we're out of the lock
|
|
41
|
+
cgi.default_really_final = false
|
|
42
|
+
|
|
43
|
+
ActionController::Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, response.body)
|
|
44
|
+
|
|
45
|
+
# This finalizes the output using the proper HttpResponse way
|
|
46
|
+
cgi.out("text/html",true) {""}
|
|
47
|
+
rescue Errno::EPIPE
|
|
48
|
+
response.socket.close
|
|
49
|
+
rescue Object => rails_error
|
|
50
|
+
STDERR.puts "#{Time.now.httpdate}: Error dispatching #{rails_error.inspect}"
|
|
51
|
+
STDERR.puts rails_error.backtrace.join("\n")
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
require "rails/plugin"
|
|
2
|
+
|
|
3
|
+
module Rails
|
|
4
|
+
class Plugin
|
|
5
|
+
class Loader
|
|
6
|
+
attr_reader :initializer
|
|
7
|
+
|
|
8
|
+
# Creates a new Plugin::Loader instance, associated with the given
|
|
9
|
+
# Rails::Initializer. This default implementation automatically locates
|
|
10
|
+
# all plugins, and adds all plugin load paths, when it is created. The plugins
|
|
11
|
+
# are then fully loaded (init.rb is evaluated) when load_plugins is called.
|
|
12
|
+
#
|
|
13
|
+
# It is the loader's responsibility to ensure that only the plugins specified
|
|
14
|
+
# in the configuration are actually loaded, and that the order defined
|
|
15
|
+
# is respected.
|
|
16
|
+
def initialize(initializer)
|
|
17
|
+
@initializer = initializer
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Returns the plugins to be loaded, in the order they should be loaded.
|
|
21
|
+
def plugins
|
|
22
|
+
@plugins ||= all_plugins.select { |plugin| should_load?(plugin) }.sort { |p1, p2| order_plugins(p1, p2) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Returns all the plugins that could be found by the current locators.
|
|
26
|
+
def all_plugins
|
|
27
|
+
@all_plugins ||= locate_plugins
|
|
28
|
+
@all_plugins
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def load_plugins
|
|
32
|
+
plugins.each do |plugin|
|
|
33
|
+
plugin.load(initializer)
|
|
34
|
+
register_plugin_as_loaded(plugin)
|
|
35
|
+
end
|
|
36
|
+
ensure_all_registered_plugins_are_loaded!
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Adds the load paths for every plugin into the $LOAD_PATH. Plugin load paths are
|
|
40
|
+
# added *after* the application's <tt>lib</tt> directory, to ensure that an application
|
|
41
|
+
# can always override code within a plugin.
|
|
42
|
+
#
|
|
43
|
+
# Plugin load paths are also added to Dependencies.load_paths, and Dependencies.load_once_paths.
|
|
44
|
+
def add_plugin_load_paths
|
|
45
|
+
plugins.each do |plugin|
|
|
46
|
+
plugin.load_paths.each do |path|
|
|
47
|
+
$LOAD_PATH.insert(application_lib_index + 1, path)
|
|
48
|
+
ActiveSupport::Dependencies.load_paths << path
|
|
49
|
+
unless Rails.configuration.reload_plugins?
|
|
50
|
+
ActiveSupport::Dependencies.load_once_paths << path
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
$LOAD_PATH.uniq!
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
protected
|
|
58
|
+
|
|
59
|
+
# The locate_plugins method uses each class in config.plugin_locators to
|
|
60
|
+
# find the set of all plugins available to this Rails application.
|
|
61
|
+
def locate_plugins
|
|
62
|
+
configuration.plugin_locators.map { |locator|
|
|
63
|
+
locator.new(initializer).plugins
|
|
64
|
+
}.flatten
|
|
65
|
+
# TODO: sorting based on config.plugins
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def register_plugin_as_loaded(plugin)
|
|
69
|
+
initializer.loaded_plugins << plugin
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def configuration
|
|
73
|
+
initializer.configuration
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def should_load?(plugin)
|
|
77
|
+
# uses Plugin#name and Plugin#valid?
|
|
78
|
+
enabled?(plugin) && plugin.valid?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def order_plugins(plugin_a, plugin_b)
|
|
82
|
+
if !explicit_plugin_loading_order?
|
|
83
|
+
plugin_a <=> plugin_b
|
|
84
|
+
else
|
|
85
|
+
if !explicitly_enabled?(plugin_a) && !explicitly_enabled?(plugin_b)
|
|
86
|
+
plugin_a <=> plugin_b
|
|
87
|
+
else
|
|
88
|
+
effective_order_of(plugin_a) <=> effective_order_of(plugin_b)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def effective_order_of(plugin)
|
|
94
|
+
if explicitly_enabled?(plugin)
|
|
95
|
+
registered_plugin_names.index(plugin.name)
|
|
96
|
+
else
|
|
97
|
+
registered_plugin_names.index('all')
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def application_lib_index
|
|
102
|
+
$LOAD_PATH.index(File.join(RAILS_ROOT, 'lib')) || 0
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def enabled?(plugin)
|
|
106
|
+
!explicit_plugin_loading_order? || registered?(plugin)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def explicit_plugin_loading_order?
|
|
110
|
+
!registered_plugin_names.nil?
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def registered?(plugin)
|
|
114
|
+
explicit_plugin_loading_order? && registered_plugins_names_plugin?(plugin)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def explicitly_enabled?(plugin)
|
|
118
|
+
!explicit_plugin_loading_order? || explicitly_registered?(plugin)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def explicitly_registered?(plugin)
|
|
122
|
+
explicit_plugin_loading_order? && registered_plugin_names.include?(plugin.name)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def registered_plugins_names_plugin?(plugin)
|
|
126
|
+
registered_plugin_names.include?(plugin.name) || registered_plugin_names.include?('all')
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# The plugins that have been explicitly listed with config.plugins. If this list is nil
|
|
130
|
+
# then it means the client does not care which plugins or in what order they are loaded,
|
|
131
|
+
# so we load all in alphabetical order. If it is an empty array, we load no plugins, if it is
|
|
132
|
+
# non empty, we load the named plugins in the order specified.
|
|
133
|
+
def registered_plugin_names
|
|
134
|
+
configuration.plugins ? configuration.plugins.map(&:to_s) : nil
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def loaded?(plugin_name)
|
|
138
|
+
initializer.loaded_plugins.detect { |plugin| plugin.name == plugin_name.to_s }
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def ensure_all_registered_plugins_are_loaded!
|
|
142
|
+
if explicit_plugin_loading_order?
|
|
143
|
+
if configuration.plugins.detect {|plugin| plugin != :all && !loaded?(plugin) }
|
|
144
|
+
missing_plugins = configuration.plugins - (plugins + [:all])
|
|
145
|
+
raise LoadError, "Could not locate the following plugins: #{missing_plugins.to_sentence}"
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|