lib/conf/argv.rb in rsence-2.0.0.3.pre vs lib/conf/argv.rb in rsence-2.0.0.4.pre
- old
+ new
@@ -16,14 +16,14 @@
class ARGVParser
@@version = File.read( File.join( SERVER_PATH, 'VERSION' ) ).strip
if RSence.pid_support?
- @@cmds = [ :run, :status, :start, :stop, :restart, :save, :setup,
+ @@cmds = [ :run, :status, :start, :stop, :restart, :save,
:initenv, :version, :help ]
else
- @@cmds = [ :run, :setup, :initenv, :version, :help ]
+ @@cmds = [ :run, :initenv, :version, :help ]
end
@@cmd_help = {}
@@cmd_help[:head] = <<-EOF
@@ -47,34 +47,10 @@
@@cmd_help[:path] = <<-EOF
The [PATH] is the RSence environment to use.
The [PATH] defaults to the current working directory.
-The expected structure of a project environment (where 'project_directory'
-is the directory of your project) is:
-
- [dir] project_directory :: The directory of your project.
- [dir] conf :: The directory of config files.
- [file] config.yaml :: The config file to load by defult.
- [dir] db :: Directory containing database files.
- [dir] log :: Directory containing log files.
- [dir] plugins :: Directory containing installed plugins.
- [dir] run :: Directory containing runtime pid files.
-
-The 'config.yaml' file contains patches specific to your project.
-
-The configuration files are loaded and applied in this order:
- 1: [rsence_install_path]/conf/default_conf.yaml
- 2: [rsence_install_path]/conf/local_conf.yaml
- 3: /etc/rsence/config.yaml
- 4: ~/.rsence/config.yaml
- 5: [project_directory]/conf/config.yaml
- 6: Any files given using --conf parameters, in order of occurrence.
-
-The plugins directory contains the plugins installed in the project.
-
-See also the 'setup' and 'initenv' commands.
EOF
@@cmd_help[:options] = <<-EOF
Available options:
@@ -98,11 +74,11 @@
--addr <ip address> The IP address or netmask the http server listens to.
'0.0.0.0' matches all interfaces.
'127.0.0.1' matches the local loopback interface.
- --server <handler> The Rack handler to use.
+ --server <handler> The Rack handler to use. Defaults to mongrel
--reset-sessions (-r) Resets all active sessions.
--auto-update (-a) Automatically checks for changes in installed plugin
and component bundles. Rebuilds changed component
@@ -122,16 +98,73 @@
Only available on Mac OS X and other systems with a
'say' command installed.
EOF
+@@cmd_help[:initenv] = <<-EOF
+usage: 'rsence initenv [options] [PATH]'
+
+The 'initenv' command creates a new RSence environment.
+
+The expected structure of a project environment (where 'project_directory'
+is the directory of your project) is:
+
+ [d] project_name : The name of your project.
+ [d] conf : The directory of config files.
+ [f] config.yaml : The config file to load by defult.
+ [d] db : Directory containing database files.
+ [d] log : Directory containing log files.
+ [d] plugins : Directory containing installed plugins.
+ [d] run : Directory containing runtime pid files.
+ [f] README : Description of the environment directory.
+ [f] VERSION : RSence version the environment was created with
+
+The 'config.yaml' file contains patches specific to your project.
+
+The configuration files are loaded and applied in this order:
+ 1: [rsence_install_path]/conf/default_conf.yaml
+ 2: [rsence_install_path]/conf/local_conf.yaml
+ 3: /etc/rsence/config.yaml
+ 4: ~/.rsence/config.yaml
+ 5: [project_directory]/conf/config.yaml
+ 6: Any files given using --conf parameters, in order of occurrence.
+
+The plugins directory contains the plugins that are run in the project.
+
+
+Available options:
+
+ --port <number> The port number the http server listens to.
+
+ --addr <ip address> The IP address or netmask the http server listens to.
+ '0.0.0.0' matches all interfaces.
+ '127.0.0.1' matches the local loopback interface.
+ Defaults to 0.0.0.0
+
+ --server <handler> The Rack handler to use. Defaults to mongrel
+
+ --title <title> The title of the index page.
+
+ --database <conn_str> Use the Sequel connection string to configure the
+ default session database.
+
+ --uri-prefix <path> Configure RSence to use this http "directory" as
+ the prefix. It defaults to the root directory: /
+
+ --blank Doesn't install the Welcome -plugin.
+
+ --non-interactive (-q) Doesn't ask anything, just creates the environment
+ with the options supplied.
+
+For further configuration, edit the config.yaml file.
+
+EOF
+
@@cmd_help[:run] = <<-EOF
usage: 'rsence run [options] [PATH]'
The 'run' command starts RSence in foreground (no daemon). Exit with CTRL-C.
-This is the suggested mode for development and the only mode supported by
-Windows, because Windows is missing the concept of a process ID.
#{@@cmd_help[:path]}
#{@@cmd_help[:options]}
EOF
@@ -142,22 +175,22 @@
Use the 'stop' command to stop RSence.
Use the 'restart' command to restart RSence in the background.
-Use the 'status' command to check if RSence is running.
+Use the 'status' command to see if RSence is running.
#{@@cmd_help[:path]}
#{@@cmd_help[:options]}
EOF
@@cmd_help[:stop] = <<-EOF
usage: 'rsence stop [options] [PATH]'
The 'stop' command stops RSence running in the background (as a daemon).
-Use the 'status' command to check if RSence is running.
+Use the 'status' command to see if RSence is running.
#{@@cmd_help[:path]}
#{@@cmd_help[:options]}
EOF
@@ -167,12 +200,13 @@
The 'restart' command restarts RSence in the background (as a daemon).
If RSence wasn't running before the 'restart' command was issued, the
effect is the same as 'start'.
Use the 'stop' command to stop RSence.
-Use the 'status' command to check if RSence is running.
+Use the 'status' command to see if RSence is running.
+
#{@@cmd_help[:path]}
#{@@cmd_help[:options]}
EOF
@@cmd_help[:status] = <<-EOF
@@ -226,10 +260,39 @@
@@cmd_help[:version] = <<-EOF
usage: 'rsence version'
The 'version' command simply outputs the version number of RSence.
+RSence follows the standard four-numbered sequence-based version identification
+scheme. The scheme is defined like: major.minor[.maintenance[.package]][.pre]
+
+The major number designates major changes in functionality, sometimes limiting
+backwards compatibility with software written for previous versions.
+
+The minor number designates minor changes in functionality, like minor or
+moderate changes in functinality that usually don't impact backwards
+compatibilty of software written for a previous release with the same major
+version.
+
+The maintenance number designates bug fixes and other minimal changes to
+the release. In a maintenance number change, no new features are introduced.
+
+The package number is a sequence used for the package release. Rubygems
+requires an unique version for each gem released, so pre-releases usually
+occupy the first package numbers of any release.
+
+The '.pre' suffix signifies a pre-release, like "Alpha" or "Beta". To
+install a prerelease version, gem requires the '--pre' command line argument.
+Release versions never have the '.pre' suffix. There are usually several
+package number increments of a new release.
+
+Version number conventions in written text should include both major and
+minor version numbers prefixed with 'RSence'. The maintennance number
+is usally not mentioned unless an issue is fix or such is discussed.
+
+For instance: "RSence 2.0 has undergone some major refactoring since 1.2.1"
+
EOF
@@cmd_help[:tail] = <<-EOF
RSence is a self-contained rich internet application client-server framework.
For further information, see http://rsence.org/
@@ -394,40 +457,40 @@
end
def set_say
@args[:say] = true
end
- def valid_env?( arg )
+ def valid_env?( arg, quiet=false )
path = File.expand_path( arg )
if not File.exists?( path )
- puts "no such directory: #{path.inspect}"
+ puts "no such directory: #{path.inspect}" unless quiet
return false
elsif not File.directory?( path )
- puts "not a directory: #{path.inspect}"
+ puts "not a directory: #{path.inspect}" unless quiet
return false
end
conf_path = File.join( path, 'conf' )
if not File.exists?( conf_path )
- puts "no conf directory, expected: #{conf_path.inspect}"
+ puts "no conf directory, expected: #{conf_path.inspect}" unless quiet
return false
elsif not File.directory?( conf_path )
- puts "not a conf directory, expected: #{conf_path.inspect}"
+ puts "not a conf directory, expected: #{conf_path.inspect}" unless quiet
return false
end
conf_file = File.join( path, 'conf', 'config.yaml' )
if not File.exists?(conf_file)
- puts "missing conf file, expected: #{conf_file.inspect}"
+ puts "missing conf file, expected: #{conf_file.inspect}" unless quiet
return false
elsif not File.file?( conf_file )
- puts "conf file not a file, expected: #{conf_file.inspect}"
+ puts "conf file not a file, expected: #{conf_file.inspect}" unless quiet
return false
end
plugin_path = File.join( path, 'plugins' )
if not File.exists?( plugin_path )
warn "Warning; no plugin directory in project, expected: #{plugin_path.inspect}" if @args[:verbose]
elsif not File.directory?( plugin_path )
- puts "plugin directory not a directory, expected: #{plugin_path.inspect}"
+ puts "plugin directory not a directory, expected: #{plugin_path.inspect}" unless quiet
return false
end
run_path = File.join( path, 'run' )
unless File.exists?( run_path )
warn "Warning: no run directory: Creating #{run_path.inspect}" if @args[:verbose]
@@ -464,15 +527,19 @@
end
def test_port( port, addr='127.0.0.1' )
require 'socket'
begin
+ addr = '127.0.0.1' if addr == '0.0.0.0'
sock = TCPsocket.open( addr, port )
sock.close
return true
rescue Errno::ECONNREFUSED
return false
+ rescue => e
+ warn e.inspect
+ return false
end
end
def parse_status_argv
init_args
@@ -665,19 +732,39 @@
puts "Session data saved."
end
end
end
- def parse_setup_argv
- throw "parse_setup_argv not implemented!"
+ # asks y/n and returns boleans,
+ # the default tells if which one is for just enter
+ def yesno(default=false)
+ if default
+ question = "Y/n? "
+ else
+ question = "y/N? "
+ end
+ print question
+ answer = $stdin.gets.strip.downcase[0]
+ answer = answer.chr if answer
+ if answer == 'n'
+ return false
+ elsif answer == 'y'
+ return true
+ elsif answer == nil
+ return default
+ else
+ return nil
+ end
end
def parse_initenv_argv
init_args
expect_option = false
- option_name = false
- valid_env
+ option_name = false
+ valid_env = false
+ interactive = true
+ create_blank = false
if @argv.length >= 2
@argv[1..-1].each_with_index do |arg,i|
if expect_option
if [:port].include?(option_name) and arg.to_i.to_s != arg
puts "invalid #{option_name.to_s}, expected number: #{arg.inspect}"
@@ -699,60 +786,251 @@
expect_option = true
option_name = :server
elsif arg == '--title'
expect_option = true
option_name = :title
+ elsif arg == '--database'
+ expect_option = true
+ option_name = :db
+ elsif arg == '--uri-prefix'
+ expect_option = true
+ option_name = :base_url
+ elsif arg == '--blank'
+ create_blank = true
+ elsif arg == '--non-interactive'
+ interactive = false
else
invalid_option(arg)
end
- elsif valid_env?(arg)
+ elsif arg.start_with?('-')
+ arg.split('')[1..-1].each do |chr|
+ if chr == 'q'
+ interactive = false
+ end
+ end
+ else
@args[:env_path] = File.expand_path(arg)
end
end
end
if expect_option
puts "no value for option #{option_name.to_s.inspect}"
puts "Type 'rsence help #{@cmd.to_s} for usage."
exit
end
end
- if valid_env?(@args[:env_path])
- conf_file = File.expand_path( File.join( @args[:env_path], 'conf', 'config.yaml' ) )
- @args[:conf_files].push( conf_file ) unless @args[:conf_files].include?( conf_file )
- else
- puts "invalid environment."
+ if valid_env?(@args[:env_path],true)
+ puts "Environment already initialized."
exit
end
+ conf_file = File.expand_path( File.join( @args[:env_path], 'conf', 'config.yaml' ) )
+ if File.exists?(@args[:env_path])
+ if Dir.entries(@args[:env_path]).length > 2 # [ '.', '..' ]
+ puts "Environment directory #{@args[:env_path]} is not empty."
+ exit
+ end
+ end
+
require 'conf/default'
- config = Configuration.new(@args).config
- port = config[:http_server][:port]
- addr = config[:http_server][:bind_address]
- port_status = test_port( port, addr )
- if RSence.pid_support?
- pid_fn = config[:daemon][:pid_fn]
- if File.exists?( pid_fn )
- pid = File.read( pid_fn ).to_i
- pid_status = RSence::SIGComm.wait_signal_response(
- pid, pid_fn, 'USR2', 3
- )
- else
- puts "no PID file, unable to check process status" if @args[:verbose]
- pid_status = nil
+ default_config = Configuration.new(@args,true).config
+
+ config = {
+ :base_url => (@args[:base_url] or default_config[:base_url]),
+ :http_server => {
+ :port => (@args[:port] or default_config[:http_server][:port]),
+ :bind_address => (@args[:addr] or default_config[:http_server][:bind_address]),
+ :rack_require => (@args[:server] or default_config[:http_server][:rack_require])
+ },
+ :index_html => {
+ :title => (@args[:title] or default_config[:index_html][:title])
+ },
+ :database => {
+ :ses_db => (@args[:db] or default_config[:database][:ses_db])
+ }
+ }
+ Signal.trap 'INT' do
+ puts
+ puts "Configuration aborted."
+ exit
+ end
+ if interactive
+ answers_ok = false
+ until answers_ok
+ puts <<-END
+
+Creating a new RSence environment at #{@args[:env_path]}
+
+RSence will first ask a few questions about your environment
+in order to initialize and prepare the project configuration.
+
+You may abort this command at any time by pressing CTRL-C
+Nothing will be written until you have answered all the questions.
+
+Pressing the ENTER (or RETURN) key at each prompt will choose the
+default option shown.
+If you are not sure about how to answer a question, press
+the ENTER (or RETURN) key to continue.
+
+ END
+
+ require 'highline/import'
+
+ say <<-END
+
+ Please enter the title of your project.
+ This title will be used in the default page title.
+
+ END
+ config[:index_html][:title] = ask("Project Title") do |q|
+ q.default = config[:index_html][:title]
+ end
+
+ say <<-END
+
+
+
+ Please specify the connection string for the session database to use.
+ By default, a local SQLite database is created in the 'db' subdirectory
+ of the environment directory. Any database supported by Sequel is supported
+ by RSence.
+
+ For further information about database connection strings, read the Sequel
+ documentation at:
+ http://sequel.rubyforge.org/rdoc/files/doc/opening_databases_rdoc.html
+
+ You will also need the appropriate ruby driver for the database selected. If
+ none is installed, RSence will not be able to store persistent session data
+ between server restarts.
+
+ END
+ config[:database][:ses_db] = ask("Session database connection string") do |q|
+ q.default = config[:database][:ses_db]
+ end
+ say <<-END
+
+
+
+ Please enter a HTTP port for the server to listen to. This port must not be a
+ TCP port already in use.
+
+ END
+ config[:http_server][:port] = ask("HTTP Port:") do |q|
+ q.default = config[:http_server][:port]
+ end
+ say <<-END
+
+
+ Please enter a TCP/IP address for the HTTP server to listen to. This address
+ must be an address configured by a network interface of this computer.
+
+ The address 0.0.0.0 matches any interfaces.
+ The address 127.0.0.1 matches only the localhost address, this address is
+ not accessible from any other computer.
+
+ END
+ config[:http_server][:bind_address] = ask("Interface TCP/IP address:") do |q|
+ q.default = config[:http_server][:bind_address]
+ end
+
+ say <<-END
+
+
+ Please enter a root directory for RSence to respond in.
+ By default this is the root directory of the server: /
+
+ END
+ config[:base_url] = ask("URI Prefix:") do |q|
+ q.default = config[:base_url]
+ end
+ test_url = "http://#{config[:http_server][:bind_address]}:#{config[:http_server][:port]}#{config[:base_url]}"
+ say <<-END
+
+Configuration Summary
+
+ Please verify that the configuration is correct.
+ This configuration will be written into the configuration file:
+ #{conf_file}
+
+Title: #{config[:index_html][:title]}
+
+Database: #{config[:database][:ses_db]}
+
+HTTP Server:
+ Address: #{config[:http_server][:bind_address]}
+ Port: #{config[:http_server][:port]}
+ URI Prefix: #{config[:base_url]}
+
+ This means the URL will be #{test_url}
+
+ END
+ print "Is the configuration correct, "
+ answers_ok = yesno(true)
end
else
- puts "no PID support, unable to check process status" if @args[:verbose]
- pid_status = nil
+ test_url = "http://#{config[:http_server][:bind_address]}:#{config[:http_server][:port]}#{config[:base_url]}"
end
- if RSence.pid_support?
- if pid_status == nil
- puts "No process id, unable to check process status."
- elsif pid_status == false
- puts "No process running#{port_status ? ' but something responds on ' : ' and nothing responds on ' }#{addr}:#{port}."
- else
- puts "Process id #{pid} is running#{port_status ? ' and responds on ' : ', but does not respond on '}#{addr}:#{port}."
- end
+
+ puts "Creating directories..."
+ env_dir = @args[:env_path]
+ require 'fileutils'
+ FileUtils.mkdir_p( env_dir ) unless File.exists?( env_dir )
+ conf_dir = File.expand_path( 'conf', env_dir )
+ Dir.mkdir( conf_dir )
+ db_dir = File.expand_path( 'db', env_dir )
+ Dir.mkdir( db_dir )
+ log_dir = File.expand_path( 'log', env_dir )
+ Dir.mkdir( log_dir )
+ plugins_dir = File.expand_path( 'plugins', env_dir )
+ Dir.mkdir( plugins_dir )
+ run_dir = File.expand_path( 'run', env_dir )
+ Dir.mkdir( run_dir )
+ unless create_blank
+ welcome_plugin_dir = File.join( SERVER_PATH, 'setup', 'welcome' )
+ welcome_plugin_dst = File.join( plugins_dir, 'welcome' )
+ puts "Installing the welcome plugin. To remove it, just delete this folder:"
+ puts " #{welcome_plugin_dst}"
+ FileUtils.cp_r( welcome_plugin_dir, welcome_plugin_dst )
end
+ puts "Creating files..."
+ conf_file = File.join( conf_dir, 'config.yaml' )
+ File.open( conf_file, 'w' ) {|f| f.write( YAML.dump( config ) ) }
+ readme_file = File.join( env_dir, 'README' )
+ File.open( readme_file, 'w' ) {|f| f.write( <<-END
+This directory contains a RSence environment titled '#{config[:index_html][:title]}'.
+Visit http://rsence.org/ for further information.
+ END
+ ) }
+ version_file = File.join( env_dir, 'VERSION' )
+ File.open( readme_file, 'w' ) {|f| f.write( "RSence Environment Version #{version.to_f}" ) }
+ puts <<-END
+
+#{'-='*39}-
+
+RSence project environment for '#{config[:index_html][:title]}' created.
+
+You may configure the environment by editing the file:
+
+ #{conf_file}
+
+If you would like to test this environment now, start the RSence server:
+
+ rsence run #{env_dir}
+
+Then point your browser to:
+
+ #{test_url}
+
+The latest documentation and further information is available at the
+RSence website:
+
+ http://rsence.org/
+
+
+Congratulations!
+
+ END
+ exit
end
def help( cmd )
cmd.to_sym! if cmd.class != Symbol
puts @@cmd_help[:head]
@@ -795,11 +1073,9 @@
parse_startup_argv
elsif cmd == :status
parse_status_argv
elsif cmd == :save
parse_save_argv
- elsif cmd == :setup
- parse_setup_argv
elsif cmd == :initenv
parse_initenv_argv
end
else
puts @@cmd_help[:unknown] + cmd.to_s.inspect