engineyard-serverside 1.6.5 → 1.7.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/engineyard-serverside.rb +2 -0
- data/lib/engineyard-serverside/cli.rb +83 -48
- data/lib/engineyard-serverside/configuration.rb +85 -18
- data/lib/engineyard-serverside/deploy.rb +105 -91
- data/lib/engineyard-serverside/deploy_hook.rb +22 -20
- data/lib/engineyard-serverside/deprecation.rb +9 -17
- data/lib/engineyard-serverside/future.rb +10 -4
- data/lib/engineyard-serverside/futures/celluloid.rb +3 -13
- data/lib/engineyard-serverside/futures/dataflow.rb +8 -13
- data/lib/engineyard-serverside/lockfile_parser.rb +1 -1
- data/lib/engineyard-serverside/rails_asset_support.rb +26 -10
- data/lib/engineyard-serverside/server.rb +17 -12
- data/lib/engineyard-serverside/shell.rb +98 -0
- data/lib/engineyard-serverside/shell/formatter.rb +71 -0
- data/lib/engineyard-serverside/shell/helpers.rb +29 -0
- data/lib/engineyard-serverside/strategies/git.rb +33 -63
- data/lib/engineyard-serverside/task.rb +34 -13
- data/lib/engineyard-serverside/version.rb +1 -1
- data/spec/basic_deploy_spec.rb +15 -50
- data/spec/bundler_deploy_spec.rb +3 -44
- data/spec/configuration_spec.rb +72 -0
- data/spec/custom_deploy_spec.rb +3 -4
- data/spec/deploy_hook_spec.rb +210 -162
- data/spec/deprecation_spec.rb +4 -26
- data/spec/ey_yml_customized_deploy_spec.rb +68 -0
- data/spec/fixtures/repos/assets_disabled/Gemfile +6 -0
- data/spec/fixtures/repos/assets_disabled/Gemfile.lock +90 -0
- data/spec/fixtures/repos/assets_disabled/README +1 -0
- data/spec/fixtures/repos/assets_disabled/Rakefile +5 -0
- data/spec/fixtures/repos/assets_disabled/config/application.rb +5 -0
- data/spec/fixtures/repos/assets_disabled_in_ey_yml/Gemfile +6 -0
- data/spec/fixtures/repos/assets_disabled_in_ey_yml/Gemfile.lock +90 -0
- data/spec/fixtures/repos/assets_disabled_in_ey_yml/README +1 -0
- data/spec/fixtures/repos/assets_disabled_in_ey_yml/Rakefile +5 -0
- data/spec/fixtures/repos/assets_disabled_in_ey_yml/config/application.rb +5 -0
- data/spec/fixtures/repos/assets_disabled_in_ey_yml/config/ey.yml +4 -0
- data/spec/fixtures/repos/assets_enabled/Gemfile +6 -0
- data/spec/fixtures/repos/assets_enabled/Gemfile.lock +90 -0
- data/spec/fixtures/repos/assets_enabled/README +1 -0
- data/spec/fixtures/repos/assets_enabled/Rakefile +5 -0
- data/spec/fixtures/repos/assets_enabled/config/application.rb +5 -0
- data/spec/fixtures/repos/assets_enabled_in_ey_yml/README +1 -0
- data/spec/fixtures/repos/assets_enabled_in_ey_yml/Rakefile +5 -0
- data/spec/fixtures/repos/assets_enabled_in_ey_yml/config/ey.yml +4 -0
- data/spec/fixtures/repos/assets_in_hook/Gemfile +6 -0
- data/spec/fixtures/repos/assets_in_hook/Gemfile.lock +90 -0
- data/spec/fixtures/repos/assets_in_hook/README +2 -0
- data/spec/fixtures/repos/assets_in_hook/Rakefile +5 -0
- data/spec/fixtures/repos/assets_in_hook/config/application.rb +5 -0
- data/spec/fixtures/repos/assets_in_hook/deploy/before_migrate.rb +1 -0
- data/spec/fixtures/repos/default/Gemfile +5 -0
- data/spec/fixtures/repos/default/Gemfile.lock +14 -0
- data/spec/fixtures/repos/default/README +5 -0
- data/spec/fixtures/repos/ey_yml/Gemfile +4 -0
- data/spec/fixtures/repos/ey_yml/Gemfile.lock +12 -0
- data/spec/fixtures/repos/ey_yml/README +1 -0
- data/spec/fixtures/repos/ey_yml/config/ey.yml +12 -0
- data/spec/fixtures/repos/ey_yml/deploy/before_migrate.rb +6 -0
- data/spec/fixtures/repos/ey_yml_alt/Gemfile +4 -0
- data/spec/fixtures/repos/ey_yml_alt/Gemfile.lock +12 -0
- data/spec/fixtures/repos/ey_yml_alt/README +1 -0
- data/spec/fixtures/repos/ey_yml_alt/deploy/before_migrate.rb +6 -0
- data/spec/fixtures/repos/ey_yml_alt/ey.yml +12 -0
- data/spec/fixtures/repos/hook_fails/README +1 -0
- data/spec/fixtures/repos/hook_fails/deploy/before_migrate.rb +1 -0
- data/spec/fixtures/repos/hooks/README +1 -0
- data/spec/fixtures/repos/hooks/deploy/after_bundle.rb +1 -0
- data/spec/fixtures/repos/hooks/deploy/after_compile_assets.rb +1 -0
- data/spec/fixtures/repos/hooks/deploy/after_migrate.rb +1 -0
- data/spec/fixtures/repos/hooks/deploy/after_restart.rb +1 -0
- data/spec/fixtures/repos/hooks/deploy/after_symlink.rb +1 -0
- data/spec/fixtures/repos/hooks/deploy/before_bundle.rb +1 -0
- data/spec/fixtures/repos/hooks/deploy/before_compile_assets.rb +1 -0
- data/spec/fixtures/repos/hooks/deploy/before_migrate.rb +1 -0
- data/spec/fixtures/repos/hooks/deploy/before_restart.rb +1 -0
- data/spec/fixtures/repos/hooks/deploy/before_symlink.rb +1 -0
- data/spec/fixtures/repos/no_ey_config/Gemfile +4 -0
- data/spec/fixtures/repos/no_ey_config/Gemfile.lock +12 -0
- data/spec/fixtures/repos/no_ey_config/README +1 -0
- data/spec/fixtures/repos/no_gemfile_lock/Gemfile +5 -0
- data/spec/fixtures/repos/no_gemfile_lock/README +1 -0
- data/spec/fixtures/repos/nodejs/README +1 -0
- data/spec/fixtures/repos/nodejs/package.json +7 -0
- data/spec/fixtures/repos/not_bundled/README +1 -0
- data/spec/fixtures/{gemfiles/1.0.21-rails-31-with-sqlite → repos/sqlite3/Gemfile} +0 -0
- data/spec/fixtures/{lockfiles/1.0.21-rails-31-with-sqlite → repos/sqlite3/Gemfile.lock} +0 -0
- data/spec/fixtures/repos/sqlite3/README +1 -0
- data/spec/git_strategy_spec.rb +11 -2
- data/spec/lockfile_parser_spec.rb +8 -3
- data/spec/nodejs_deploy_spec.rb +1 -26
- data/spec/rails31_deploy_spec.rb +23 -31
- data/spec/services_deploy_spec.rb +41 -100
- data/spec/shell_spec.rb +50 -0
- data/spec/spec_helper.rb +80 -66
- data/spec/sqlite3_deploy_spec.rb +10 -16
- data/spec/support/integration.rb +45 -139
- metadata +233 -78
- data/lib/engineyard-serverside/logged_output.rb +0 -91
- data/spec/logged_output_spec.rb +0 -55
@@ -1,41 +1,51 @@
|
|
1
|
+
require 'engineyard-serverside/shell/helpers'
|
2
|
+
|
1
3
|
module EY
|
2
4
|
module Serverside
|
3
5
|
class DeployHook < Task
|
4
|
-
def initialize(options)
|
5
|
-
super(EY::Serverside::Deploy::Configuration.new(options))
|
6
|
-
end
|
7
|
-
|
8
6
|
def callback_context
|
9
|
-
@context ||= CallbackContext.new(config)
|
7
|
+
@context ||= CallbackContext.new(config, shell)
|
10
8
|
end
|
11
9
|
|
12
10
|
def run(hook)
|
13
11
|
hook_path = "#{c.release_path}/deploy/#{hook}.rb"
|
14
12
|
if File.exist?(hook_path)
|
15
13
|
Dir.chdir(c.release_path) do
|
16
|
-
puts "~> running deploy hook: deploy/#{hook}.rb"
|
17
14
|
if desc = syntax_error(hook_path)
|
18
15
|
hook_name = File.basename(hook_path)
|
19
16
|
abort "*** [Error] Invalid Ruby syntax in hook: #{hook_name} ***\n*** #{desc.chomp} ***"
|
20
17
|
else
|
21
|
-
|
18
|
+
eval_hook(IO.read(hook_path))
|
22
19
|
end
|
23
20
|
end
|
24
21
|
end
|
25
22
|
end
|
26
23
|
|
24
|
+
def eval_hook(code)
|
25
|
+
callback_context.instance_eval(code)
|
26
|
+
end
|
27
|
+
|
27
28
|
def syntax_error(file)
|
28
29
|
output = `ruby -c #{file} 2>&1`
|
29
30
|
output unless output =~ /Syntax OK/
|
30
31
|
end
|
31
32
|
|
32
33
|
class CallbackContext
|
33
|
-
|
34
|
+
include EY::Serverside::Shell::Helpers
|
35
|
+
|
36
|
+
attr_reader :shell
|
37
|
+
|
38
|
+
def initialize(config, shell)
|
34
39
|
@configuration = config
|
35
40
|
@configuration.set_framework_envs
|
41
|
+
@shell = shell
|
36
42
|
@node = node
|
37
43
|
end
|
38
44
|
|
45
|
+
def config
|
46
|
+
@configuration
|
47
|
+
end
|
48
|
+
|
39
49
|
def method_missing(meth, *args, &blk)
|
40
50
|
if @configuration.respond_to?(meth)
|
41
51
|
@configuration.send(meth, *args, &blk)
|
@@ -44,24 +54,16 @@ module EY
|
|
44
54
|
end
|
45
55
|
end
|
46
56
|
|
47
|
-
def respond_to?(
|
48
|
-
@configuration.respond_to?(
|
57
|
+
def respond_to?(*a)
|
58
|
+
@configuration.respond_to?(*a) || super
|
49
59
|
end
|
50
60
|
|
51
61
|
def run(cmd)
|
52
|
-
|
62
|
+
shell.logged_system(Escape.shell_command(["sh", "-l", "-c", cmd])).success?
|
53
63
|
end
|
54
64
|
|
55
65
|
def sudo(cmd)
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
def info(*args)
|
60
|
-
$stderr.puts *args
|
61
|
-
end
|
62
|
-
|
63
|
-
def debug(*args)
|
64
|
-
$stdout.puts *args
|
66
|
+
shell.logged_system(Escape.shell_command(["sudo", "sh", "-l", "-c", cmd])).success?
|
65
67
|
end
|
66
68
|
|
67
69
|
# convenience functions for running on certain instance types
|
@@ -1,26 +1,18 @@
|
|
1
|
+
require 'engineyard-serverside/shell/helpers'
|
2
|
+
|
1
3
|
module EY
|
2
4
|
module Serverside
|
3
5
|
def self.deprecation_warning(msg)
|
4
6
|
$stderr.puts "DEPRECATION WARNING: #{msg}"
|
5
7
|
end
|
6
|
-
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
def self.const_missing(const)
|
10
|
+
if const == :LoggedOutput
|
11
|
+
EY::Serverside.deprecation_warning("EY::Serverside::LoggedOutput has been deprecated. Use EY::Serverside::Shell::Helpers instead.")
|
12
|
+
EY::Serverside::Shell::Helpers
|
13
|
+
else
|
14
|
+
super
|
15
|
+
end
|
14
16
|
end
|
15
17
|
end
|
16
|
-
|
17
|
-
def self.node
|
18
|
-
EY::Serverside.deprecation_warning("EY.node has been deprecated. use EY::Serverside.node instead")
|
19
|
-
EY::Serverside.node
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.dna_json
|
23
|
-
EY::Serverside.deprecation_warning("EY.dna_json has been deprecated. use EY::Serverside.dna_json instead")
|
24
|
-
EY::Serverside.dna_json
|
25
|
-
end
|
26
18
|
end
|
@@ -1,18 +1,24 @@
|
|
1
1
|
module EY
|
2
2
|
module Serverside
|
3
3
|
class Future
|
4
|
+
def self.map(blocks)
|
5
|
+
blocks.map { |block| new(&block) }
|
6
|
+
end
|
7
|
+
|
4
8
|
def self.success?(futures)
|
5
9
|
futures.empty? || futures.all? {|f| f.success?}
|
6
10
|
end
|
7
11
|
|
8
|
-
def initialize(
|
9
|
-
@server = server
|
10
|
-
@args = args
|
12
|
+
def initialize(&block)
|
11
13
|
@block = block
|
12
14
|
end
|
13
15
|
|
16
|
+
def result
|
17
|
+
@result ||= call
|
18
|
+
end
|
19
|
+
|
14
20
|
def success?
|
15
|
-
|
21
|
+
result.success?
|
16
22
|
end
|
17
23
|
|
18
24
|
def error?
|
@@ -3,22 +3,12 @@ module EY
|
|
3
3
|
$LOAD_PATH.unshift File.expand_path('../../vendor/celluloid/lib', File.dirname(__FILE__))
|
4
4
|
require 'celluloid'
|
5
5
|
class Future
|
6
|
-
def self.call(
|
7
|
-
|
8
|
-
new(server, *args, &block)
|
9
|
-
end
|
10
|
-
|
11
|
-
futures.each {|f| f.call}
|
12
|
-
futures
|
13
|
-
end
|
14
|
-
|
15
|
-
def future
|
16
|
-
Celluloid::Future.new(@server, *@args, &@block)
|
6
|
+
def self.call(blocks)
|
7
|
+
map(blocks).each {|f| f.result }
|
17
8
|
end
|
18
9
|
|
19
10
|
def call
|
20
|
-
|
21
|
-
@value ||= future.call
|
11
|
+
Celluloid::Future.new(&@block).call
|
22
12
|
end
|
23
13
|
end
|
24
14
|
end
|
@@ -6,25 +6,20 @@ module EY
|
|
6
6
|
class Future
|
7
7
|
extend Dataflow
|
8
8
|
|
9
|
-
def self.call(
|
10
|
-
futures =
|
11
|
-
# Dataflow needs to call `barrier` and `need_later` in the same object
|
12
|
-
barrier(*servers.map do |server|
|
13
|
-
future = new(server, *args, &block)
|
14
|
-
futures << future
|
9
|
+
def self.call(blocks)
|
10
|
+
futures = map(blocks)
|
15
11
|
|
16
|
-
|
17
|
-
|
12
|
+
# Dataflow needs to call `barrier` and `need_later` in the same object
|
13
|
+
need_laters = futures.map do |future|
|
14
|
+
need_later { future.result }
|
15
|
+
end
|
16
|
+
barrier(*need_laters)
|
18
17
|
|
19
18
|
futures
|
20
19
|
end
|
21
20
|
|
22
|
-
def future
|
23
|
-
@block.call(@server, *@args)
|
24
|
-
end
|
25
|
-
|
26
21
|
def call
|
27
|
-
@
|
22
|
+
@block.call
|
28
23
|
end
|
29
24
|
end
|
30
25
|
end
|
@@ -2,44 +2,60 @@ module EY
|
|
2
2
|
module Serverside
|
3
3
|
module RailsAssetSupport
|
4
4
|
def compile_assets
|
5
|
-
asset_dir = "#{c.release_path}/app/assets"
|
6
5
|
return unless app_needs_assets?
|
7
6
|
rails_version = bundled_rails_version
|
8
7
|
roles :app_master, :app, :solo do
|
9
8
|
keep_existing_assets
|
10
|
-
cmd = "cd #{c.release_path} && PATH=#{c.binstubs_path}:$PATH #{c.framework_envs} rake assets:precompile
|
9
|
+
cmd = "cd #{c.release_path} && PATH=#{c.binstubs_path}:$PATH #{c.framework_envs} rake assets:precompile"
|
10
|
+
|
11
|
+
unless config.precompile_assets?
|
12
|
+
# If specifically requested, then we want to fail if compilation fails.
|
13
|
+
# If we are implicitly precompiling, we want to fail non-destructively
|
14
|
+
# because we don't know if the rake task exists or if the user
|
15
|
+
# actually intended for assets to be compiled.
|
16
|
+
cmd << %{ || (echo "Asset compilation failure ignored.\n Add 'precompile_assets: true' to ey.yml to abort deploy on failure." && true)}
|
17
|
+
end
|
18
|
+
|
11
19
|
if rails_version
|
12
|
-
|
20
|
+
shell.status "Precompiling assets for rails v#{rails_version}"
|
13
21
|
else
|
14
|
-
warning "Precompiling assets even though Rails was not bundled."
|
22
|
+
shell.warning "Precompiling assets even though Rails was not bundled."
|
15
23
|
end
|
16
24
|
run(cmd)
|
17
25
|
end
|
18
26
|
end
|
19
27
|
|
20
28
|
def app_needs_assets?
|
29
|
+
if config.precompile_assets?
|
30
|
+
shell.status "Attempting Rails asset precompilation. (enabled in config)"
|
31
|
+
return true
|
32
|
+
elsif config.skip_precompile_assets?
|
33
|
+
shell.status "Skipping asset precompilation. (disabled in config)"
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
|
21
37
|
app_rb_path = File.join(c.release_path, 'config', 'application.rb')
|
22
38
|
return unless File.readable?(app_rb_path) # Not a Rails app in the first place.
|
23
39
|
|
24
40
|
if File.directory?(File.join(c.release_path, 'app', 'assets'))
|
25
|
-
|
41
|
+
shell.status "Attempting Rails asset precompilation. (found directory: 'app/assets')"
|
26
42
|
else
|
27
43
|
return false
|
28
44
|
end
|
29
45
|
|
30
46
|
if app_builds_own_assets?
|
31
|
-
|
47
|
+
shell.status "Skipping asset compilation. (found directory: 'public/assets')"
|
32
48
|
return
|
33
49
|
end
|
34
50
|
if app_disables_assets?(app_rb_path)
|
35
|
-
|
51
|
+
shell.status "Skipping asset compilation. (application.rb has disabled asset compilation)"
|
36
52
|
return
|
37
53
|
end
|
38
54
|
# This check is very expensive, and has been deemed not worth the time.
|
39
55
|
# Leaving this here in case someone comes up with a faster way.
|
40
56
|
=begin
|
41
57
|
unless app_has_asset_task?
|
42
|
-
|
58
|
+
shell.status "No 'assets:precompile' Rake task found. Skipping."
|
43
59
|
return
|
44
60
|
end
|
45
61
|
=end
|
@@ -62,8 +78,7 @@ module EY
|
|
62
78
|
# have the same code anyway.
|
63
79
|
task_check = "PATH=#{c.binstubs_path}:$PATH #{c.framework_envs} rake -T assets:precompile |grep 'assets:precompile'"
|
64
80
|
cmd = "cd #{c.release_path} && #{task_check}"
|
65
|
-
logged_system
|
66
|
-
$? == 0
|
81
|
+
shell.logged_system("cd #{c.release_path} && #{task_check}").success?
|
67
82
|
end
|
68
83
|
|
69
84
|
def app_builds_own_assets?
|
@@ -90,6 +105,7 @@ ln -nfs #{current} #{last_asset_path} #{c.release_path}/public
|
|
90
105
|
|
91
106
|
def bundled_rails_version(lockfile_path = nil)
|
92
107
|
lockfile_path ||= File.join(c.release_path, 'Gemfile.lock')
|
108
|
+
return unless File.exist?(lockfile_path)
|
93
109
|
lockfile = File.open(lockfile_path) {|f| f.read}
|
94
110
|
lockfile.each_line do |line|
|
95
111
|
# scan for gemname (version) toplevel deps.
|
@@ -1,11 +1,8 @@
|
|
1
1
|
require 'open-uri'
|
2
|
-
require 'engineyard-serverside/logged_output'
|
3
2
|
|
4
3
|
module EY
|
5
4
|
module Serverside
|
6
5
|
class Server < Struct.new(:hostname, :roles, :name, :user)
|
7
|
-
include LoggedOutput
|
8
|
-
|
9
6
|
class DuplicateHostname < StandardError
|
10
7
|
def initialize(hostname)
|
11
8
|
super "There is already an EY::Serverside::Server with hostname '#{hostname}'"
|
@@ -73,18 +70,26 @@ module EY
|
|
73
70
|
hostname == 'localhost'
|
74
71
|
end
|
75
72
|
|
76
|
-
def
|
77
|
-
return if local?
|
78
|
-
|
79
|
-
|
73
|
+
def sync_directory_command(directory)
|
74
|
+
return nil if local?
|
75
|
+
[
|
76
|
+
remote_command("mkdir -p #{directory}"),
|
77
|
+
Escape.shell_command(%w[rsync --delete -aq -e] + [ssh_command, "#{directory}/", "#{user}@#{hostname}:#{directory}"])
|
78
|
+
].join(' && ')
|
79
|
+
end
|
80
|
+
|
81
|
+
def command_on_server(prefix, cmd, &block)
|
82
|
+
command = block ? block.call(self, cmd.dup) : cmd
|
83
|
+
command = "#{prefix} #{Escape.shell_command([command])}"
|
84
|
+
local? ? command : remote_command(command)
|
80
85
|
end
|
81
86
|
|
82
87
|
def run(command)
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
+
yield local? ? command : remote_command(command)
|
89
|
+
end
|
90
|
+
|
91
|
+
def remote_command(command)
|
92
|
+
ssh_command + Escape.shell_command(["#{user}@#{hostname}", command])
|
88
93
|
end
|
89
94
|
|
90
95
|
# Make a known hosts tempfile to absorb host fingerprints so we don't show
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'pathname'
|
3
|
+
require 'systemu'
|
4
|
+
require 'engineyard-serverside/shell/formatter'
|
5
|
+
|
6
|
+
module EY
|
7
|
+
module Serverside
|
8
|
+
class Shell
|
9
|
+
class YieldIO
|
10
|
+
def initialize(&block)
|
11
|
+
@block = block
|
12
|
+
end
|
13
|
+
def <<(str)
|
14
|
+
@block.call str
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class CommandResult < Struct.new(:command, :exitstatus, :output)
|
19
|
+
def success?
|
20
|
+
exitstatus.zero?
|
21
|
+
end
|
22
|
+
|
23
|
+
def inspect
|
24
|
+
<<-EOM
|
25
|
+
$ #{command}
|
26
|
+
#{output}
|
27
|
+
|
28
|
+
# => #{exitstatus}
|
29
|
+
EOM
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :logger
|
34
|
+
|
35
|
+
def initialize(options)
|
36
|
+
@start_time = options[:start_time]
|
37
|
+
@verbose = options[:verbose]
|
38
|
+
|
39
|
+
|
40
|
+
@stdout = options[:stdout] || $stdout
|
41
|
+
@stderr = options[:stderr] || $stderr
|
42
|
+
|
43
|
+
log_pathname = Pathname.new(options[:log_path])
|
44
|
+
log_pathname.unlink if log_pathname.exist? # start fresh
|
45
|
+
@logger = Logger.new(log_pathname.to_s)
|
46
|
+
@logger.level = Logger::DEBUG # Always log to the file at debug, formatter hides debug for non-verbose
|
47
|
+
@logger.formatter = EY::Serverside::Shell::Formatter.new(@stdout, @stderr, start_time, @verbose)
|
48
|
+
end
|
49
|
+
|
50
|
+
def start_time
|
51
|
+
@start_time ||= Time.now
|
52
|
+
end
|
53
|
+
|
54
|
+
# a nice info outputter that prepends spermy operators for some reason.
|
55
|
+
def status(msg)
|
56
|
+
info msg.gsub(/^/, '~> ')
|
57
|
+
end
|
58
|
+
|
59
|
+
def substatus(msg)
|
60
|
+
debug msg.gsub(/^/, ' ~ ')
|
61
|
+
end
|
62
|
+
|
63
|
+
def fatal(msg) logger.fatal "FATAL: #{msg}" end
|
64
|
+
def error(msg) logger.error "ERROR: #{msg}" end
|
65
|
+
def warning(msg) logger.warn "WARNING: #{msg}" end
|
66
|
+
def notice(msg) logger.warn msg end
|
67
|
+
def info(msg) logger.info msg end
|
68
|
+
def debug(msg) logger.debug msg end
|
69
|
+
def unknown(msg) logger.unknown msg end
|
70
|
+
|
71
|
+
# a debug outputter that displays a command being run
|
72
|
+
# Formatis like this:
|
73
|
+
# $ cmd blah do \
|
74
|
+
# > something more
|
75
|
+
# > end
|
76
|
+
def show_command(cmd)
|
77
|
+
debug cmd.gsub(/^/, ' > ').sub(/>/, '$')
|
78
|
+
end
|
79
|
+
|
80
|
+
def logged_system(cmd)
|
81
|
+
show_command(cmd)
|
82
|
+
output = ""
|
83
|
+
outio = YieldIO.new { |msg| output << msg; debug msg.gsub(/^/,' ') }
|
84
|
+
errio = YieldIO.new { |msg| output << msg; unknown msg.gsub(/^/,' ') }
|
85
|
+
result = spawn_process(cmd, outio, errio)
|
86
|
+
CommandResult.new(cmd, result.exitstatus, output)
|
87
|
+
end
|
88
|
+
|
89
|
+
protected
|
90
|
+
|
91
|
+
# This is the meat of process spawning. It's nice to keep it separate even
|
92
|
+
# though it's simple because we've had to modify it frequently.
|
93
|
+
def spawn_process(cmd, outio, errio)
|
94
|
+
systemu cmd, 'stdout' => outio, 'stderr' => errio
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|