capricorn 0.2.00

Sign up to get free protection for your applications and to get access to all the features.
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