lib/vegas/runner.rb in vegas-0.0.4.1 vs lib/vegas/runner.rb in vegas-0.1.0

- old
+ new

@@ -10,77 +10,86 @@ end end module Vegas class Runner - attr_reader :app, :app_name, :rack_handler, :port, :host, :options - + attr_reader :app, :app_name, :rack_handler, :port, :host, :options, :args + ROOT_DIR = File.expand_path(File.join('~', '.vegas')) PORT = 5678 HOST = WINDOWS ? 'localhost' : '0.0.0.0' - - def initialize(app, app_name, set_options = {}, &block) + + def initialize(app, app_name, set_options = {}, runtime_args = ARGV, &block) # initialize - @app = app - @app_name = app_name - @options = set_options || {} - @rack_handler = @app.send :detect_rack_handler + @app = app + @app_name = app_name + @options = set_options || {} + @runtime_args = runtime_args + self.class.logger.level = options[:debug] ? Logger::DEBUG : Logger::INFO + + @rack_handler = @app.respond_to?(:detect_rack_handler) ? + @app.send(:detect_rack_handler) : Rack::Handler.get('thin') # load options from opt parser - define_options do |opts| + @args = define_options do |opts| if block_given? opts.separator '' opts.separator "#{app_name} options:" - yield(opts, app) + yield(self, opts, app) end end + # set app options @host = options[:host] || HOST - @app.set options + @app.set(options) if @app.respond_to?(:set) # initialize app dir FileUtils.mkdir_p(app_dir) - - logger.info "Running with Windows Settings" if WINDOWS - logger.info "Starting #{app_name}" - - check_for_running - find_port - write_url - - begin - launch! - daemonize! unless options[:foreground] - run! - rescue RuntimeError => e - logger.warn "There was an error starting #{app_name}: #{e}" - exit + return if options[:start] === false + # evaluate the launch_path + path = if options[:launch_path] && options[:launch_path].respond_to?(:call) + options[:launch_path].call(self) + else + options[:launch_path] end + start(path) end - + def app_dir File.join(ROOT_DIR, app_name) end - + def pid_file File.join(app_dir, "#{app_name}.pid") end - + def url_file File.join(app_dir, "#{app_name}.url") end - + def url "http://#{host}:#{port}" end - + def log_file File.join(app_dir, "#{app_name}.log") end - - def handler_name - rack_handler.name.gsub(/.*::/, '') + + def start(path = nil) + logger.info "Running with Windows Settings" if WINDOWS + logger.info "Starting #{app_name}" + begin + check_for_running(path) + find_port + write_url + launch!(url, path) + daemonize! unless options[:foreground] + run! + rescue RuntimeError => e + logger.warn "There was an error starting #{app_name}: #{e}" + exit + end end - + def find_port if @port = options[:port] if !port_open? logger.warn "Port #{port} is already in use. Please try another or don't use -P, for auto-port" end @@ -91,46 +100,46 @@ @port += 1 logger.info "Trying to start #{app_name} on Port #{port}" end end end - + def port_open?(check_url = nil) begin open(check_url || url) false rescue Errno::ECONNREFUSED => e true end end - + def write_url File.open(url_file, 'w') {|f| f << url } end - - def check_for_running + + def check_for_running(path = nil) if File.exists?(pid_file) && File.exists?(url_file) running_url = File.read(url_file) if !port_open?(running_url) logger.warn "#{app_name} is already running at #{running_url}" - launch!(running_url) + launch!(running_url, path) exit! end end end - + def run! rack_handler.run app, :Host => host, :Port => port do |server| trap(kill_command) do ## Use thins' hard #stop! if available, otherwise just #stop server.respond_to?(:stop!) ? server.stop! : server.stop logger.info "#{app_name} received INT ... stopping" delete_pid! end end end - + # Adapted from Rackup def daemonize! if RUBY_VERSION < "1.9" logger.debug "Parent Process: #{Process.pid}" exit! if fork @@ -147,55 +156,65 @@ logger.debug "Child Process: #{Process.pid}" File.open(pid_file, 'w') {|f| f.write("#{Process.pid}") } at_exit { delete_pid! } end - - def launch!(specific_url = nil) + + def launch!(specific_url = nil, path = nil) return if options[:skip_launch] - cmd = WINDOWS ? "start" : "sleep 2 && open" - system "#{cmd} #{specific_url || url}" + cmd = WINDOWS ? "start" : "open" + system "#{cmd} #{specific_url || url}#{path}" end - + def kill! pid = File.read(pid_file) logger.warn "Sending INT to #{pid.to_i}" Process.kill(kill_command, pid.to_i) rescue => e logger.warn "pid not found at #{pid_file} : #{e}" end - + def status if File.exists?(pid_file) logger.info "#{app_name} running" logger.info "PID #{File.read(pid_file)}" logger.info "URL #{File.read(url_file)}" if File.exists?(url_file) else logger.info "#{app_name} not running!" end end - def logger - return @logger if @logger - @logger = Logger.new(STDOUT) - @logger.level = options[:debug] ? Logger::DEBUG : Logger::INFO - @logger.formatter = Proc.new {|s, t, n, msg| "[#{t}] #{msg}\n"} + def self.logger=(logger) + @logger = logger + end + + def self.logger + @logger ||= LOGGER if defined?(LOGGER) + if !@logger + @logger = Logger.new(STDOUT) + @logger.formatter = Proc.new {|s, t, n, msg| "[#{t}] #{msg}\n"} + @logger + end @logger end - + + def logger + self.class.logger + end + private def define_options - OptionParser.new("", 24, ' ') { |opts| + OptionParser.new("", 24, ' ') do |opts| opts.banner = "Usage: #{app_name} [options]" opts.separator "" opts.separator "Vegas options:" - - opts.on("-s", "--server SERVER", "serve using SERVER (webrick/mongrel)") { |s| + + opts.on("-s", "--server SERVER", "serve using SERVER (thin/mongrel/webrick)") { |s| @rack_handler = Rack::Handler.get(s) } - + opts.on("-o", "--host HOST", "listen on HOST (default: #{HOST})") { |host| @options[:host] = host } opts.on("-p", "--port PORT", "use PORT (default: #{PORT})") { |port| @@ -216,22 +235,22 @@ opts.on('-K', "--kill", "kill the running process and exit") {|k| kill! exit } - + opts.on('-S', "--status", "display the current running PID and URL then quit") {|s| status exit! } - + opts.on('-d', "--debug", "raise the log level to :debug (default: :info)") {|s| @options[:debug] = true } - + yield opts if block_given? - + opts.separator "" opts.separator "Common options:" opts.on_tail("-h", "--help", "Show this message") do puts opts @@ -240,26 +259,27 @@ opts.on_tail("--version", "Show version") do if app.respond_to?(:version) puts "#{app_name} #{app.version}" end - puts "sinatra #{Sinatra::VERSION}" + puts "rack #{Rack::VERSION.join('.')}" + puts "sinatra #{Sinatra::VERSION}" if defined?(Sinatra) puts "vegas #{Vegas::VERSION}" exit end - opts.parse! ARGV - } + end.parse! @runtime_args rescue OptionParser::MissingArgument => e logger.warn "#{e}, run -h for options" exit end - + def kill_command WINDOWS ? 1 : :INT end - + def delete_pid! File.delete(pid_file) if File.exist?(pid_file) end end + end