capricorn 0.2.00

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. data/app_generators/engine/engine_generator.rb +39 -0
  2. data/app_generators/engine/templates/Gmfile +20 -0
  3. data/app_generators/engine/templates/MIT-LICENSE.txt +20 -0
  4. data/app_generators/engine/templates/README.rdoc +7 -0
  5. data/app_generators/engine/templates/config/routes.rb +2 -0
  6. data/app_generators/engine/templates/gitignore +3 -0
  7. data/app_generators/engine/templates/init.rb +1 -0
  8. data/app_generators/engine/templates/lib/engine.rb +1 -0
  9. data/app_generators/engine/templates/rails/init.rb +1 -0
  10. data/app_generators/engine/templates/tasks/engine_tasks.rake +4 -0
  11. data/bin/capricorn +20 -0
  12. data/lib/capricorn.rb +100 -0
  13. data/lib/capricorn/actor.rb +23 -0
  14. data/lib/capricorn/actor/actions.rb +76 -0
  15. data/lib/capricorn/actors/apache_actor.rb +56 -0
  16. data/lib/capricorn/actors/base_actor.rb +276 -0
  17. data/lib/capricorn/actors/mysql_actor.rb +20 -0
  18. data/lib/capricorn/actors/passenger_actor.rb +19 -0
  19. data/lib/capricorn/actors/plesk_actor.rb +210 -0
  20. data/lib/capricorn/actors/sqlite3_actor.rb +44 -0
  21. data/lib/capricorn/app_runner.rb +119 -0
  22. data/lib/capricorn/apps/dev.rb +15 -0
  23. data/lib/capricorn/apps/engines.rb +33 -0
  24. data/lib/capricorn/apps/jobs.rb +35 -0
  25. data/lib/capricorn/apps/satellite.rb +32 -0
  26. data/lib/capricorn/apps/server.rb +67 -0
  27. data/lib/capricorn/client.rb +48 -0
  28. data/lib/capricorn/client/auth_token.rb +98 -0
  29. data/lib/capricorn/daemon.rb +71 -0
  30. data/lib/capricorn/exception_handler.rb +79 -0
  31. data/lib/capricorn/extentions/rubygems_plugin.rb +27 -0
  32. data/lib/capricorn/extentions/thor_extentions.rb +32 -0
  33. data/lib/capricorn/job_queue.rb +199 -0
  34. data/lib/capricorn/satellite.rb +50 -0
  35. data/lib/capricorn/satellite/actions.rb +35 -0
  36. data/lib/capricorn/satellite/dependency_loader.rb +78 -0
  37. data/lib/capricorn/satellite/persistence.rb +50 -0
  38. data/lib/capricorn/server.rb +122 -0
  39. data/lib/capricorn/server/daemon.rb +88 -0
  40. data/lib/capricorn/server/proxy.rb +25 -0
  41. data/lib/capricorn/server/security.rb +113 -0
  42. data/lib/capricorn/system.rb +184 -0
  43. data/lib/capricorn/system/config.rb +49 -0
  44. data/lib/capricorn/system/helper.rb +21 -0
  45. data/lib/capricorn/system/options.rb +79 -0
  46. data/lib/capricorn/system/process_user.rb +73 -0
  47. data/lib/capricorn/system/satellites.rb +44 -0
  48. data/lib/capricorn/system/shell.rb +80 -0
  49. data/lib/rubygems_plugin.rb +1 -0
  50. data/spec/actor/actions_spec.rb +13 -0
  51. data/spec/spec_helper.rb +1 -0
  52. metadata +108 -0
@@ -0,0 +1,39 @@
1
+ class EngineGenerator < RubiGen::Base
2
+ attr_reader :engine_name
3
+
4
+ def initialize(runtime_args, runtime_options = {})
5
+ super
6
+ @destination_root = args.shift
7
+ @engine_name = File.basename(File.expand_path(@destination_root)).underscore
8
+ end
9
+
10
+ def manifest
11
+ record do |m|
12
+
13
+ m.directory "app/controllers"
14
+ m.directory "app/models"
15
+ m.directory "app/views"
16
+ m.directory "app/helpers"
17
+ m.directory "config"
18
+ m.directory "db/migrate"
19
+ m.directory "lib"
20
+ m.directory "public/images"
21
+ m.directory "public/javascripts"
22
+ m.directory "public/stylesheets"
23
+ m.directory "rails"
24
+ m.directory "tasks"
25
+
26
+ m.template('config/routes.rb', "config/routes.rb")
27
+ m.template('Gmfile', "Gmfile")
28
+ m.template('rails/init.rb', "rails/init.rb")
29
+ m.template('init.rb', "init.rb")
30
+ m.template('tasks/engine_tasks.rake', "tasks/#{engine_name}_tasks.rake")
31
+ m.template('README.rdoc', "README.rdoc")
32
+ m.template('MIT-LICENSE.txt', "MIT-LICENSE.txt")
33
+ m.template('lib/engine.rb', "lib/#{engine_name}.rb")
34
+ m.template('gitignore', ".gitignore")
35
+
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,20 @@
1
+ specify do |s|
2
+ s.name = %q{<%= engine_name %>}
3
+ s.version = "0.0.1"
4
+ s.summary = %q{Fix this}
5
+ s.homepage = %q{Fix this}
6
+
7
+ s.author = "Fix this"
8
+ s.email = %q{Fix this}
9
+
10
+ s.ignore_files %r{^public/(\d{3}|index)\.html$}
11
+ s.ignore_files %r{^public/favicon.ico$}
12
+ s.ignore_files %r{^public/robots.txt$}
13
+ s.ignore_files %r{^public/images/rails\.png$}
14
+ s.ignore_files %r{^lib/tasks}
15
+ s.ignore_files %r{^config/(boot|database|environment|initializers|locales)}
16
+ s.ignore_files %r{^app/controllers/application_controller.rb}
17
+ s.ignore_files %r{^app/helpers/application_helper.rb}
18
+ s.ignore_files %r{^db/schema.rb}
19
+ s.ignore_files %r{^public/system}
20
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 [AUTHOR]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,7 @@
1
+ = <%= engine_name.humanize %>
2
+
3
+
4
+ == Example
5
+
6
+
7
+ Copyright (c) 2009 [AUTHOR], released under the MIT license
@@ -0,0 +1,2 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ end
@@ -0,0 +1,3 @@
1
+ *.gem
2
+ rdoc
3
+ .DS_Store
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__)+'/rails/init'
@@ -0,0 +1 @@
1
+ # <%= engine_name.camelize %>
@@ -0,0 +1 @@
1
+ # Include hook code here
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :<%= engine_name %> do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ begin
3
+ require File.dirname(__FILE__)+'/../lib/capricorn'
4
+ rescue LoadError
5
+ require 'rubygems'
6
+ require 'capricorn'
7
+ end
8
+
9
+ module Capricorn
10
+ BIN_PATH = File.expand_path($PROGRAM_NAME)
11
+ ORIGINAL_ARGV = ARGV.dup
12
+ end
13
+
14
+ Capricorn::AppRunner.use :Server
15
+ Capricorn::AppRunner.use :Satellite
16
+ Capricorn::AppRunner.use :Engines
17
+ Capricorn::AppRunner.use :Jobs
18
+ Capricorn::AppRunner.use :Dev
19
+ Capricorn::AppRunner.namespace = 'capricorn:apps'
20
+ Capricorn::AppRunner.start
@@ -0,0 +1,100 @@
1
+ require 'rubygems'
2
+
3
+ autoload :URI, 'uri'
4
+ autoload :Etc, 'etc'
5
+ autoload :DRb, 'drb'
6
+ autoload :TSort, 'tsort'
7
+ autoload :Logger, 'logger'
8
+ autoload :OpenSSL, 'drb/ssl'
9
+ autoload :FileUtils, 'fileutils'
10
+ autoload :DRbUndumped, 'drb'
11
+
12
+ module Capricorn
13
+ base = File.expand_path(File.dirname(__FILE__))
14
+
15
+ autoload :Actor, (base+'/capricorn/actor')
16
+ autoload :Server, (base+'/capricorn/server')
17
+ autoload :Client, (base+'/capricorn/client')
18
+ autoload :System, (base+'/capricorn/system')
19
+ autoload :Daemon, (base+'/capricorn/daemon')
20
+ autoload :JobQueue, (base+'/capricorn/job_queue')
21
+ autoload :Satellite, (base+'/capricorn/satellite')
22
+ autoload :AppRunner, (base+'/capricorn/app_runner')
23
+ autoload :ExceptionHandler, (base+'/capricorn/exception_handler')
24
+
25
+ module Actors
26
+ base = File.expand_path(File.dirname(__FILE__))
27
+
28
+ autoload :BaseActor, (base+'/capricorn/actors/base_actor')
29
+ autoload :MysqlActor, (base+'/capricorn/actors/mysql_actor')
30
+ autoload :PleskActor, (base+'/capricorn/actors/plesk_actor')
31
+ autoload :ApacheActor, (base+'/capricorn/actors/apache_actor')
32
+ autoload :Sqlite3Actor, (base+'/capricorn/actors/sqlite3_actor')
33
+ autoload :PassengerActor, (base+'/capricorn/actors/passenger_actor')
34
+ end
35
+
36
+ module Apps
37
+ base = File.expand_path(File.dirname(__FILE__))
38
+
39
+ autoload :Dev, (base+'/capricorn/apps/dev')
40
+ autoload :Jobs, (base+'/capricorn/apps/jobs')
41
+ autoload :Server, (base+'/capricorn/apps/server')
42
+ autoload :Engines, (base+'/capricorn/apps/engines')
43
+ autoload :Satellite, (base+'/capricorn/apps/satellite')
44
+ end
45
+
46
+ DEFAULT_ROOT_SYSTEM_DIR = '/var/capricorn'
47
+ DEFAULT_USER_SYSTEM_DIR = '~/.capricorn'
48
+ STOP_STATUS = 101
49
+ RESTART_STATUS = 102
50
+ RELOAD_STATUS = 103
51
+ QUICK_CERT = "http://segment7.net/projects/ruby/QuickCert/QuickCert-1.0.2.tar.gz"
52
+
53
+ THOR_VERSION = '>= 0.9.9'
54
+ RUBIGEN_VERSION = '>= 1.5.2'
55
+
56
+ Capricorn::ExceptionHandler.setup
57
+ extend ExceptionHandler
58
+
59
+ def self.client(token=nil)
60
+ unless @client
61
+ @client = Capricorn::Client.current(token)
62
+ unless @client
63
+ puts "Failed to connect to the capricorn!"
64
+ exit(1)
65
+ end
66
+ end
67
+ @client
68
+ end
69
+
70
+ def self.system
71
+ @system ||= Capricorn::System.shared
72
+ end
73
+
74
+ def self.version
75
+ unless @version
76
+ if __FILE__ =~ /\/capricorn-([^\/]+)\//
77
+ @version = $1
78
+ else
79
+ @version = 'edge'
80
+ end
81
+ end
82
+ @version
83
+ end
84
+
85
+ def self.server?(value=nil)
86
+ @is_server = value unless value.nil?
87
+ @is_server
88
+ end
89
+
90
+ def self.runtime_gem(gem, version='>= 0.0.0', lib=nil)
91
+ begin
92
+ gem(gem, version)
93
+ require(lib || gem)
94
+ rescue LoadError
95
+ puts "You must install #{gem} (#{version}) to use this.\nPlease run: [sudo] gem install #{gem}"
96
+ exit(1)
97
+ end
98
+ end
99
+
100
+ end
@@ -0,0 +1,23 @@
1
+
2
+ module Capricorn
3
+
4
+ # The actor class provides the mechanisme for scheduling the execution of seperate tasks.
5
+ class Actor
6
+
7
+ autoload :Actions, File.dirname(__FILE__)+'/actor/actions'
8
+
9
+ include Capricorn::Actor::Actions
10
+
11
+ attr_reader :system, :satellite
12
+
13
+ action :install_satellite, :uninstall_satellite, :link_satellite
14
+ action :install_engine, :uninstall_engine, :update_engine
15
+
16
+ # create a new actor for the provided system and satellite
17
+ def initialize(system, satellite)
18
+ @system = system
19
+ @satellite = satellite
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,76 @@
1
+
2
+ module Capricorn
3
+ class Actor
4
+ module Actions
5
+
6
+ def self.included(base)
7
+ base.extend Capricorn::Actor::Actions::ClassMethods
8
+ end
9
+
10
+ # run the callbacks registerd to <tt>action</tt>. the will run the <tt>before</tt>, <tt>on</tt> and <tt>after</tt> fases.
11
+ def run_callbacks!(action)
12
+ action = action.to_sym
13
+ run_callbacks_in_fase! action, :before
14
+ run_callbacks_in_fase! action, :on
15
+ run_callbacks_in_fase! action, :after
16
+ end
17
+
18
+ # run the callbacks registerd to <tt>action</tt> in the +fase+
19
+ def run_callbacks_in_fase!(action, fase)
20
+ action = action.to_sym
21
+ fase = fase.to_sym
22
+ self.class.methods_for(action, fase).each { |meth| self.send(meth) }
23
+ end
24
+
25
+ module ClassMethods
26
+
27
+ # register a callback to be run <tt>before</tt> the <tt>action</tt>.
28
+ def before(action, meth)
29
+ methods_for(action, :before).push(meth.to_sym)
30
+ end
31
+
32
+ # register a callback to be run <tt>on</tt> the <tt>action</tt>.
33
+ def on(action, meth)
34
+ methods_for(action, :on).push(meth.to_sym)
35
+ end
36
+
37
+ # register a callback to be run <tt>after</tt> the <tt>action</tt>.
38
+ def after(action, meth)
39
+ methods_for(action, :after).push(meth.to_sym)
40
+ end
41
+
42
+ # get the registered callbacks for the +action+ and +face+.
43
+ def methods_for(action, fase)
44
+ action = action.to_sym
45
+ fase = fase.to_sym
46
+
47
+ @actions ||= {}
48
+ @actions[action] ||= {}
49
+ @actions[action][fase] ||= []
50
+ @actions[action][fase]
51
+ end
52
+
53
+ # define one or more actions.
54
+ def action(*names)
55
+ names.each do |name|
56
+ module_eval %{
57
+ def self.before_#{name}(meth)
58
+ before(:#{name}, meth)
59
+ end
60
+ def self.on_#{name}(meth)
61
+ on(:#{name}, meth)
62
+ end
63
+ def self.after_#{name}(meth)
64
+ after(:#{name}, meth)
65
+ end
66
+ def run_#{name}_callbacks!
67
+ run_callbacks!(:#{name})
68
+ end
69
+ }
70
+ end
71
+ end
72
+
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,56 @@
1
+
2
+ module Capricorn
3
+ module Actors # :nodoc:
4
+ class ApacheActor < Capricorn::Actor
5
+
6
+ on_install_satellite :write_config_file
7
+ after_install_satellite :restart
8
+
9
+ on_uninstall_satellite :remove_config_file
10
+ after_uninstall_satellite :restart
11
+
12
+ # restart the apache server
13
+ def restart
14
+ system.run "#{system.apachectl_path} -k restart"
15
+ end
16
+
17
+ # write the vhost config file (needs apache restart)
18
+ def write_config_file
19
+ config = %{<VirtualHost *>
20
+ ServerName #{satellite.domain}
21
+
22
+ ErrorLog logs/#{satellite.domain}.error.log
23
+ CustomLog logs/#{satellite.domain}.access.log common
24
+ DocumentRoot #{system.satellite_root}/public
25
+ <Directory "#{system.satellite_root}/public">
26
+ Options All
27
+ AllowOverride All
28
+ Order allow,deny
29
+ Allow from all
30
+ </Directory>
31
+ </VirtualHost>}
32
+ File.open(system.apache_conf_path, 'w+') { |f| f.write config }
33
+ end
34
+
35
+ # remove the vhost config file (needs apache restart)
36
+ def remove_config_file
37
+ File.unlink(system.apache_conf_path) if File.exist? system.apache_conf_path
38
+ end
39
+
40
+ module Config
41
+
42
+ # path to the apachectl tool
43
+ def apachectl_path(&block)
44
+ option(:apachectl_path, block) { |v| v or find_bin('apache2ctl', 'apachectl') }
45
+ end
46
+
47
+ # path to the vhost specific config files
48
+ def apache_conf_path(&block)
49
+ satellite_option(:apache_conf_path, block) { |s,v| v or "/opt/local/apache2/conf/apps/#{s.domain}.conf" }
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,276 @@
1
+
2
+ module Capricorn
3
+ module Actors # :nodoc:
4
+ class BaseActor < Capricorn::Actor
5
+
6
+ on_install_satellite :create_rails_app
7
+ on_link_satellite :link_engines
8
+ on_uninstall_satellite :destroy_rails_app
9
+
10
+ # create a new rails app for the current satellite
11
+ def create_rails_app
12
+ system.as_user(system.web_user, system.web_group) do
13
+ FileUtils.mkdir_p(File.dirname(system.satellite_root), :verbose => true)
14
+ FileUtils.mkdir_p(system.shared_root, :verbose => true)
15
+ end
16
+
17
+ Dir.chdir(File.dirname(system.satellite_root)) do
18
+ system.user_run system.web_user, "rails --force #{system.satellite_root}"
19
+ end
20
+
21
+ system.as_user(system.web_user, system.web_group) do
22
+ Dir.chdir(File.dirname(system.satellite_root)) do
23
+ link(File.join(system.shared_root, 'public'),
24
+ File.join(system.satellite_root, 'public', 'system'))
25
+ link(File.join(system.shared_root, 'private'),
26
+ File.join(system.satellite_root, 'db', 'system'))
27
+ link(File.join(system.shared_root, 'log'),
28
+ File.join(system.satellite_root, 'log'))
29
+ link(File.join(system.shared_root, 'settings'),
30
+ File.join(system.satellite_root, 'config', 'settings'))
31
+ end
32
+
33
+ end
34
+ end
35
+
36
+ # destroy the rails app for the current satellite
37
+ def destroy_rails_app
38
+ FileUtils.rm_rf system.satellite_root, :verbose => true
39
+ end
40
+
41
+ # link the required engines for the current satellite
42
+ def link_engines
43
+ Dir.chdir(system.satellite_root) do
44
+ system.as_user(system.web_user, system.web_group) do
45
+
46
+ write_environment
47
+ clean_links
48
+ @dependecies.reverse_each do |spec|
49
+ link_engine(spec)
50
+ end
51
+
52
+ end
53
+ run_migrations
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def link(src, dst)
60
+ FileUtils.mkdir_p(File.dirname(dst), :verbose => true)
61
+ FileUtils.mkdir_p(src, :verbose => true)
62
+ FileUtils.rm_rf dst, :verbose => true
63
+ FileUtils.symlink(src, dst, :verbose => true)
64
+ end
65
+
66
+ def write_environment
67
+ @dependecies = Capricorn::Satellite::DependencyLoader.load_for(satellite.engines)
68
+ @dependecies.engines
69
+
70
+ rails_header = "Rails::Initializer.run do |config|\n"
71
+ gems_header = " # Gems added by engine_manager:\n \n"
72
+
73
+ gsub_file('config/environment.rb') do |content|
74
+ content.gsub! /^\s*config.gem.+\n/, ''
75
+ content.gsub! %r{#{Regexp.escape(rails_header)}(#{Regexp.escape(gems_header)})?},
76
+ "#{rails_header}#{gems_header}"
77
+
78
+ @dependecies.reverse_each do |spec|
79
+ gem_options = @dependecies.engines[spec.name] || {}
80
+ content.gsub! "engine_manager:\n",
81
+ "engine_manager:\n config.gem #{spec.name.inspect}, #{gem_options.inspect}\n"
82
+ end
83
+ end
84
+ end
85
+
86
+ def link_engine(spec)
87
+ Capricorn.log "linking: #{spec.name}..."
88
+ path = File.join(spec.full_gem_path, 'public')
89
+ if File.directory?(path)
90
+ FileUtils.mkdir_p('public/vendor', :verbose => true)
91
+ FileUtils.ln_s(path, "public/vendor/#{spec.name}", :verbose => true)
92
+ end
93
+
94
+ path = File.join(spec.full_gem_path, 'tasks')
95
+ if File.directory?(path)
96
+ FileUtils.mkdir_p("lib/tasks/vendor/#{spec.name}", :verbose => true)
97
+ Dir.glob("#{path}/*.rake").each do |rake_file|
98
+ FileUtils.ln_s(rake_file,
99
+ "lib/tasks/vendor/#{spec.name}/#{File.basename(rake_file)}", :verbose => true)
100
+ end
101
+ end
102
+
103
+ path = File.join(spec.full_gem_path, 'db', 'migrate')
104
+ if File.directory?(path)
105
+ FileUtils.mkdir_p("db/migrate", :verbose => true)
106
+ unlinked_migrations.concat(Dir.glob("#{path}/*.rb"))
107
+ linked_migrations.each do |migration, target|
108
+ if target.starts_with? spec.full_gem_path
109
+ unlinked_migrations.delete(target)
110
+ unused_migrations.delete(migration)
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ def clean_links
117
+ FileUtils.rm_rf("lib/tasks/vendor", :verbose => true)
118
+ FileUtils.rm_rf("public/vendor", :verbose => true)
119
+ end
120
+
121
+ def run_migrations
122
+ Capricorn.log "running your migrations..." unless unlinked_migrations.empty? and unused_migrations.empty?
123
+
124
+ unlinked_migration_targets = unlinked_migrations.collect{ |migration|
125
+ File.basename(migration) }
126
+
127
+ unused_migrations.each do |migration, target|
128
+ unless unlinked_migration_targets.include? File.basename(migration)
129
+ migration =~ /(\d+)_[^.]+\.rb/
130
+ system.user_run(system.web_user, "cd #{system.satellite_root} ; rake db:migrate:down RAILS_ENV=#{system.rails_environment} VERSION=#{$1}")
131
+ end
132
+ FileUtils.rm_rf(migration, :verbose => true)
133
+ end
134
+ system.as_user(system.web_user, system.web_group) do
135
+ unlinked_migrations.each do |migration|
136
+ FileUtils.ln_s(migration, "db/migrate/#{File.basename(migration)}", :verbose => true)
137
+ end
138
+ end
139
+
140
+ unless unlinked_migrations.empty?
141
+ system.user_run(system.web_user, "cd #{system.satellite_root} ; rake db:migrate RAILS_ENV=#{system.rails_environment}")
142
+ end
143
+ end
144
+
145
+ def gsub_file(path, pattern=nil, replace=nil, &block)
146
+ if File.exist? path
147
+ content = File.read(path)
148
+ if block
149
+ block.call(content)
150
+ else
151
+ return false unless content.gsub!(pattern, replace)
152
+ end
153
+ File.open(path, 'w+') { |f| f.write content }
154
+ end
155
+ end
156
+
157
+ def linked_migrations
158
+ @linked_migrations ||= Dir.glob('db/migrate/*.rb').select { |migration| File.symlink?(migration) }.inject({}) { |m, migration| m[migration] = File.readlink(migration) ; m }
159
+ end
160
+
161
+ def unused_migrations
162
+ @unused_migrations ||= linked_migrations.dup
163
+ end
164
+
165
+ def unlinked_migrations
166
+ @unlinked_migrations ||= []
167
+ end
168
+
169
+ module Helper
170
+
171
+ # install a gem.
172
+ def gem_install(name, options={})
173
+ gem_cmd('install', name, options)
174
+ end
175
+
176
+ # check if a gem is installed
177
+ def gem_installed(name, options)
178
+ version = options[:version] || '0.0.0'
179
+ options = { :version => version, :installed => true }
180
+ (gem_cmd('list', name, options).strip == 'true')
181
+ end
182
+
183
+ # update a gem
184
+ def gem_update(name, options={})
185
+ !(gem_cmd('update', name, options) =~ /Nothing to update/)
186
+ end
187
+
188
+ # ensure the presence of a gem
189
+ def ensure_presence_of_gem(name, options={})
190
+ if !gem_installed(name, options)
191
+ gem_install(name, options)
192
+ end
193
+ end
194
+
195
+ private
196
+
197
+ def gem_cmd(cmd, args, options={})
198
+ user = options.delete(:user)
199
+ user ||= (install_gems_with_web_user ? web_user : system_user)
200
+
201
+ args = [args].flatten.compact
202
+ args.collect! { |a| (a and a.inspect) || '' }
203
+ args += options.map do |k,v|
204
+ if TrueClass === v
205
+ "--#{k}"
206
+ else
207
+ "--#{k}=#{v.inspect}"
208
+ end
209
+ end
210
+ output = user_run(user, "#{gem_bin_path} #{cmd} #{args.join(' ')}")
211
+ Gem.refresh
212
+ output
213
+ end
214
+
215
+ end
216
+
217
+ module Config
218
+
219
+ # set the path to the ruby executable.
220
+ def ruby_path(&block)
221
+ option(:ruby_path, block) { |s, v| v or find_bin('ruby', 'ruby1.8', 'ruby18') }
222
+ end
223
+
224
+ # set the path to the gem executable.
225
+ def gem_bin_path(&block)
226
+ option(:gem_bin_path, block) { |s, v| v or find_bin('gem', 'gem1.8', 'gem18') }
227
+ end
228
+
229
+ # set the path to the rails executable.
230
+ def rails_path(&block)
231
+ option(:rails_path, block) do |v|
232
+ user = (install_gems_with_web_user ? web_user : system_user)
233
+ v or user_find_bin(user, 'rails')
234
+ end
235
+ end
236
+
237
+ # set the owner group of the current satellite.
238
+ def web_group(&block)
239
+ satellite_option(:web_group, block)
240
+ end
241
+
242
+ # set the owner of the current satellite.
243
+ def web_user(&block)
244
+ satellite_option(:web_user, block)
245
+ end
246
+
247
+ # set the system user (the user which runs the capricorn server).
248
+ def system_user(&block)
249
+ option(:system_user, block) { |v| v or 'root' }
250
+ end
251
+
252
+ # set whether gems should be installed with the web user.
253
+ def install_gems_with_web_user(&block)
254
+ option(:install_gems_with_web_user, block)
255
+ end
256
+
257
+ # set the path to the satellite's root path
258
+ def satellite_root(&block)
259
+ satellite_option(:satellite_root, block)
260
+ end
261
+
262
+ # set the path to the satellite's shared path
263
+ def shared_root(&block)
264
+ satellite_option(:shared_root, block)
265
+ end
266
+
267
+ # set the rails environment.
268
+ def rails_environment(&block)
269
+ satellite_option(:rails_environment, block) { |s,v| v or 'development' }
270
+ end
271
+
272
+ end
273
+
274
+ end
275
+ end
276
+ end