bin/camping in camping-1.4.2 vs bin/camping in camping-1.5

- old
+ new

@@ -1,62 +1,60 @@ #!/usr/bin/env ruby -# this line prevents other db adapters from being loaded (oci8 was -# causing some pain.) -unless Object.const_defined? :RAILS_CONNECTION_ADAPTERS - RAILS_CONNECTION_ADAPTERS = [] -end -RAILS_CONNECTION_ADAPTERS.replace %w[sqlite] - require 'delegate' require 'optparse' +require 'ostruct' + require 'stringio' -require 'rubygems' require 'camping' +require 'camping/reloader' +require 'yaml' -host = '0.0.0.0' -port = 3301 +conf = OpenStruct.new(:host => '0.0.0.0', :port => 3301) -db = nil -homes = [] -homes << File.join( ENV['HOME'], '.camping.db' ) if ENV['HOME'] -homes << File.join( ENV['APPDATA'], 'Camping.db' ) if ENV['APPDATA'] -homes.each do |db| - break if File.exists?( db ) +# Setup paths +if home = ENV['HOME'] # POSIX + conf.db = File.join(home, '.camping.db') + conf.rc = File.join(home, '.campingrc') +elsif home = ENV['APPDATA'] # MSWIN + conf.db = File.join(home, 'Camping.db') + conf.rc = File.join(home, 'Campingrc') end +# Load configuration if any +if conf.rc and File.exists?( conf.rc ) + YAML.load_file(conf.rc).each do |k,v| + conf.send("#{k}=", v) + end +end +# Parse options opts = OptionParser.new do |opts| opts.banner = "Usage: camping app1.rb, app2.rb..." opts.define_head "#{File.basename($0)}, the microframework ON-button for ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]" opts.separator "" opts.separator "Specific options:" - opts.on("-h", "--host HOSTNAME", "Host for web server to bind to (default is all IPs)") do |h| - host = h - end + opts.on("-h", "--host HOSTNAME", "Host for web server to bind to (default is all IPs)") { |conf.host| } + opts.on("-p", "--port NUM", "Port for web server (defaults to #{conf.port})") { |conf.port| } + opts.on("-d", "--database FILE", "Database file (defaults to #{conf.db})") { |conf.db| } + opts.on("-l", "--log FILE", "Start a database log ('-' for STDOUT)") { |conf.log| } + opts.on("-C", "--console", "Run in console mode with IRB") { conf.server = :console } + opts.on("-s", "--server NAME", "Server to force (mongrel, webrick, console)") { |s| conf.server = s.to_sym } - opts.on("-p", "--port NUM", "Port for web server (defaults to #{port})") do |p| - port = p - end - - opts.on("-d", "--database FILE", "Database file (defaults to #{db})") do |d| - db = d - end - opts.separator "" opts.separator "Common options:" # No argument, shows at tail. This will print an options summary. # Try it and see! - opts.on_tail("-h", "--help", "Show this message") do + opts.on_tail("-?", "--help", "Show this message") do puts opts exit end # Another typical switch to print the version. - opts.on_tail("--version", "Show version") do + opts.on_tail("-v", "--version", "Show version") do class << Gem; attr_accessor :loaded_specs; end puts Gem.loaded_specs['camping'].version exit end end @@ -65,67 +63,51 @@ if ARGV.length < 1 puts opts exit end -Camping::Models::Base.establish_connection :adapter => 'sqlite3', :database => db +# Default database +unless conf.database + unless conf.db + puts "!! No home directory found. Please specify a database file, see --help."; exit + end + conf.database = {:adapter => 'sqlite3', :database => conf.db} +end -class CampingReloader - attr_accessor :klass, :mtime, :mount - - def initialize(script) - @script = script - @mount = File.basename(script, '.rb') - load_app +# Load apps +PATHS = ARGV.dup +apps = PATHS.inject([]) do |apps, script| + if File.directory? script + apps.push(*Dir[File.join(script, '*.rb')]) + else + apps << script end +end - def load_app - @mtime = File.mtime(@script) - title = File.basename(@script)[/^(\w+)/,1] - begin - load @script - rescue Exception => e - puts "!! trouble loading #{title}: [#{e.class}] #{e.message}" - @klass = nil - return - end +Camping::Reloader.database = conf.database +Camping::Reloader.log = conf.log +apps.map! { |script| Camping::Reloader.new(script) } +abort("** No apps successfully loaded") unless apps.detect { |app| app.klass } - @klass = Object.const_get(Object.constants.grep(/^#{title}$/i)[0]) rescue nil - unless @klass.const_defined? :C - puts "!! trouble loading #{title}: not a Camping app" - @klass = nil - return - end - @klass.create if @klass.respond_to? :create - @klass - end +def apps.find_new_scripts + each { |app| app.reload_app } + PATHS.each do |path| + Dir[File.join(path, '*.rb')].each do |script| + smount = File.basename(script, '.rb') + next if detect { |x| x.mount == smount } - # Load the script, locate the module - def reload_app - newtime = File.mtime( @script ) - return if @klass and @mtime and newtime <= @mtime + puts "** Discovered new #{script}" + app = Camping::Reloader.new(script) + next unless app - k = @klass - Object.instance_eval { remove_const k.name } if k - load_app - end - - def run(*a) - reload_app - if @klass - @klass.run(*a) - else - Camping.run(*a) + yield app + self << app end end - - def view_source - File.read(@script) - end + self.sort! { |x, y| x.mount <=> y.mount } end -apps = ARGV.map { |script| CampingReloader.new(script) } def apps.index_page welcome = "You are Camping" apps = self b = Markaby::Builder.new({}, {}) b = b.instance_eval do @@ -159,19 +141,38 @@ end end b.to_s end -begin +# Check that mongrel exists +unless conf.server + begin + require 'mongrel' + require 'mongrel/camping' + conf.server = :mongrel + rescue LoadError + conf.server = :webrick + end +end + +# Running the selected server +case conf.server.to_s +when 'mongrel' require 'mongrel' require 'mongrel/camping' + class IndexHandler < Mongrel::HttpHandler - def initialize(apps) + def initialize(apps, server) @apps = apps + @server = server end def process(req, res) res.start(200) do |head, out| + @apps.find_new_scripts do |app| + @server.register "/#{app.mount}", Mongrel::Camping::CampingHandler.new(app) + @server.register "/code/#{app.mount}", ViewSource.new(app) + end out << @apps.index_page end end end class ViewSource < Mongrel::HttpHandler @@ -183,39 +184,96 @@ head['Content-Type'] = 'text/plain' out << @app.view_source end end end - config = Mongrel::Configurator.new :host => host do - listener :port => port do - apps.each do |app| - uri "/#{app.mount}", :handler => Mongrel::Camping::CampingHandler.new(app) - uri "/code/#{app.mount}", :handler => ViewSource.new(app) + begin + config = Mongrel::Configurator.new :host => conf.host do + listener :port => conf.port do + if apps.length > 1 + apps.each do |app| + uri "/#{app.mount}", :handler => Mongrel::Camping::CampingHandler.new(app) + uri "/code/#{app.mount}", :handler => ViewSource.new(app) + end + uri "/", :handler => IndexHandler.new(apps, @listener) + else + uri "/", :handler => Mongrel::Camping::CampingHandler.new(apps.first) + end + uri "/favicon.ico", :handler => Mongrel::Error404Handler.new("") + trap("INT") { stop } + run end - uri "/", :handler => IndexHandler.new(apps) - uri "/favicon.ico", :handler => Mongrel::Error404Handler.new("") - trap("INT") { stop } - run - end + end + + puts "** Camping running on #{conf.host}:#{conf.port}." + config.join + rescue Errno::EADDRINUSE + puts "** ERROR : address #{conf.host}:#{conf.port} already in use." end - config.join -rescue LoadError +when 'webrick' require 'webrick/httpserver' require 'camping/webrick' # Mount the root - s = WEBrick::HTTPServer.new(:BindAddress => host, :Port => port) - apps.each do |app| - s.mount "/#{app.mount}", WEBrick::CampingHandler, app - s.mount_proc("/code/#{app.mount}") do |req, resp| - resp['Content-Type'] = 'text/plain' - resp.body = app.view_source + s = WEBrick::HTTPServer.new(:BindAddress => conf.host, :Port => conf.port) + if apps.length > 1 + apps.each do |app| + s.mount "/#{app.mount}", WEBrick::CampingHandler, app + s.mount_proc("/code/#{app.mount}") do |req, resp| + resp['Content-Type'] = 'text/plain' + resp.body = app.view_source + end end + s.mount_proc("/") do |req, resp| + apps.find_new_scripts do |app| + s.mount "/#{app.mount}", WEBrick::CampingHandler, app + s.mount_proc("/code/#{app.mount}") do |req, resp| + resp['Content-Type'] = 'text/plain' + resp.body = app.view_source + end + end + resp.body = apps.index_page + end + else + s.mount "/", WEBrick::CampingHandler, apps.first end - s.mount_proc("/") { |req, resp| resp.body = apps.index_page } # Server up trap(:INT) do s.shutdown end s.start +when 'lighttpd' + require 'rbconfig' + ruby = File.join(Config::CONFIG['bindir'], Config::CONFIG['RUBY_INSTALL_NAME']) + dispatcher =<<SCRIPT +#!#{ruby} +require 'rubygems' +require 'camping/fastcgi' +Camping::Models::Base.establish_connection(Marshal.load(#{Marshal.dump(conf.database).dump})) +Camping::FastCGI.serve("") +SCRIPT + lighttpd_conf =<<CONF +server.port = #{conf.port} +server.bind = "#{conf.host}" +server.modules = ( "mod_fastcgi" ) +server.document-root = "/dont/need/one" + +#### fastcgi module +fastcgi.server = ( "/" => ( + "localhost" => ( + "socket" => "/tmp/camping-blog.socket", + "bin-path" => "#{conf.dispatcher}", + "check-local" => "disable", + "max-procs" => 1 ) ) ) +CONF + +when 'console' + ARGV.clear # Avoid passing args to IRB + + require 'irb' + require 'irb/completion' + if File.exists? ".irbrc" + ENV['IRBRC'] = ".irbrc" + end + IRB.start end