lib/subtrac.rb in keithsalisbury-subtrac-0.1.15 vs lib/subtrac.rb in keithsalisbury-subtrac-1.0.0

- old
+ new

@@ -37,387 +37,192 @@ require 'yaml' require 'erb' require 'fileutils' require 'subtrac/version' -require 'subtrac/commands' - module Subtrac - - SUBTRAC_ROOT = "#{File.dirname(__FILE__)}/" unless defined?(SUBTRAC_ROOT) - SUBTRAC_ENV = (ENV['SUBTRAC_ENV'] || 'development').dup unless defined?(SUBTRAC_ENV) - USER_CONFIG = 'config/user.yml' - - class << self - - # The Configuration instance used to configure the Subtrac environment - def configuration - @@configuration + DEV_ENV = 'test' # should be a system environment var + DEV_ROOT = Dir.getwd + module Commands + class Install + def initialize(args, options) + Devserver.load_config() + Devserver.install(args,options) + end end - - def configuration=(configuration) - @@configuration = configuration + class Create + def initialize(args, options) + project = ask("What is the name of the project you would like to create?") if !options.project + client = ask("Which client is this project for?") if !options.client + Devserver.load_config() + Devserver.create_project(options.project,options.client) + end end + end - def initialized? - @initialized || false + # Install + def self.install(args,options) + # Ask if the user agrees (yes or no) + confirm = agree("Are you sure?") if options.clean + if confirm + # clear previous data + clean() + create_environment_directories() + else + puts "\nAttempt install without overwrites" end - - def initialized=(initialized) - @initialized ||= initialized - end - - def root - Pathname.new(SUBTRAC_ROOT) if defined?(SUBTRAC_ROOT) - end - - def public_path - @@public_path ||= self.root ? File.join(self.root, "public") : "public" - end - - def subtrac_path - @@subtrac_path ||= self.root ? File.join(self.root, "subtrac") : "subtrac" - end - - def public_path=(path) - @@public_path = path - end - - def docs_dir - @@docs_dir ||= File.join(@install_dir,@APP_CONFIG[:dirs][:docs]) - end - - def docs_dir=(dir) - @@docs_dir = dir - end - - def svn_dir - @@svn_dir ||= File.join(@install_dir,@APP_CONFIG[:dirs][:svn]) - end - - def svn_dir=(dir) - @@svn_dir = dir - end - - def trac_dir - @@trac_dir ||= File.join(@install_dir,@APP_CONFIG[:dirs][:trac]) - end - - def trac_dir=(dir) - @@trac_dir = dir - end - - def temp_dir - @@temp_dir ||= File.join(@install_dir,@APP_CONFIG[:dirs][:temp]) - end - - def temp_dir=(dir) - @@temp_dir = dir - end - - def log_dir - @@log_dir ||= File.join(@install_dir,@APP_CONFIG[:dirs][:log]) - end - - def log_dir=(dir) - @@log_dir = dir - end - - def locations_dir - @@locations_dir ||= File.join(@install_dir,@APP_CONFIG[:dirs][:locations]) - end - - def locations_dir=(dir) - @@locations_dir = dir - end - + install_common_files() + create_virtual_host() + # create default project and client + #create_client(@APP_CONFIG[:default_client]) + create_project(@APP_CONFIG[:default_project],@APP_CONFIG[:default_client]) end + + private # Loads the configuration YML file def self.load_config - # TODO: We need to refactor this code so it will load the default configuration only if one has not been created puts "\n==== Loading configuration file ====" # load configuration file - file_path = File.join(subtrac_path, USER_CONFIG) - file_path = File.join(subtrac_path,"/config/config.yml") if not File.exists?(file_path) - puts "Attempting to read config file: #{file_path}" begin - raw_config = File.read(file_path) - yamlFile = YAML.load(raw_config) + yamlFile = YAML.load_file("#{DEV_ROOT}/config/config.yml") rescue Exception => e - raise StandardError, "Config #{file_path} could not be loaded." + raise StandardError, "config/config.yml could not be loaded." end if yamlFile - if yamlFile[SUBTRAC_ENV] - @APP_CONFIG = yamlFile[SUBTRAC_ENV] + if yamlFile[DEV_ENV] + @APP_CONFIG = yamlFile[DEV_ENV] else - raise StandardError, "config/config.yml exists, but doesn't have a configuration for #{SUBTRAC_ENV}." + raise StandardError, "config/config.yml exists, but doesn't have a configuration for DEV_ENV=#{DEV_ENV}." end else raise StandardError, "config/config.yml does not exist." end - puts "\n==== Installation options ====" - - say("Setting up default configuration...") - @server_name = @APP_CONFIG[:server_name] - @server_hostname = @APP_CONFIG[:server_hostname] - @server_ip = @APP_CONFIG[:server_ip] - - @default_client = @APP_CONFIG[:default_client] - @default_project = @APP_CONFIG[:default_project] - - @install_dir = File.expand_path(@APP_CONFIG[:installation_dir]) - @conf_dir = @APP_CONFIG[:apache2_conf] - - @ldap_enable = @APP_CONFIG[:ldap][:enable] - if (@ldap_enable) then - @ldap_bind_dn = @APP_CONFIG[:ldap][:bind_dn] - @ldap_bind_password = @APP_CONFIG[:ldap][:bind_password] - @ldap_url = @APP_CONFIG[:ldap][:host] - end - end - - # Install - def self.install(args,options) - puts "\n==== Installing development server files ====" - # check where we are installing - change_install_dir = agree("The default installation directory is \"#{@install_dir}\". Would you like to change this? [Y/n]") - @install_dir = ask("Where would you like to install this server?") if change_install_dir - - unless !File.directory?(@install_dir) - # Ask if the user agrees (yes or no) - confirm_clean = agree("Err, it seems there's some stuff in there. You sure you want me to overwrite? [Y/n]") if options.clean - confirm_clean = agree("Doubly sure? I can't undo this....[Y/n]") if confirm_clean - end - - # right lets install - change_server_name = agree("The default server name is \"#{@server_name}\". Would you like to change this? [Y/n]") - @server_name = ask("What would you like to call your new development server? ") if change_server_name - - create_environment_directories(confirm_clean) - install_common_files() - configure_admin_user() - # TODO: Need to check for default client/project before creating virtual host - # otherwise we need remove the rewrite rule - create_virtual_host() - confirm_default_client = agree("Do you want to create a default client project? [Y/n]") - # create default project and client - if confirm_default_client - change_client = agree("The default client name is \"#{@default_client}\". Would you like to change this? [Y/n]") - @default_client = ask("What client name would you like to use? ") if change_client - change_project = agree("The default project name is \"#{@default_project}\". Would you like to change this? [Y/n]") - @default_project = ask("What would you like to call your new project? ") if change_project - create_project(@default_project,@default_client) - end - save_config() - end - - private - - # Write the changes configuration to disk - def self.save_config - # save the things that might have changed - @APP_CONFIG[:server_name] = @server_name - @APP_CONFIG[:server_hostname] = @server_hostname - @APP_CONFIG[:server_ip] = @server_ip - - @APP_CONFIG[:default_client] = @default_client - @APP_CONFIG[:default_project] = @default_project - - @APP_CONFIG[:installation_dir] = @install_dir - @APP_CONFIG[:apache2_conf] = @conf_dir - - @APP_CONFIG[:ldap][:bind_dn] = @ldap_bind_dn - @APP_CONFIG[:ldap][:bind_password] = @ldap_bind_password - @APP_CONFIG[:ldap][:host] = @ldap_url - - file_path = File.join(subtrac_path, USER_CONFIG) - open(file_path, 'w') {|f| YAML.dump({SUBTRAC_ENV => @APP_CONFIG}, f)} - end - # creates a directory if it does not exist - def self.create_if_missing(*names) - names.each do |name| - unless File.directory?(name) - puts "Creating directory called #{names}..." - FileUtils.mkdir_p(name) - end - end + def self.create_if_missing *names + puts "\n==== Creating directory #{names} ====" + names.each do |name| FileUtils.mkdir_p(name) unless File.directory?(name) end end # publishes an erb template def self.parse_template(infile,outfile,binding) - file = File.open(outfile, 'w+') + file = File.new(outfile, "w") if file - template = ERB.new(IO.read(infile)) - if template - file.syswrite(template.result(binding)) - else - raise "Could not read template. file #{infile}" - end + file.syswrite(ERB.new(IO.read(infile)).result(binding)) else - raise "Unable to open file for writing. file #{outfile}" + puts "Unable to write to file #{outfile}!" end end # creates a new virtual host and reloads apache and enables the new virtual host def self.create_virtual_host puts "\n==== Creating new virtual host ====" - vhost_template = File.join(subtrac_path, @APP_CONFIG[:templates][:virtual_host]) - puts "group apache tempalte: #{vhost_template}" - new_vhost = File.join(@conf_dir,@server_hostname) - puts "group apache file: #{new_vhost}" - parse_template(vhost_template,new_vhost,binding) if SUBTRAC_ENV != 'test' + parse_template(@APP_CONFIG[:templates][:virtual_host],"#{@APP_CONFIG[:dirs][:apache2_conf]}/#{@APP_CONFIG[:server][:hostname]}",binding) # reload apache configuration - `/etc/init.d/apache2 force-reload` if SUBTRAC_ENV != 'test' - `a2ensite #{@server_hostname}` if SUBTRAC_ENV != 'test' + `/etc/init.d/apache2 force-reload` if DEV_ENV != 'test' + `a2ensite #{@APP_CONFIG[:server][:hostname]}` if DEV_ENV != 'test' end def self.install_common_files puts "\n==== Installing common files ====" - # TODO: implement a mask for .svn folders + # TODO: implement a mash for .svn folders # TODO: refactor /common to the app config - FileUtils.cp_r(Dir.glob(File.join(subtrac_path, "common/.")),docs_dir) - FileUtils.cp_r(Dir.glob(File.join(subtrac_path, "shared/.")),create_if_missing(File.join(trac_dir, ".shared"))) - # this need to be replaced with a question/answer session - #FileUtils.cp(,@install_dir) + source = Dir.glob("#{DEV_ROOT}/common/.") + dest = @APP_CONFIG[:dirs][:document] + FileUtils.cp_r(source,dest) end - - def self.configure_admin_user - puts "\n==== Configure admin user ====" - # create admin user - passwd_file = File.join(@install_dir, ".passwd") - admin_user = ask("Pick an admin username: ") { |q| q.echo = true } - `htpasswd -c #{passwd_file} #{admin_user}` - @APP_CONFIG[:admin_user] = admin_user - # ensure this guy is added to trac admin group - @APP_CONFIG[:trac][:permissions][admin_user] = "admins" - #FileUtils.chown_R('www-data', 'www-data', passwd_file, :verbose => true) if SUBTRAC_ENV != 'test' - end - def self.create_environment_directories(overwrite=false) + def self.create_environment_directories puts "\n==== Creating new environment directories ====" - FileUtils.rm_rf @install_dir if overwrite - create_if_missing @install_dir # create the environment directories @APP_CONFIG[:dirs].each do |key, value| - dir = File.join(@install_dir,value) - create_if_missing dir + create_if_missing value end end + def self.clean + puts "\n==== Remove old data if exists ====" + @APP_CONFIG[:dirs].each do |key, value| + unless [@APP_CONFIG[:dirs][:install]].include? value + #TODO: Ask for confirmation - yes,no,All + puts "Deleting #{value}" + FileUtils.rm_rf value + end + end + end + def self.create_client(name) - puts "\n==== Create a new client called #{name} ====" + puts "\n==== Create a new client #{name} ====" client_name = name.downcase # create apache configuration - puts "subtrac_path: #{subtrac_path}" - puts "templates_location: #{@APP_CONFIG[:templates][:location]}" - location_template = File.join(subtrac_path, @APP_CONFIG[:templates][:location]) - puts "location_template: #{location_template}" - location_conf = File.join(locations_dir,"#{client_name}.conf") - puts "location_conf: #{location_conf}" - parse_template(location_template,location_conf,binding) - `/etc/init.d/apache2 force-reload` if SUBTRAC_ENV != 'test' + # create apache template + parse_template(@APP_CONFIG[:templates][:location],"#{@APP_CONFIG[:dirs][:conf_locations]}/#{client_name}.conf",binding) + `/etc/init.d/apache2 force-reload` if DEV_ENV != 'test' # create svn+trac directory - create_if_missing File.join(svn_dir,client_name) - create_if_missing File.join(trac_dir,client_name) - - # create a project for this clients trac theme - create_project("trac_theme", client_name,@APP_CONFIG[:default_theme_template]) - - # check the theme project out - client_theme_dir = File.join(trac_dir,client_name,".theme") - create_if_missing(client_theme_dir) - FileUtils.chown_R('www-data', 'www-data', client_theme_dir, :verbose => true) if SUBTRAC_ENV != 'test' - puts "Attempting checkout of theme project..." - - `sudo svn co --username #{@APP_CONFIG[:admin][:username]} --password #{@APP_CONFIG[:admin][:password]} \ - file://#{svn_dir}/#{client_name}/trac_theme/trunk #{client_theme_dir}` if SUBTRAC_ENV != 'test' - + create_if_missing "#{@APP_CONFIG[:dirs][:svn]}/#{client_name}" + create_if_missing "#{@APP_CONFIG[:dirs][:trac]}/#{client_name}" end - def self.create_project(project, client, project_type=@APP_CONFIG[:default_project_template]) - puts "\n==== Create a new project called #{project} for #{client} ====" + def self.create_project(project, client) + puts "\n==== Create a new project #{project} for #{client} ====" client_name = client.downcase project_name = project.downcase # create client directory if needed - create_client(client_name) if (!File.directory? File.join(svn_dir,client_name)) + create_client(client_name) if (!File.directory? "#{@APP_CONFIG[:dirs][:svn]}/#{client_name}") - project_svn_dir = File.join(svn_dir,client_name,project_name) - project_trac_dir = File.join(trac_dir,client_name,project_name) - - # TODO: Need to change this to use a 'groups' yml file - if (File.directory? project_svn_dir) then + svn_dir = "#{@APP_CONFIG[:dirs][:svn]}/#{client_name}/#{project_name}" + trac_dir = "#{@APP_CONFIG[:dirs][:trac]}/#{client_name}/#{project_name}" + if (File.directory? svn_dir) then raise StandardError, "A project called #{project} already exists in the #{client} repository. Would you like to replace it?" end - # create new project directories - say("Create project directories...") - create_if_missing project_svn_dir - create_if_missing project_trac_dir - - project_template = File.join(subtrac_path, @APP_CONFIG[:templates][:projects],project_type) - # copy template svn project to a temp folder, then svn import it into the repo - say("Create temporary project directory and copy template files...") - svn_template_dir = File.join(project_template,"svn") - project_temp_dir = File.join(temp_dir,project_name) - FileUtils.cp_r(svn_template_dir,project_temp_dir) + svn_template_dir = "#{@APP_CONFIG[:templates][:blank]}/svn/." + temp_dir = "#{@APP_CONFIG[:dirs][:temp]}/#{project_name}" + FileUtils.cp_r(svn_template_dir,temp_dir) # create a new subversion repository - say("Creating a new subversion repository...") - `svnadmin create #{project_svn_dir}` if SUBTRAC_ENV != 'test' + `svnadmin create #{svn_dir}` if DEV_ENV != 'test' - # import into svn - say("Importing temporary project into the new subversion repository...") - `svn import #{project_temp_dir} file:///#{project_svn_dir} --message "initial import"` if SUBTRAC_ENV != 'test' - # delete the temporary directory - FileUtils.rm_r(project_temp_dir, :force => true) + # import into svn and delete the temporary directory + `svn import #{temp_dir} file:///#{svn_dir} --message "initial import"` if DEV_ENV != 'test' + FileUtils.rm_r(temp_dir, :force => true) # create a new trac site - say("Creating a new trac site...") - result = `trac-admin #{project_trac_dir} initenv #{project_name} sqlite:#{project_trac_dir}/db/trac.db svn #{project_svn_dir}` if SUBTRAC_ENV != 'test' - FileUtils.chown_R('www-data', 'www-data', project_trac_dir, :verbose => true) if SUBTRAC_ENV != 'test' - FileUtils.mkdir_p("#{project_trac_dir}/conf") if SUBTRAC_ENV == 'test' # fake the folder for tests + `trac-admin #{trac_dir} initenv #{project_name} sqlite:#{trac_dir}/db/trac.db svn #{svn_dir}` if DEV_ENV != 'test' + FileUtils.chown_R('www-data', 'www-data', trac_dir, :verbose => true) if DEV_ENV != 'test' + FileUtils.mkdir_p("#{trac_dir}/conf") if DEV_ENV == 'test' # fake the folder for tests - say("Installing trac configuration...") # install shared trac.ini - trac_ini_template = File.join(subtrac_path, @APP_CONFIG[:templates][:trac]) - parse_template(trac_ini_template,File.join(project_trac_dir,"/conf/trac.ini"),binding) + parse_template(@APP_CONFIG[:templates][:trac],"#{trac_dir}/conf/trac.ini",binding) # remove custom templates directory so trac uses the shared location (while we wait for trac patch) - FileUtils.rm_rf("#{project_trac_dir}/templates") + FileUtils.rm_rf("#{trac_dir}/templates") - say("Setting up default trac permissions...") + puts "Setting up default trac permission..." # set up trac permissions @APP_CONFIG[:trac][:permissions].each do |key, value| - `sudo trac-admin #{project_trac_dir} permission add #{key} #{value}` if SUBTRAC_ENV != 'test' + `trac-admin #{trac_dir} permission add #{key} #{value}` if DEV_ENV != 'test' end - say("Adding default trac wiki pages...") - # loop through the directory and import all pages - Dir.foreach("#{project_template}/trac/wiki/.") do |file| + puts "Adding default trac wiki pages..." + # this needs to loop through the directory and import all pages + Dir.foreach("#{DEV_ROOT}/#{@APP_CONFIG[:default_project_template]}/trac/wiki/.") do |file| # do something with the file here unless ['.', '..','.svn'].include? file - temp_file = File.join(temp_dir,file) - puts = binding - parse_template(File.join(project_template,"trac/wiki",file), temp_file, binding) - `trac-admin #{project_trac_dir} wiki import #{file} #{temp_file}` if SUBTRAC_ENV != 'test' - FileUtils.rm(temp_file) + parse_template("#{DEV_ROOT}/#{@APP_CONFIG[:default_project_template]}/trac/wiki/#{file}","#{@APP_CONFIG[:dirs][:temp]}/#{file}", binding) + `trac-admin #{trac_dir} wiki import #{file} #{@APP_CONFIG[:dirs][:temp]}/#{file}` if DEV_ENV != 'test' + FileUtils.rm("#{@APP_CONFIG[:dirs][:temp]}/#{file}") end end - - # run trac upgrade - say("Upgrading the trac installation...") - `trac-admin #{project_trac_dir} upgrade` if SUBTRAC_ENV != 'test' - end + end