Checkout of Instiki Trunk 1/21/2007.
This commit is contained in:
commit
69b62b6f33
1138 changed files with 139586 additions and 0 deletions
2
vendor/rails/railties/lib/commands/about.rb
vendored
Normal file
2
vendor/rails/railties/lib/commands/about.rb
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
require 'environment'
|
||||
puts Rails::Info
|
1
vendor/rails/railties/lib/commands/breakpointer.rb
vendored
Normal file
1
vendor/rails/railties/lib/commands/breakpointer.rb
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
require 'breakpoint_client'
|
25
vendor/rails/railties/lib/commands/console.rb
vendored
Normal file
25
vendor/rails/railties/lib/commands/console.rb
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
irb = RUBY_PLATFORM =~ /mswin32/ ? 'irb.bat' : 'irb'
|
||||
|
||||
require 'optparse'
|
||||
options = { :sandbox => false, :irb => irb }
|
||||
OptionParser.new do |opt|
|
||||
opt.banner = "Usage: console [environment] [options]"
|
||||
opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v }
|
||||
opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |v| options[:irb] = v }
|
||||
opt.parse!(ARGV)
|
||||
end
|
||||
|
||||
libs = " -r irb/completion"
|
||||
libs << " -r #{RAILS_ROOT}/config/environment"
|
||||
libs << " -r console_app"
|
||||
libs << " -r console_sandbox" if options[:sandbox]
|
||||
libs << " -r console_with_helpers"
|
||||
|
||||
ENV['RAILS_ENV'] = ARGV.first || ENV['RAILS_ENV'] || 'development'
|
||||
if options[:sandbox]
|
||||
puts "Loading #{ENV['RAILS_ENV']} environment in sandbox."
|
||||
puts "Any modifications you make will be rolled back on exit."
|
||||
else
|
||||
puts "Loading #{ENV['RAILS_ENV']} environment."
|
||||
end
|
||||
exec "#{options[:irb]} #{libs} --simple-prompt"
|
6
vendor/rails/railties/lib/commands/destroy.rb
vendored
Normal file
6
vendor/rails/railties/lib/commands/destroy.rb
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
require "#{RAILS_ROOT}/config/environment"
|
||||
require 'rails_generator'
|
||||
require 'rails_generator/scripts/destroy'
|
||||
|
||||
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
||||
Rails::Generator::Scripts::Destroy.new.run(ARGV)
|
6
vendor/rails/railties/lib/commands/generate.rb
vendored
Executable file
6
vendor/rails/railties/lib/commands/generate.rb
vendored
Executable file
|
@ -0,0 +1,6 @@
|
|||
require "#{RAILS_ROOT}/config/environment"
|
||||
require 'rails_generator'
|
||||
require 'rails_generator/scripts/generate'
|
||||
|
||||
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
||||
Rails::Generator::Scripts::Generate.new.run(ARGV)
|
86
vendor/rails/railties/lib/commands/ncgi/listener
vendored
Normal file
86
vendor/rails/railties/lib/commands/ncgi/listener
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
#!/usr/local/bin/ruby
|
||||
|
||||
require 'stringio'
|
||||
require 'fileutils'
|
||||
require 'fcgi_handler'
|
||||
|
||||
def message(s)
|
||||
$stderr.puts "listener: #{s}" if ENV && ENV["DEBUG_GATEWAY"]
|
||||
end
|
||||
|
||||
class RemoteCGI < CGI
|
||||
attr_accessor :stdinput, :stdoutput, :env_table
|
||||
def initialize(env_table, input = nil, output = nil)
|
||||
self.env_table = env_table
|
||||
self.stdinput = input || StringIO.new
|
||||
self.stdoutput = output || StringIO.new
|
||||
super()
|
||||
end
|
||||
|
||||
def out(stream) # Ignore the requested output stream
|
||||
super(stdoutput)
|
||||
end
|
||||
end
|
||||
|
||||
class Listener
|
||||
include DRbUndumped
|
||||
|
||||
def initialize(timeout, socket_path)
|
||||
@socket = File.expand_path(socket_path)
|
||||
@mutex = Mutex.new
|
||||
@active = false
|
||||
@timeout = timeout
|
||||
|
||||
@handler = RailsFCGIHandler.new
|
||||
@handler.extend DRbUndumped
|
||||
|
||||
message 'opening socket'
|
||||
DRb.start_service("drbunix:#{@socket}", self)
|
||||
|
||||
message 'entering process loop'
|
||||
@handler.process! self
|
||||
end
|
||||
|
||||
def each_cgi(&cgi_block)
|
||||
@cgi_block = cgi_block
|
||||
message 'entering idle loop'
|
||||
loop do
|
||||
sleep @timeout rescue nil
|
||||
die! unless @active
|
||||
@active = false
|
||||
end
|
||||
end
|
||||
|
||||
def process(env, input)
|
||||
message 'received request'
|
||||
@mutex.synchronize do
|
||||
@active = true
|
||||
|
||||
message 'creating input stream'
|
||||
input_stream = StringIO.new(input)
|
||||
message 'building CGI instance'
|
||||
cgi = RemoteCGI.new(eval(env), input_stream)
|
||||
|
||||
message 'yielding to fcgi handler'
|
||||
@cgi_block.call cgi
|
||||
message 'yield finished -- sending output'
|
||||
|
||||
cgi.stdoutput.seek(0)
|
||||
output = cgi.stdoutput.read
|
||||
|
||||
return output
|
||||
end
|
||||
end
|
||||
|
||||
def die!
|
||||
message 'shutting down'
|
||||
DRb.stop_service
|
||||
FileUtils.rm_f @socket
|
||||
Kernel.exit 0
|
||||
end
|
||||
end
|
||||
|
||||
socket_path = ARGV.shift
|
||||
timeout = (ARGV.shift || 90).to_i
|
||||
|
||||
Listener.new(timeout, socket_path)
|
69
vendor/rails/railties/lib/commands/ncgi/tracker
vendored
Normal file
69
vendor/rails/railties/lib/commands/ncgi/tracker
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
#!/usr/local/bin/ruby
|
||||
|
||||
require 'drb'
|
||||
require 'thread'
|
||||
|
||||
def message(s)
|
||||
$stderr.puts "tracker: #{s}" if ENV && ENV["DEBUG_GATEWAY"]
|
||||
end
|
||||
|
||||
class Tracker
|
||||
include DRbUndumped
|
||||
|
||||
def initialize(instances, socket_path)
|
||||
@instances = instances
|
||||
@socket = File.expand_path(socket_path)
|
||||
@active = false
|
||||
|
||||
@listeners = []
|
||||
@instances.times { @listeners << Mutex.new }
|
||||
|
||||
message "using #{@listeners.length} listeners"
|
||||
message "opening socket at #{@socket}"
|
||||
|
||||
@service = DRb.start_service("drbunix://#{@socket}", self)
|
||||
end
|
||||
|
||||
def with_listener
|
||||
message "listener requested"
|
||||
|
||||
mutex = has_lock = index = nil
|
||||
3.times do
|
||||
@listeners.each_with_index do |mutex, index|
|
||||
has_lock = mutex.try_lock
|
||||
break if has_lock
|
||||
end
|
||||
break if has_lock
|
||||
sleep 0.05
|
||||
end
|
||||
|
||||
if has_lock
|
||||
message "obtained listener #{index}"
|
||||
@active = true
|
||||
begin yield index
|
||||
ensure
|
||||
mutex.unlock
|
||||
message "released listener #{index}"
|
||||
end
|
||||
else
|
||||
message "dropping request because no listeners are available!"
|
||||
end
|
||||
end
|
||||
|
||||
def background(check_interval = nil)
|
||||
if check_interval
|
||||
loop do
|
||||
sleep check_interval
|
||||
message "Idle for #{check_interval}, shutting down" unless @active
|
||||
@active = false
|
||||
Kernel.exit 0
|
||||
end
|
||||
else DRb.thread.join
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
socket_path = ARGV.shift
|
||||
instances = ARGV.shift.to_i
|
||||
t = Tracker.new(instances, socket_path)
|
||||
t.background(ARGV.first ? ARGV.shift.to_i : 90)
|
24
vendor/rails/railties/lib/commands/performance/benchmarker.rb
vendored
Normal file
24
vendor/rails/railties/lib/commands/performance/benchmarker.rb
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
if ARGV.empty?
|
||||
puts "Usage: ./script/performance/benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ..."
|
||||
exit 1
|
||||
end
|
||||
|
||||
begin
|
||||
N = Integer(ARGV.first)
|
||||
ARGV.shift
|
||||
rescue ArgumentError
|
||||
N = 1
|
||||
end
|
||||
|
||||
require RAILS_ROOT + '/config/environment'
|
||||
require 'benchmark'
|
||||
include Benchmark
|
||||
|
||||
# Don't include compilation in the benchmark
|
||||
ARGV.each { |expression| eval(expression) }
|
||||
|
||||
bm(6) do |x|
|
||||
ARGV.each_with_index do |expression, idx|
|
||||
x.report("##{idx + 1}") { N.times { eval(expression) } }
|
||||
end
|
||||
end
|
34
vendor/rails/railties/lib/commands/performance/profiler.rb
vendored
Normal file
34
vendor/rails/railties/lib/commands/performance/profiler.rb
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
if ARGV.empty?
|
||||
$stderr.puts "Usage: ./script/performance/profiler 'Person.expensive_method(10)' [times]"
|
||||
exit(1)
|
||||
end
|
||||
|
||||
# Keep the expensive require out of the profile.
|
||||
$stderr.puts 'Loading Rails...'
|
||||
require RAILS_ROOT + '/config/environment'
|
||||
|
||||
# Define a method to profile.
|
||||
if ARGV[1] and ARGV[1].to_i > 1
|
||||
eval "def profile_me() #{ARGV[1]}.times { #{ARGV[0]} } end"
|
||||
else
|
||||
eval "def profile_me() #{ARGV[0]} end"
|
||||
end
|
||||
|
||||
# Use the ruby-prof extension if available. Fall back to stdlib profiler.
|
||||
begin
|
||||
require 'prof'
|
||||
$stderr.puts 'Using the ruby-prof extension.'
|
||||
Prof.clock_mode = Prof::GETTIMEOFDAY
|
||||
Prof.start
|
||||
profile_me
|
||||
results = Prof.stop
|
||||
require 'rubyprof_ext'
|
||||
Prof.print_profile(results, $stderr)
|
||||
rescue LoadError
|
||||
require 'profiler'
|
||||
$stderr.puts 'Using the standard Ruby profiler.'
|
||||
Profiler__.start_profile
|
||||
profile_me
|
||||
Profiler__.stop_profile
|
||||
Profiler__.print_profile($stderr)
|
||||
end
|
871
vendor/rails/railties/lib/commands/plugin.rb
vendored
Normal file
871
vendor/rails/railties/lib/commands/plugin.rb
vendored
Normal file
|
@ -0,0 +1,871 @@
|
|||
# Rails Plugin Manager.
|
||||
#
|
||||
# Listing available plugins:
|
||||
#
|
||||
# $ ./script/plugin list
|
||||
# continuous_builder http://dev.rubyonrails.com/svn/rails/plugins/continuous_builder
|
||||
# asset_timestamping http://svn.aviditybytes.com/rails/plugins/asset_timestamping
|
||||
# enumerations_mixin http://svn.protocool.com/rails/plugins/enumerations_mixin/trunk
|
||||
# calculations http://techno-weenie.net/svn/projects/calculations/
|
||||
# ...
|
||||
#
|
||||
# Installing plugins:
|
||||
#
|
||||
# $ ./script/plugin install continuous_builder asset_timestamping
|
||||
#
|
||||
# Finding Repositories:
|
||||
#
|
||||
# $ ./script/plugin discover
|
||||
#
|
||||
# Adding Repositories:
|
||||
#
|
||||
# $ ./script/plugin source http://svn.protocool.com/rails/plugins/
|
||||
#
|
||||
# How it works:
|
||||
#
|
||||
# * Maintains a list of subversion repositories that are assumed to have
|
||||
# a plugin directory structure. Manage them with the (source, unsource,
|
||||
# and sources commands)
|
||||
#
|
||||
# * The discover command scrapes the following page for things that
|
||||
# look like subversion repositories with plugins:
|
||||
# http://wiki.rubyonrails.org/rails/pages/Plugins
|
||||
#
|
||||
# * Unless you specify that you want to use svn, script/plugin uses plain old
|
||||
# HTTP for downloads. The following bullets are true if you specify
|
||||
# that you want to use svn.
|
||||
#
|
||||
# * If `vendor/plugins` is under subversion control, the script will
|
||||
# modify the svn:externals property and perform an update. You can
|
||||
# use normal subversion commands to keep the plugins up to date.
|
||||
#
|
||||
# * Or, if `vendor/plugins` is not under subversion control, the
|
||||
# plugin is pulled via `svn checkout` or `svn export` but looks
|
||||
# exactly the same.
|
||||
#
|
||||
# This is Free Software, copyright 2005 by Ryan Tomayko (rtomayko@gmail.com)
|
||||
# and is licensed MIT: (http://www.opensource.org/licenses/mit-license.php)
|
||||
|
||||
$verbose = false
|
||||
|
||||
|
||||
require 'open-uri'
|
||||
require 'fileutils'
|
||||
require 'tempfile'
|
||||
|
||||
include FileUtils
|
||||
|
||||
class RailsEnvironment
|
||||
attr_reader :root
|
||||
|
||||
def initialize(dir)
|
||||
@root = dir
|
||||
end
|
||||
|
||||
def self.find(dir=nil)
|
||||
dir ||= pwd
|
||||
while dir.length > 1
|
||||
return new(dir) if File.exist?(File.join(dir, 'config', 'environment.rb'))
|
||||
dir = File.dirname(dir)
|
||||
end
|
||||
end
|
||||
|
||||
def self.default
|
||||
@default ||= find
|
||||
end
|
||||
|
||||
def self.default=(rails_env)
|
||||
@default = rails_env
|
||||
end
|
||||
|
||||
def install(name_uri_or_plugin)
|
||||
if name_uri_or_plugin.is_a? String
|
||||
if name_uri_or_plugin =~ /:\/\//
|
||||
plugin = Plugin.new(name_uri_or_plugin)
|
||||
else
|
||||
plugin = Plugins[name_uri_or_plugin]
|
||||
end
|
||||
else
|
||||
plugin = name_uri_or_plugin
|
||||
end
|
||||
unless plugin.nil?
|
||||
plugin.install
|
||||
else
|
||||
puts "plugin not found: #{name_uri_or_plugin}"
|
||||
end
|
||||
end
|
||||
|
||||
def use_svn?
|
||||
require 'active_support/core_ext/kernel'
|
||||
silence_stderr {`svn --version` rescue nil}
|
||||
!$?.nil? && $?.success?
|
||||
end
|
||||
|
||||
def use_externals?
|
||||
use_svn? && File.directory?("#{root}/vendor/plugins/.svn")
|
||||
end
|
||||
|
||||
def use_checkout?
|
||||
# this is a bit of a guess. we assume that if the rails environment
|
||||
# is under subversion then they probably want the plugin checked out
|
||||
# instead of exported. This can be overridden on the command line
|
||||
File.directory?("#{root}/.svn")
|
||||
end
|
||||
|
||||
def best_install_method
|
||||
return :http unless use_svn?
|
||||
case
|
||||
when use_externals? then :externals
|
||||
when use_checkout? then :checkout
|
||||
else :export
|
||||
end
|
||||
end
|
||||
|
||||
def externals
|
||||
return [] unless use_externals?
|
||||
ext = `svn propget svn:externals "#{root}/vendor/plugins"`
|
||||
ext.reject{ |line| line.strip == '' }.map do |line|
|
||||
line.strip.split(/\s+/, 2)
|
||||
end
|
||||
end
|
||||
|
||||
def externals=(items)
|
||||
unless items.is_a? String
|
||||
items = items.map{|name,uri| "#{name.ljust(29)} #{uri.chomp('/')}"}.join("\n")
|
||||
end
|
||||
Tempfile.open("svn-set-prop") do |file|
|
||||
file.write(items)
|
||||
file.flush
|
||||
system("svn propset -q svn:externals -F #{file.path} \"#{root}/vendor/plugins\"")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Plugin
|
||||
attr_reader :name, :uri
|
||||
|
||||
def initialize(uri, name=nil)
|
||||
@uri = uri
|
||||
guess_name(uri)
|
||||
end
|
||||
|
||||
def to_s
|
||||
"#{@name.ljust(30)}#{@uri}"
|
||||
end
|
||||
|
||||
def installed?
|
||||
File.directory?("#{rails_env.root}/vendor/plugins/#{name}") \
|
||||
or rails_env.externals.detect{ |name, repo| self.uri == repo }
|
||||
end
|
||||
|
||||
def install(method=nil, options = {})
|
||||
method ||= rails_env.best_install_method?
|
||||
method = :export if method == :http and @uri =~ /svn:\/\/*/
|
||||
|
||||
uninstall if installed? and options[:force]
|
||||
|
||||
unless installed?
|
||||
send("install_using_#{method}", options)
|
||||
run_install_hook
|
||||
else
|
||||
puts "already installed: #{name} (#{uri}). pass --force to reinstall"
|
||||
end
|
||||
end
|
||||
|
||||
def uninstall
|
||||
path = "#{rails_env.root}/vendor/plugins/#{name}"
|
||||
if File.directory?(path)
|
||||
puts "Removing 'vendor/plugins/#{name}'" if $verbose
|
||||
rm_r path
|
||||
else
|
||||
puts "Plugin doesn't exist: #{path}"
|
||||
end
|
||||
# clean up svn:externals
|
||||
externals = rails_env.externals
|
||||
externals.reject!{|n,u| name == n or name == u}
|
||||
rails_env.externals = externals
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def run_install_hook
|
||||
install_hook_file = "#{rails_env.root}/vendor/plugins/#{name}/install.rb"
|
||||
load install_hook_file if File.exists? install_hook_file
|
||||
end
|
||||
|
||||
def install_using_export(options = {})
|
||||
svn_command :export, options
|
||||
end
|
||||
|
||||
def install_using_checkout(options = {})
|
||||
svn_command :checkout, options
|
||||
end
|
||||
|
||||
def install_using_externals(options = {})
|
||||
externals = rails_env.externals
|
||||
externals.push([@name, uri])
|
||||
rails_env.externals = externals
|
||||
install_using_checkout(options)
|
||||
end
|
||||
|
||||
def install_using_http(options = {})
|
||||
root = rails_env.root
|
||||
mkdir_p "#{root}/vendor/plugins"
|
||||
Dir.chdir "#{root}/vendor/plugins"
|
||||
puts "fetching from '#{uri}'" if $verbose
|
||||
fetcher = RecursiveHTTPFetcher.new(uri)
|
||||
fetcher.quiet = true if options[:quiet]
|
||||
fetcher.fetch
|
||||
end
|
||||
|
||||
def svn_command(cmd, options = {})
|
||||
root = rails_env.root
|
||||
mkdir_p "#{root}/vendor/plugins"
|
||||
base_cmd = "svn #{cmd} #{uri} \"#{root}/vendor/plugins/#{name}\""
|
||||
base_cmd += ' -q' if options[:quiet] and not $verbose
|
||||
base_cmd += " -r #{options[:revision]}" if options[:revision]
|
||||
puts base_cmd if $verbose
|
||||
system(base_cmd)
|
||||
end
|
||||
|
||||
def guess_name(url)
|
||||
@name = File.basename(url)
|
||||
if @name == 'trunk' || @name.empty?
|
||||
@name = File.basename(File.dirname(url))
|
||||
end
|
||||
end
|
||||
|
||||
def rails_env
|
||||
@rails_env || RailsEnvironment.default
|
||||
end
|
||||
end
|
||||
|
||||
class Repositories
|
||||
include Enumerable
|
||||
|
||||
def initialize(cache_file = File.join(find_home, ".rails-plugin-sources"))
|
||||
@cache_file = File.expand_path(cache_file)
|
||||
load!
|
||||
end
|
||||
|
||||
def each(&block)
|
||||
@repositories.each(&block)
|
||||
end
|
||||
|
||||
def add(uri)
|
||||
unless find{|repo| repo.uri == uri }
|
||||
@repositories.push(Repository.new(uri)).last
|
||||
end
|
||||
end
|
||||
|
||||
def remove(uri)
|
||||
@repositories.reject!{|repo| repo.uri == uri}
|
||||
end
|
||||
|
||||
def exist?(uri)
|
||||
@repositories.detect{|repo| repo.uri == uri }
|
||||
end
|
||||
|
||||
def all
|
||||
@repositories
|
||||
end
|
||||
|
||||
def find_plugin(name)
|
||||
@repositories.each do |repo|
|
||||
repo.each do |plugin|
|
||||
return plugin if plugin.name == name
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def load!
|
||||
contents = File.exist?(@cache_file) ? File.read(@cache_file) : defaults
|
||||
contents = defaults if contents.empty?
|
||||
@repositories = contents.split(/\n/).reject do |line|
|
||||
line =~ /^\s*#/ or line =~ /^\s*$/
|
||||
end.map { |source| Repository.new(source.strip) }
|
||||
end
|
||||
|
||||
def save
|
||||
File.open(@cache_file, 'w') do |f|
|
||||
each do |repo|
|
||||
f.write(repo.uri)
|
||||
f.write("\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def defaults
|
||||
<<-DEFAULTS
|
||||
http://dev.rubyonrails.com/svn/rails/plugins/
|
||||
DEFAULTS
|
||||
end
|
||||
|
||||
def find_home
|
||||
['HOME', 'USERPROFILE'].each do |homekey|
|
||||
return ENV[homekey] if ENV[homekey]
|
||||
end
|
||||
if ENV['HOMEDRIVE'] && ENV['HOMEPATH']
|
||||
return "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}"
|
||||
end
|
||||
begin
|
||||
File.expand_path("~")
|
||||
rescue StandardError => ex
|
||||
if File::ALT_SEPARATOR
|
||||
"C:/"
|
||||
else
|
||||
"/"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.instance
|
||||
@instance ||= Repositories.new
|
||||
end
|
||||
|
||||
def self.each(&block)
|
||||
self.instance.each(&block)
|
||||
end
|
||||
end
|
||||
|
||||
class Repository
|
||||
include Enumerable
|
||||
attr_reader :uri, :plugins
|
||||
|
||||
def initialize(uri)
|
||||
@uri = uri.chomp('/') << "/"
|
||||
@plugins = nil
|
||||
end
|
||||
|
||||
def plugins
|
||||
unless @plugins
|
||||
if $verbose
|
||||
puts "Discovering plugins in #{@uri}"
|
||||
puts index
|
||||
end
|
||||
|
||||
@plugins = index.reject{ |line| line !~ /\/$/ }
|
||||
@plugins.map! { |name| Plugin.new(File.join(@uri, name), name) }
|
||||
end
|
||||
|
||||
@plugins
|
||||
end
|
||||
|
||||
def each(&block)
|
||||
plugins.each(&block)
|
||||
end
|
||||
|
||||
private
|
||||
def index
|
||||
@index ||= RecursiveHTTPFetcher.new(@uri).ls
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# load default environment and parse arguments
|
||||
require 'optparse'
|
||||
module Commands
|
||||
|
||||
class Plugin
|
||||
attr_reader :environment, :script_name, :sources
|
||||
def initialize
|
||||
@environment = RailsEnvironment.default
|
||||
@rails_root = RailsEnvironment.default.root
|
||||
@script_name = File.basename($0)
|
||||
@sources = []
|
||||
end
|
||||
|
||||
def environment=(value)
|
||||
@environment = value
|
||||
RailsEnvironment.default = value
|
||||
end
|
||||
|
||||
def options
|
||||
OptionParser.new do |o|
|
||||
o.set_summary_indent(' ')
|
||||
o.banner = "Usage: #{@script_name} [OPTIONS] command"
|
||||
o.define_head "Rails plugin manager."
|
||||
|
||||
o.separator ""
|
||||
o.separator "GENERAL OPTIONS"
|
||||
|
||||
o.on("-r", "--root=DIR", String,
|
||||
"Set an explicit rails app directory.",
|
||||
"Default: #{@rails_root}") { |@rails_root| self.environment = RailsEnvironment.new(@rails_root) }
|
||||
o.on("-s", "--source=URL1,URL2", Array,
|
||||
"Use the specified plugin repositories instead of the defaults.") { |@sources|}
|
||||
|
||||
o.on("-v", "--verbose", "Turn on verbose output.") { |$verbose| }
|
||||
o.on("-h", "--help", "Show this help message.") { puts o; exit }
|
||||
|
||||
o.separator ""
|
||||
o.separator "COMMANDS"
|
||||
|
||||
o.separator " discover Discover plugin repositories."
|
||||
o.separator " list List available plugins."
|
||||
o.separator " install Install plugin(s) from known repositories or URLs."
|
||||
o.separator " update Update installed plugins."
|
||||
o.separator " remove Uninstall plugins."
|
||||
o.separator " source Add a plugin source repository."
|
||||
o.separator " unsource Remove a plugin repository."
|
||||
o.separator " sources List currently configured plugin repositories."
|
||||
|
||||
o.separator ""
|
||||
o.separator "EXAMPLES"
|
||||
o.separator " Install a plugin:"
|
||||
o.separator " #{@script_name} install continuous_builder\n"
|
||||
o.separator " Install a plugin from a subversion URL:"
|
||||
o.separator " #{@script_name} install http://dev.rubyonrails.com/svn/rails/plugins/continuous_builder\n"
|
||||
o.separator " Install a plugin and add a svn:externals entry to vendor/plugins"
|
||||
o.separator " #{@script_name} install -x continuous_builder\n"
|
||||
o.separator " List all available plugins:"
|
||||
o.separator " #{@script_name} list\n"
|
||||
o.separator " List plugins in the specified repository:"
|
||||
o.separator " #{@script_name} list --source=http://dev.rubyonrails.com/svn/rails/plugins/\n"
|
||||
o.separator " Discover and prompt to add new repositories:"
|
||||
o.separator " #{@script_name} discover\n"
|
||||
o.separator " Discover new repositories but just list them, don't add anything:"
|
||||
o.separator " #{@script_name} discover -l\n"
|
||||
o.separator " Add a new repository to the source list:"
|
||||
o.separator " #{@script_name} source http://dev.rubyonrails.com/svn/rails/plugins/\n"
|
||||
o.separator " Remove a repository from the source list:"
|
||||
o.separator " #{@script_name} unsource http://dev.rubyonrails.com/svn/rails/plugins/\n"
|
||||
o.separator " Show currently configured repositories:"
|
||||
o.separator " #{@script_name} sources\n"
|
||||
end
|
||||
end
|
||||
|
||||
def parse!(args=ARGV)
|
||||
general, sub = split_args(args)
|
||||
options.parse!(general)
|
||||
|
||||
command = general.shift
|
||||
if command =~ /^(list|discover|install|source|unsource|sources|remove|update)$/
|
||||
command = Commands.const_get(command.capitalize).new(self)
|
||||
command.parse!(sub)
|
||||
else
|
||||
puts "Unknown command: #{command}"
|
||||
puts options
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
def split_args(args)
|
||||
left = []
|
||||
left << args.shift while args[0] and args[0] =~ /^-/
|
||||
left << args.shift if args[0]
|
||||
return [left, args]
|
||||
end
|
||||
|
||||
def self.parse!(args=ARGV)
|
||||
Plugin.new.parse!(args)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class List
|
||||
def initialize(base_command)
|
||||
@base_command = base_command
|
||||
@sources = []
|
||||
@local = false
|
||||
@remote = true
|
||||
end
|
||||
|
||||
def options
|
||||
OptionParser.new do |o|
|
||||
o.set_summary_indent(' ')
|
||||
o.banner = "Usage: #{@base_command.script_name} list [OPTIONS] [PATTERN]"
|
||||
o.define_head "List available plugins."
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
o.on( "-s", "--source=URL1,URL2", Array,
|
||||
"Use the specified plugin repositories.") {|@sources|}
|
||||
o.on( "--local",
|
||||
"List locally installed plugins.") {|@local| @remote = false}
|
||||
o.on( "--remote",
|
||||
"List remotely availabled plugins. This is the default behavior",
|
||||
"unless --local is provided.") {|@remote|}
|
||||
end
|
||||
end
|
||||
|
||||
def parse!(args)
|
||||
options.order!(args)
|
||||
unless @sources.empty?
|
||||
@sources.map!{ |uri| Repository.new(uri) }
|
||||
else
|
||||
@sources = Repositories.instance.all
|
||||
end
|
||||
if @remote
|
||||
@sources.map{|r| r.plugins}.flatten.each do |plugin|
|
||||
if @local or !plugin.installed?
|
||||
puts plugin.to_s
|
||||
end
|
||||
end
|
||||
else
|
||||
cd "#{@base_command.environment.root}/vendor/plugins"
|
||||
Dir["*"].select{|p| File.directory?(p)}.each do |name|
|
||||
puts name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class Sources
|
||||
def initialize(base_command)
|
||||
@base_command = base_command
|
||||
end
|
||||
|
||||
def options
|
||||
OptionParser.new do |o|
|
||||
o.set_summary_indent(' ')
|
||||
o.banner = "Usage: #{@base_command.script_name} sources [OPTIONS] [PATTERN]"
|
||||
o.define_head "List configured plugin repositories."
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
o.on( "-c", "--check",
|
||||
"Report status of repository.") { |@sources|}
|
||||
end
|
||||
end
|
||||
|
||||
def parse!(args)
|
||||
options.parse!(args)
|
||||
Repositories.each do |repo|
|
||||
puts repo.uri
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class Source
|
||||
def initialize(base_command)
|
||||
@base_command = base_command
|
||||
end
|
||||
|
||||
def options
|
||||
OptionParser.new do |o|
|
||||
o.set_summary_indent(' ')
|
||||
o.banner = "Usage: #{@base_command.script_name} source REPOSITORY"
|
||||
o.define_head "Add a new repository."
|
||||
end
|
||||
end
|
||||
|
||||
def parse!(args)
|
||||
options.parse!(args)
|
||||
count = 0
|
||||
args.each do |uri|
|
||||
if Repositories.instance.add(uri)
|
||||
puts "added: #{uri.ljust(50)}" if $verbose
|
||||
count += 1
|
||||
else
|
||||
puts "failed: #{uri.ljust(50)}"
|
||||
end
|
||||
end
|
||||
Repositories.instance.save
|
||||
puts "Added #{count} repositories."
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class Unsource
|
||||
def initialize(base_command)
|
||||
@base_command = base_command
|
||||
end
|
||||
|
||||
def options
|
||||
OptionParser.new do |o|
|
||||
o.set_summary_indent(' ')
|
||||
o.banner = "Usage: #{@base_command.script_name} source URI [URI [URI]...]"
|
||||
o.define_head "Remove repositories from the default search list."
|
||||
o.separator ""
|
||||
o.on_tail("-h", "--help", "Show this help message.") { puts o; exit }
|
||||
end
|
||||
end
|
||||
|
||||
def parse!(args)
|
||||
options.parse!(args)
|
||||
count = 0
|
||||
args.each do |uri|
|
||||
if Repositories.instance.remove(uri)
|
||||
count += 1
|
||||
puts "removed: #{uri.ljust(50)}"
|
||||
else
|
||||
puts "failed: #{uri.ljust(50)}"
|
||||
end
|
||||
end
|
||||
Repositories.instance.save
|
||||
puts "Removed #{count} repositories."
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class Discover
|
||||
def initialize(base_command)
|
||||
@base_command = base_command
|
||||
@list = false
|
||||
@prompt = true
|
||||
end
|
||||
|
||||
def options
|
||||
OptionParser.new do |o|
|
||||
o.set_summary_indent(' ')
|
||||
o.banner = "Usage: #{@base_command.script_name} discover URI [URI [URI]...]"
|
||||
o.define_head "Discover repositories referenced on a page."
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
o.on( "-l", "--list",
|
||||
"List but don't prompt or add discovered repositories.") { |@list| @prompt = !@list }
|
||||
o.on( "-n", "--no-prompt",
|
||||
"Add all new repositories without prompting.") { |v| @prompt = !v }
|
||||
end
|
||||
end
|
||||
|
||||
def parse!(args)
|
||||
options.parse!(args)
|
||||
args = ['http://wiki.rubyonrails.org/rails/pages/Plugins'] if args.empty?
|
||||
args.each do |uri|
|
||||
scrape(uri) do |repo_uri|
|
||||
catch(:next_uri) do
|
||||
if @prompt
|
||||
begin
|
||||
$stdout.print "Add #{repo_uri}? [Y/n] "
|
||||
throw :next_uri if $stdin.gets !~ /^y?$/i
|
||||
rescue Interrupt
|
||||
$stdout.puts
|
||||
exit 1
|
||||
end
|
||||
elsif @list
|
||||
puts repo_uri
|
||||
throw :next_uri
|
||||
end
|
||||
Repositories.instance.add(repo_uri)
|
||||
puts "discovered: #{repo_uri}" if $verbose or !@prompt
|
||||
end
|
||||
end
|
||||
end
|
||||
Repositories.instance.save
|
||||
end
|
||||
|
||||
def scrape(uri)
|
||||
require 'open-uri'
|
||||
puts "Scraping #{uri}" if $verbose
|
||||
dupes = []
|
||||
content = open(uri).each do |line|
|
||||
if line =~ /<a[^>]*href=['"]([^'"]*)['"]/ or line =~ /(svn:\/\/[^<|\n]*)/
|
||||
uri = $1
|
||||
if uri =~ /\/plugins\// and uri !~ /\/browser\//
|
||||
uri = extract_repository_uri(uri)
|
||||
yield uri unless dupes.include?(uri) or Repositories.instance.exist?(uri)
|
||||
dupes << uri
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def extract_repository_uri(uri)
|
||||
uri.match(/(svn|https?):.*\/plugins\//i)[0]
|
||||
end
|
||||
end
|
||||
|
||||
class Install
|
||||
def initialize(base_command)
|
||||
@base_command = base_command
|
||||
@method = :http
|
||||
@options = { :quiet => false, :revision => nil, :force => false }
|
||||
end
|
||||
|
||||
def options
|
||||
OptionParser.new do |o|
|
||||
o.set_summary_indent(' ')
|
||||
o.banner = "Usage: #{@base_command.script_name} install PLUGIN [PLUGIN [PLUGIN] ...]"
|
||||
o.define_head "Install one or more plugins."
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.on( "-x", "--externals",
|
||||
"Use svn:externals to grab the plugin.",
|
||||
"Enables plugin updates and plugin versioning.") { |v| @method = :externals }
|
||||
o.on( "-o", "--checkout",
|
||||
"Use svn checkout to grab the plugin.",
|
||||
"Enables updating but does not add a svn:externals entry.") { |v| @method = :checkout }
|
||||
o.on( "-q", "--quiet",
|
||||
"Suppresses the output from installation.",
|
||||
"Ignored if -v is passed (./script/plugin -v install ...)") { |v| @options[:quiet] = true }
|
||||
o.on( "-r REVISION", "--revision REVISION",
|
||||
"Checks out the given revision from subversion.",
|
||||
"Ignored if subversion is not used.") { |v| @options[:revision] = v }
|
||||
o.on( "-f", "--force",
|
||||
"Reinstalls a plugin if it's already installed.") { |v| @options[:force] = true }
|
||||
o.separator ""
|
||||
o.separator "You can specify plugin names as given in 'plugin list' output or absolute URLs to "
|
||||
o.separator "a plugin repository."
|
||||
end
|
||||
end
|
||||
|
||||
def determine_install_method
|
||||
best = @base_command.environment.best_install_method
|
||||
@method = :http if best == :http and @method == :export
|
||||
case
|
||||
when (best == :http and @method != :http)
|
||||
msg = "Cannot install using subversion because `svn' cannot be found in your PATH"
|
||||
when (best == :export and (@method != :export and @method != :http))
|
||||
msg = "Cannot install using #{@method} because this project is not under subversion."
|
||||
when (best != :externals and @method == :externals)
|
||||
msg = "Cannot install using externals because vendor/plugins is not under subversion."
|
||||
end
|
||||
if msg
|
||||
puts msg
|
||||
exit 1
|
||||
end
|
||||
@method
|
||||
end
|
||||
|
||||
def parse!(args)
|
||||
options.parse!(args)
|
||||
environment = @base_command.environment
|
||||
install_method = determine_install_method
|
||||
puts "Plugins will be installed using #{install_method}" if $verbose
|
||||
args.each do |name|
|
||||
if name =~ /\// then
|
||||
::Plugin.new(name).install(install_method, @options)
|
||||
else
|
||||
plugin = Repositories.instance.find_plugin(name)
|
||||
unless plugin.nil?
|
||||
plugin.install(install_method, @options)
|
||||
else
|
||||
puts "Plugin not found: #{name}"
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Update
|
||||
def initialize(base_command)
|
||||
@base_command = base_command
|
||||
end
|
||||
|
||||
def options
|
||||
OptionParser.new do |o|
|
||||
o.set_summary_indent(' ')
|
||||
o.banner = "Usage: #{@base_command.script_name} update [name [name]...]"
|
||||
o.on( "-r REVISION", "--revision REVISION",
|
||||
"Checks out the given revision from subversion.",
|
||||
"Ignored if subversion is not used.") { |v| @revision = v }
|
||||
o.define_head "Update plugins."
|
||||
end
|
||||
end
|
||||
|
||||
def parse!(args)
|
||||
options.parse!(args)
|
||||
root = @base_command.environment.root
|
||||
cd root
|
||||
args = Dir["vendor/plugins/*"].map do |f|
|
||||
File.directory?("#{f}/.svn") ? File.basename(f) : nil
|
||||
end.compact if args.empty?
|
||||
cd "vendor/plugins"
|
||||
args.each do |name|
|
||||
if File.directory?(name)
|
||||
puts "Updating plugin: #{name}"
|
||||
system("svn #{$verbose ? '' : '-q'} up \"#{name}\" #{@revision ? "-r #{@revision}" : ''}")
|
||||
else
|
||||
puts "Plugin doesn't exist: #{name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Remove
|
||||
def initialize(base_command)
|
||||
@base_command = base_command
|
||||
end
|
||||
|
||||
def options
|
||||
OptionParser.new do |o|
|
||||
o.set_summary_indent(' ')
|
||||
o.banner = "Usage: #{@base_command.script_name} remove name [name]..."
|
||||
o.define_head "Remove plugins."
|
||||
end
|
||||
end
|
||||
|
||||
def parse!(args)
|
||||
options.parse!(args)
|
||||
root = @base_command.environment.root
|
||||
args.each do |name|
|
||||
::Plugin.new(name).uninstall
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class RecursiveHTTPFetcher
|
||||
attr_accessor :quiet
|
||||
def initialize(urls_to_fetch, cwd = ".")
|
||||
@cwd = cwd
|
||||
@urls_to_fetch = urls_to_fetch.to_a
|
||||
@quiet = false
|
||||
end
|
||||
|
||||
def ls
|
||||
@urls_to_fetch.collect do |url|
|
||||
if url =~ /^svn:\/\/.*/
|
||||
`svn ls #{url}`.split("\n").map {|entry| "/#{entry}"} rescue nil
|
||||
else
|
||||
open(url) do |stream|
|
||||
links("", stream.read)
|
||||
end rescue nil
|
||||
end
|
||||
end.flatten
|
||||
end
|
||||
|
||||
def push_d(dir)
|
||||
@cwd = File.join(@cwd, dir)
|
||||
FileUtils.mkdir_p(@cwd)
|
||||
end
|
||||
|
||||
def pop_d
|
||||
@cwd = File.dirname(@cwd)
|
||||
end
|
||||
|
||||
def links(base_url, contents)
|
||||
links = []
|
||||
contents.scan(/href\s*=\s*\"*[^\">]*/i) do |link|
|
||||
link = link.sub(/href="/i, "")
|
||||
next if link =~ /^http/i || link =~ /^\./
|
||||
links << File.join(base_url, link)
|
||||
end
|
||||
links
|
||||
end
|
||||
|
||||
def download(link)
|
||||
puts "+ #{File.join(@cwd, File.basename(link))}" unless @quiet
|
||||
open(link) do |stream|
|
||||
File.open(File.join(@cwd, File.basename(link)), "wb") do |file|
|
||||
file.write(stream.read)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def fetch(links = @urls_to_fetch)
|
||||
links.each do |l|
|
||||
(l =~ /\/$/ || links == @urls_to_fetch) ? fetch_dir(l) : download(l)
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_dir(url)
|
||||
push_d(File.basename(url))
|
||||
open(url) do |stream|
|
||||
contents = stream.read
|
||||
fetch(links(url, contents))
|
||||
end
|
||||
pop_d
|
||||
end
|
||||
end
|
||||
|
||||
Commands::Plugin.parse!
|
130
vendor/rails/railties/lib/commands/process/reaper.rb
vendored
Normal file
130
vendor/rails/railties/lib/commands/process/reaper.rb
vendored
Normal file
|
@ -0,0 +1,130 @@
|
|||
require 'optparse'
|
||||
require 'net/http'
|
||||
require 'uri'
|
||||
|
||||
if RUBY_PLATFORM =~ /mswin32/ then abort("Reaper is only for Unix") end
|
||||
|
||||
# Instances of this class represent a single running process. Processes may
|
||||
# be queried by "keyword" to find those that meet a specific set of criteria.
|
||||
class ProgramProcess
|
||||
class << self
|
||||
|
||||
# Searches for all processes matching the given keywords, and then invokes
|
||||
# a specific action on each of them. This is useful for (e.g.) reloading a
|
||||
# set of processes:
|
||||
#
|
||||
# ProgramProcess.process_keywords(:reload, "basecamp")
|
||||
def process_keywords(action, *keywords)
|
||||
processes = keywords.collect { |keyword| find_by_keyword(keyword) }.flatten
|
||||
|
||||
if processes.empty?
|
||||
puts "Couldn't find any process matching: #{keywords.join(" or ")}"
|
||||
else
|
||||
processes.each do |process|
|
||||
puts "#{action.capitalize}ing #{process}"
|
||||
process.send(action)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Searches for all processes matching the given keyword:
|
||||
#
|
||||
# ProgramProcess.find_by_keyword("basecamp")
|
||||
def find_by_keyword(keyword)
|
||||
process_lines_with_keyword(keyword).split("\n").collect { |line|
|
||||
next if line =~ /inq|ps axww|grep|spawn-fcgi|spawner|reaper/
|
||||
pid, *command = line.split
|
||||
new(pid, command.join(" "))
|
||||
}.compact
|
||||
end
|
||||
|
||||
private
|
||||
def process_lines_with_keyword(keyword)
|
||||
`ps axww -o 'pid command' | grep #{keyword}`
|
||||
end
|
||||
end
|
||||
|
||||
# Create a new ProgramProcess instance that represents the process with the
|
||||
# given pid, running the given command.
|
||||
def initialize(pid, command)
|
||||
@pid, @command = pid, command
|
||||
end
|
||||
|
||||
# Forces the (rails) application to reload by sending a +HUP+ signal to the
|
||||
# process.
|
||||
def reload
|
||||
`kill -s HUP #{@pid}`
|
||||
end
|
||||
|
||||
# Forces the (rails) application to gracefully terminate by sending a
|
||||
# +TERM+ signal to the process.
|
||||
def graceful
|
||||
`kill -s TERM #{@pid}`
|
||||
end
|
||||
|
||||
# Forces the (rails) application to terminate immediately by sending a -9
|
||||
# signal to the process.
|
||||
def kill
|
||||
`kill -9 #{@pid}`
|
||||
end
|
||||
|
||||
# Send a +USR1+ signal to the process.
|
||||
def usr1
|
||||
`kill -s USR1 #{@pid}`
|
||||
end
|
||||
|
||||
# Force the (rails) application to restart by sending a +USR2+ signal to the
|
||||
# process.
|
||||
def restart
|
||||
`kill -s USR2 #{@pid}`
|
||||
end
|
||||
|
||||
def to_s #:nodoc:
|
||||
"[#{@pid}] #{@command}"
|
||||
end
|
||||
end
|
||||
|
||||
OPTIONS = {
|
||||
:action => "restart",
|
||||
:dispatcher => File.expand_path(RAILS_ROOT + '/public/dispatch.fcgi')
|
||||
}
|
||||
|
||||
ARGV.options do |opts|
|
||||
opts.banner = "Usage: reaper [options]"
|
||||
|
||||
opts.separator ""
|
||||
|
||||
opts.on <<-EOF
|
||||
Description:
|
||||
The reaper is used to restart, reload, gracefully exit, and forcefully exit FCGI processes
|
||||
running a Rails Dispatcher. This is commonly done when a new version of the application
|
||||
is available, so the existing processes can be updated to use the latest code.
|
||||
|
||||
The reaper actions are:
|
||||
|
||||
* restart : Restarts the application by reloading both application and framework code
|
||||
* reload : Only reloads the application, but not the framework (like the development environment)
|
||||
* graceful: Marks all of the processes for exit after the next request
|
||||
* kill : Forcefully exists all processes regardless of whether they're currently serving a request
|
||||
|
||||
Restart is the most common and default action.
|
||||
|
||||
Examples:
|
||||
reaper # restarts the default dispatcher
|
||||
reaper -a reload
|
||||
reaper -a exit -d /my/special/dispatcher.fcgi
|
||||
EOF
|
||||
|
||||
opts.on(" Options:")
|
||||
|
||||
opts.on("-a", "--action=name", "reload|graceful|kill (default: #{OPTIONS[:action]})", String) { |v| OPTIONS[:action] = v }
|
||||
opts.on("-d", "--dispatcher=path", "default: #{OPTIONS[:dispatcher]}", String) { |v| OPTIONS[:dispatcher] = v }
|
||||
|
||||
opts.separator ""
|
||||
|
||||
opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
|
||||
|
||||
opts.parse!
|
||||
end
|
||||
|
||||
ProgramProcess.process_keywords(OPTIONS[:action], OPTIONS[:dispatcher])
|
94
vendor/rails/railties/lib/commands/process/spawner.rb
vendored
Normal file
94
vendor/rails/railties/lib/commands/process/spawner.rb
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
require 'optparse'
|
||||
require 'socket'
|
||||
|
||||
def daemonize #:nodoc:
|
||||
exit if fork # Parent exits, child continues.
|
||||
Process.setsid # Become session leader.
|
||||
exit if fork # Zap session leader. See [1].
|
||||
Dir.chdir "/" # Release old working directory.
|
||||
File.umask 0000 # Ensure sensible umask. Adjust as needed.
|
||||
STDIN.reopen "/dev/null" # Free file descriptors and
|
||||
STDOUT.reopen "/dev/null", "a" # point them somewhere sensible.
|
||||
STDERR.reopen STDOUT # STDOUT/ERR should better go to a logfile.
|
||||
end
|
||||
|
||||
def spawn(port)
|
||||
print "Checking if something is already running on port #{port}..."
|
||||
begin
|
||||
srv = TCPServer.new('0.0.0.0', port)
|
||||
srv.close
|
||||
srv = nil
|
||||
print "NO\n "
|
||||
print "Starting FCGI on port: #{port}\n "
|
||||
system("#{OPTIONS[:spawner]} -f #{OPTIONS[:dispatcher]} -p #{port}")
|
||||
rescue
|
||||
print "YES\n"
|
||||
end
|
||||
end
|
||||
|
||||
def spawn_all
|
||||
OPTIONS[:instances].times { |i| spawn(OPTIONS[:port] + i) }
|
||||
end
|
||||
|
||||
OPTIONS = {
|
||||
:environment => "production",
|
||||
:spawner => '/usr/bin/env spawn-fcgi',
|
||||
:dispatcher => File.expand_path(RAILS_ROOT + '/public/dispatch.fcgi'),
|
||||
:port => 8000,
|
||||
:instances => 3,
|
||||
:repeat => nil
|
||||
}
|
||||
|
||||
ARGV.options do |opts|
|
||||
opts.banner = "Usage: spawner [options]"
|
||||
|
||||
opts.separator ""
|
||||
|
||||
opts.on <<-EOF
|
||||
Description:
|
||||
The spawner is a wrapper for spawn-fcgi that makes it easier to start multiple FCGI
|
||||
processes running the Rails dispatcher. The spawn-fcgi command is included with the lighttpd
|
||||
web server, but can be used with both Apache and lighttpd (and any other web server supporting
|
||||
externally managed FCGI processes).
|
||||
|
||||
You decide a starting port (default is 8000) and the number of FCGI process instances you'd
|
||||
like to run. So if you pick 9100 and 3 instances, you'll start processes on 9100, 9101, and 9102.
|
||||
|
||||
By setting the repeat option, you get a protection loop, which will attempt to restart any FCGI processes
|
||||
that might have been exited or outright crashed.
|
||||
|
||||
Examples:
|
||||
spawner # starts instances on 8000, 8001, and 8002
|
||||
spawner -p 9100 -i 10 # starts 10 instances counting from 9100 to 9109
|
||||
spawner -p 9100 -r 5 # starts 3 instances counting from 9100 to 9102 and attempts start them every 5 seconds
|
||||
EOF
|
||||
|
||||
opts.on(" Options:")
|
||||
|
||||
opts.on("-p", "--port=number", Integer, "Starting port number (default: #{OPTIONS[:port]})") { |v| OPTIONS[:port] = v }
|
||||
opts.on("-i", "--instances=number", Integer, "Number of instances (default: #{OPTIONS[:instances]})") { |v| OPTIONS[:instances] = v }
|
||||
opts.on("-r", "--repeat=seconds", Integer, "Repeat spawn attempts every n seconds (default: off)") { |v| OPTIONS[:repeat] = v }
|
||||
opts.on("-e", "--environment=name", String, "test|development|production (default: #{OPTIONS[:environment]})") { |v| OPTIONS[:environment] = v }
|
||||
opts.on("-s", "--spawner=path", String, "default: #{OPTIONS[:spawner]}") { |v| OPTIONS[:spawner] = v }
|
||||
opts.on("-d", "--dispatcher=path", String, "default: #{OPTIONS[:dispatcher]}") { |dispatcher| OPTIONS[:dispatcher] = File.expand_path(dispatcher) }
|
||||
|
||||
opts.separator ""
|
||||
|
||||
opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
|
||||
|
||||
opts.parse!
|
||||
end
|
||||
|
||||
ENV["RAILS_ENV"] = OPTIONS[:environment]
|
||||
|
||||
if OPTIONS[:repeat]
|
||||
daemonize
|
||||
trap("TERM") { exit }
|
||||
|
||||
loop do
|
||||
spawn_all
|
||||
sleep(OPTIONS[:repeat])
|
||||
end
|
||||
else
|
||||
spawn_all
|
||||
end
|
57
vendor/rails/railties/lib/commands/process/spinner.rb
vendored
Normal file
57
vendor/rails/railties/lib/commands/process/spinner.rb
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
require 'optparse'
|
||||
|
||||
def daemonize #:nodoc:
|
||||
exit if fork # Parent exits, child continues.
|
||||
Process.setsid # Become session leader.
|
||||
exit if fork # Zap session leader. See [1].
|
||||
Dir.chdir "/" # Release old working directory.
|
||||
File.umask 0000 # Ensure sensible umask. Adjust as needed.
|
||||
STDIN.reopen "/dev/null" # Free file descriptors and
|
||||
STDOUT.reopen "/dev/null", "a" # point them somewhere sensible.
|
||||
STDERR.reopen STDOUT # STDOUT/ERR should better go to a logfile.
|
||||
end
|
||||
|
||||
OPTIONS = {
|
||||
:interval => 5.0,
|
||||
:command => File.expand_path(RAILS_ROOT + '/script/process/spawner'),
|
||||
:daemon => false
|
||||
}
|
||||
|
||||
ARGV.options do |opts|
|
||||
opts.banner = "Usage: spinner [options]"
|
||||
|
||||
opts.separator ""
|
||||
|
||||
opts.on <<-EOF
|
||||
Description:
|
||||
The spinner is a protection loop for the spawner, which will attempt to restart any FCGI processes
|
||||
that might have been exited or outright crashed. It's a brute-force attempt that'll just try
|
||||
to run the spawner every X number of seconds, so it does pose a light load on the server.
|
||||
|
||||
Examples:
|
||||
spinner # attempts to run the spawner with default settings every second with output on the terminal
|
||||
spinner -i 3 -d # only run the spawner every 3 seconds and detach from the terminal to become a daemon
|
||||
spinner -c '/path/to/app/script/process/spawner -p 9000 -i 10' -d # using custom spawner
|
||||
EOF
|
||||
|
||||
opts.on(" Options:")
|
||||
|
||||
opts.on("-c", "--command=path", String) { |v| OPTIONS[:command] = v }
|
||||
opts.on("-i", "--interval=seconds", Float) { |v| OPTIONS[:interval] = v }
|
||||
opts.on("-d", "--daemon") { |v| OPTIONS[:daemon] = v }
|
||||
|
||||
opts.separator ""
|
||||
|
||||
opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
|
||||
|
||||
opts.parse!
|
||||
end
|
||||
|
||||
daemonize if OPTIONS[:daemon]
|
||||
|
||||
trap(OPTIONS[:daemon] ? "TERM" : "INT") { exit }
|
||||
|
||||
loop do
|
||||
system(OPTIONS[:command])
|
||||
sleep(OPTIONS[:interval])
|
||||
end
|
27
vendor/rails/railties/lib/commands/runner.rb
vendored
Normal file
27
vendor/rails/railties/lib/commands/runner.rb
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
require 'optparse'
|
||||
|
||||
options = { :environment => (ENV['RAILS_ENV'] || "development").dup }
|
||||
|
||||
ARGV.options do |opts|
|
||||
script_name = File.basename($0)
|
||||
opts.banner = "Usage: runner 'puts Person.find(1).name' [options]"
|
||||
|
||||
opts.separator ""
|
||||
|
||||
opts.on("-e", "--environment=name", String,
|
||||
"Specifies the environment for the runner to operate under (test/development/production).",
|
||||
"Default: development") { |v| options[:environment] = v }
|
||||
|
||||
opts.separator ""
|
||||
|
||||
opts.on("-h", "--help",
|
||||
"Show this help message.") { puts opts; exit }
|
||||
|
||||
opts.parse!
|
||||
end
|
||||
|
||||
ENV["RAILS_ENV"] = options[:environment]
|
||||
RAILS_ENV.replace(options[:environment]) if defined?(RAILS_ENV)
|
||||
|
||||
require RAILS_ROOT + '/config/environment'
|
||||
ARGV.empty? ? puts("Usage: runner 'code' [options]") : eval(ARGV.first)
|
30
vendor/rails/railties/lib/commands/server.rb
vendored
Normal file
30
vendor/rails/railties/lib/commands/server.rb
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
require 'active_support'
|
||||
require 'fileutils'
|
||||
|
||||
begin
|
||||
require_library_or_gem 'fcgi'
|
||||
rescue Exception
|
||||
# FCGI not available
|
||||
end
|
||||
|
||||
server = case ARGV.first
|
||||
when "lighttpd"
|
||||
ARGV.shift
|
||||
when "webrick"
|
||||
ARGV.shift
|
||||
else
|
||||
if RUBY_PLATFORM !~ /mswin/ && !silence_stderr { `lighttpd -version` }.blank? && defined?(FCGI)
|
||||
"lighttpd"
|
||||
else
|
||||
"webrick"
|
||||
end
|
||||
end
|
||||
|
||||
if server == "webrick"
|
||||
puts "=> Booting WEBrick..."
|
||||
else
|
||||
puts "=> Booting lighttpd (use 'script/server webrick' to force WEBrick)"
|
||||
end
|
||||
|
||||
FileUtils.mkdir_p(%w( tmp/sessions tmp/cache tmp/sockets ))
|
||||
require "commands/servers/#{server}"
|
92
vendor/rails/railties/lib/commands/servers/lighttpd.rb
vendored
Normal file
92
vendor/rails/railties/lib/commands/servers/lighttpd.rb
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
require 'rbconfig'
|
||||
|
||||
unless RUBY_PLATFORM !~ /mswin/ && !silence_stderr { `lighttpd -version` }.blank?
|
||||
puts "PROBLEM: Lighttpd is not available on your system (or not in your path)"
|
||||
exit 1
|
||||
end
|
||||
|
||||
unless defined?(FCGI)
|
||||
puts "PROBLEM: Lighttpd requires that the FCGI Ruby bindings are installed on the system"
|
||||
exit 1
|
||||
end
|
||||
|
||||
require 'initializer'
|
||||
configuration = Rails::Initializer.run(:initialize_logger).configuration
|
||||
default_config_file = config_file = Pathname.new("#{RAILS_ROOT}/config/lighttpd.conf").cleanpath
|
||||
|
||||
require 'optparse'
|
||||
|
||||
detach = false
|
||||
|
||||
ARGV.options do |opt|
|
||||
opt.on('-c', "--config=#{config_file}", 'Specify a different lighttpd config file.') { |path| config_file = path }
|
||||
opt.on('-h', '--help', 'Show this message.') { puts opt; exit 0 }
|
||||
opt.on('-d', '-d', 'Call with -d to detach') { detach = true; puts "=> Configuration in config/lighttpd.conf" }
|
||||
opt.parse!
|
||||
end
|
||||
|
||||
unless File.exist?(config_file)
|
||||
if config_file != default_config_file
|
||||
puts "=> #{config_file} not found."
|
||||
exit 1
|
||||
end
|
||||
|
||||
require 'fileutils'
|
||||
|
||||
source = File.expand_path(File.join(File.dirname(__FILE__),
|
||||
"..", "..", "..", "configs", "lighttpd.conf"))
|
||||
puts "=> #{config_file} not found, copying from #{source}"
|
||||
|
||||
FileUtils.cp(source, config_file)
|
||||
end
|
||||
|
||||
config = IO.read(config_file)
|
||||
default_port, default_ip = 3000, '0.0.0.0'
|
||||
port = config.scan(/^\s*server.port\s*=\s*(\d+)/).first rescue default_port
|
||||
ip = config.scan(/^\s*server.bind\s*=\s*"([^"]+)"/).first rescue default_ip
|
||||
puts "=> Rails application started on http://#{ip || default_ip}:#{port || default_port}"
|
||||
|
||||
tail_thread = nil
|
||||
|
||||
if !detach
|
||||
puts "=> Call with -d to detach"
|
||||
puts "=> Ctrl-C to shutdown server (see config/lighttpd.conf for options)"
|
||||
detach = false
|
||||
|
||||
cursor = File.size(configuration.log_path)
|
||||
last_checked = Time.now
|
||||
tail_thread = Thread.new do
|
||||
File.open(configuration.log_path, 'r') do |f|
|
||||
loop do
|
||||
f.seek cursor
|
||||
if f.mtime > last_checked
|
||||
last_checked = f.mtime
|
||||
contents = f.read
|
||||
cursor += contents.length
|
||||
print contents
|
||||
end
|
||||
sleep 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
trap(:INT) { exit }
|
||||
|
||||
begin
|
||||
`rake tmp:sockets:clear` # Needed if lighttpd crashes or otherwise leaves FCGI sockets around
|
||||
`lighttpd #{!detach ? "-D " : ""}-f #{config_file}`
|
||||
ensure
|
||||
unless detach
|
||||
tail_thread.kill if tail_thread
|
||||
puts 'Exiting'
|
||||
|
||||
# Ensure FCGI processes are reaped
|
||||
silence_stream(STDOUT) do
|
||||
ARGV.replace ['-a', 'kill']
|
||||
require 'commands/process/reaper'
|
||||
end
|
||||
|
||||
`rake tmp:sockets:clear` # Remove sockets on clean shutdown
|
||||
end
|
||||
end
|
59
vendor/rails/railties/lib/commands/servers/webrick.rb
vendored
Normal file
59
vendor/rails/railties/lib/commands/servers/webrick.rb
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
require 'webrick'
|
||||
require 'optparse'
|
||||
|
||||
OPTIONS = {
|
||||
:port => 3000,
|
||||
:ip => "0.0.0.0",
|
||||
:environment => (ENV['RAILS_ENV'] || "development").dup,
|
||||
:server_root => File.expand_path(RAILS_ROOT + "/public/"),
|
||||
:server_type => WEBrick::SimpleServer,
|
||||
:charset => "UTF-8",
|
||||
:mime_types => WEBrick::HTTPUtils::DefaultMimeTypes
|
||||
}
|
||||
|
||||
ARGV.options do |opts|
|
||||
script_name = File.basename($0)
|
||||
opts.banner = "Usage: ruby #{script_name} [options]"
|
||||
|
||||
opts.separator ""
|
||||
|
||||
opts.on("-p", "--port=port", Integer,
|
||||
"Runs Rails on the specified port.",
|
||||
"Default: 3000") { |v| OPTIONS[:port] = v }
|
||||
opts.on("-b", "--binding=ip", String,
|
||||
"Binds Rails to the specified ip.",
|
||||
"Default: 0.0.0.0") { |v| OPTIONS[:ip] = v }
|
||||
opts.on("-e", "--environment=name", String,
|
||||
"Specifies the environment to run this server under (test/development/production).",
|
||||
"Default: development") { |v| OPTIONS[:environment] = v }
|
||||
opts.on("-m", "--mime-types=filename", String,
|
||||
"Specifies an Apache style mime.types configuration file to be used for mime types",
|
||||
"Default: none") { |mime_types_file| OPTIONS[:mime_types] = WEBrick::HTTPUtils::load_mime_types(mime_types_file) }
|
||||
|
||||
opts.on("-d", "--daemon",
|
||||
"Make Rails run as a Daemon (only works if fork is available -- meaning on *nix)."
|
||||
) { OPTIONS[:server_type] = WEBrick::Daemon }
|
||||
|
||||
opts.on("-c", "--charset=charset", String,
|
||||
"Set default charset for output.",
|
||||
"Default: UTF-8") { |v| OPTIONS[:charset] = v }
|
||||
|
||||
opts.separator ""
|
||||
|
||||
opts.on("-h", "--help",
|
||||
"Show this help message.") { puts opts; exit }
|
||||
|
||||
opts.parse!
|
||||
end
|
||||
|
||||
ENV["RAILS_ENV"] = OPTIONS[:environment]
|
||||
RAILS_ENV.replace(OPTIONS[:environment]) if defined?(RAILS_ENV)
|
||||
|
||||
require RAILS_ROOT + "/config/environment"
|
||||
require 'webrick_server'
|
||||
|
||||
OPTIONS['working_directory'] = File.expand_path(RAILS_ROOT)
|
||||
|
||||
puts "=> Rails application started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
|
||||
puts "=> Ctrl-C to shutdown server; call with --help for options" if OPTIONS[:server_type] == WEBrick::SimpleServer
|
||||
DispatchServlet.dispatch(OPTIONS)
|
4
vendor/rails/railties/lib/commands/update.rb
vendored
Normal file
4
vendor/rails/railties/lib/commands/update.rb
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
require "#{RAILS_ROOT}/config/environment"
|
||||
require 'rails_generator'
|
||||
require 'rails_generator/scripts/update'
|
||||
Rails::Generator::Scripts::Update.new.run(ARGV)
|
Loading…
Add table
Add a link
Reference in a new issue