hem 1.0.1.beta1
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.
- checksums.yaml +7 -0
- data/.editorconfig +10 -0
- data/.gitignore +3 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +125 -0
- data/DoD.md +5 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +71 -0
- data/Guardfile +14 -0
- data/Hemfile +43 -0
- data/LICENSE +21 -0
- data/README.md +42 -0
- data/Rakefile +23 -0
- data/bin/hem +64 -0
- data/features/deps.feature +43 -0
- data/features/hem/basic.feature +43 -0
- data/features/hem/help.feature +16 -0
- data/features/hem/subcommands.feature +15 -0
- data/features/seed/plant.feature +64 -0
- data/features/step_definitions/env.rb +6 -0
- data/features/step_definitions/seed.rb +11 -0
- data/features/support/env.rb +6 -0
- data/hem.gemspec +47 -0
- data/lib/hem/asset_applicator.rb +33 -0
- data/lib/hem/asset_applicators/files.rb +5 -0
- data/lib/hem/asset_applicators/sqldump.rb +38 -0
- data/lib/hem/cli.rb +252 -0
- data/lib/hem/config/file.rb +22 -0
- data/lib/hem/config.rb +5 -0
- data/lib/hem/error_handlers/debug.rb +12 -0
- data/lib/hem/error_handlers/exit_code_map.rb +17 -0
- data/lib/hem/error_handlers/friendly.rb +58 -0
- data/lib/hem/errors.rb +89 -0
- data/lib/hem/help_formatter.rb +118 -0
- data/lib/hem/helper/file_locator.rb +44 -0
- data/lib/hem/helper/github.rb +10 -0
- data/lib/hem/helper/http_download.rb +41 -0
- data/lib/hem/helper/shell.rb +101 -0
- data/lib/hem/helper/vm_command.rb +30 -0
- data/lib/hem/lib/github/api.rb +48 -0
- data/lib/hem/lib/github/client.rb +52 -0
- data/lib/hem/lib/host_check/deps.rb +39 -0
- data/lib/hem/lib/host_check/git.rb +76 -0
- data/lib/hem/lib/host_check/ruby.rb +53 -0
- data/lib/hem/lib/host_check/vagrant.rb +45 -0
- data/lib/hem/lib/host_check.rb +34 -0
- data/lib/hem/lib/s3/local/file.rb +40 -0
- data/lib/hem/lib/s3/local/iohandler.rb +36 -0
- data/lib/hem/lib/s3/remote/file.rb +57 -0
- data/lib/hem/lib/s3/remote/iohandler.rb +38 -0
- data/lib/hem/lib/s3/sync.rb +134 -0
- data/lib/hem/lib/seed/project.rb +71 -0
- data/lib/hem/lib/seed/replacer.rb +56 -0
- data/lib/hem/lib/seed/seed.rb +111 -0
- data/lib/hem/lib/self_signed_cert_generator.rb +38 -0
- data/lib/hem/lib/vm/command.rb +131 -0
- data/lib/hem/lib/vm/inspector.rb +73 -0
- data/lib/hem/logging.rb +20 -0
- data/lib/hem/metadata.rb +42 -0
- data/lib/hem/null.rb +31 -0
- data/lib/hem/patches/deepstruct.rb +21 -0
- data/lib/hem/patches/rake.rb +101 -0
- data/lib/hem/patches/rubygems.rb +6 -0
- data/lib/hem/patches/slop.rb +69 -0
- data/lib/hem/paths.rb +96 -0
- data/lib/hem/tasks/assets.rb +92 -0
- data/lib/hem/tasks/config.rb +15 -0
- data/lib/hem/tasks/deps.rb +103 -0
- data/lib/hem/tasks/exec.rb +3 -0
- data/lib/hem/tasks/magento.rb +281 -0
- data/lib/hem/tasks/ops.rb +6 -0
- data/lib/hem/tasks/pr.rb +45 -0
- data/lib/hem/tasks/seed.rb +61 -0
- data/lib/hem/tasks/self.rb +45 -0
- data/lib/hem/tasks/shell_init.rb +25 -0
- data/lib/hem/tasks/system/completions.rb +76 -0
- data/lib/hem/tasks/system.rb +18 -0
- data/lib/hem/tasks/tools.rb +17 -0
- data/lib/hem/tasks/vm.rb +140 -0
- data/lib/hem/ui.rb +182 -0
- data/lib/hem/util.rb +76 -0
- data/lib/hem/version.rb +3 -0
- data/lib/hem.rb +72 -0
- data/lib/hobo/tasks/magento.rb +3 -0
- data/spec/hem/asset_applicator_spec.rb +30 -0
- data/spec/hem/cli_spec.rb +166 -0
- data/spec/hem/config/file_spec.rb +55 -0
- data/spec/hem/error_handlers/debug_spec.rb +43 -0
- data/spec/hem/error_handlers/friendly_spec.rb +97 -0
- data/spec/hem/error_spec.rb +0 -0
- data/spec/hem/help_formatter_spec.rb +162 -0
- data/spec/hem/helpers/file_locator_spec.rb +11 -0
- data/spec/hem/helpers/github_spec.rb +31 -0
- data/spec/hem/helpers/shell_spec.rb +22 -0
- data/spec/hem/helpers/vm_command_spec.rb +96 -0
- data/spec/hem/lib/github/api_spec.rb +92 -0
- data/spec/hem/lib/s3/sync_spec.rb +16 -0
- data/spec/hem/lib/seed/project_spec.rb +80 -0
- data/spec/hem/lib/seed/replacer_spec.rb +45 -0
- data/spec/hem/lib/seed/seed_spec.rb +127 -0
- data/spec/hem/logging_spec.rb +27 -0
- data/spec/hem/metadata_spec.rb +55 -0
- data/spec/hem/null_spec.rb +30 -0
- data/spec/hem/patches/rake_spec.rb +230 -0
- data/spec/hem/paths_spec.rb +75 -0
- data/spec/hem/ui_spec.rb +189 -0
- data/spec/hem/util_spec.rb +74 -0
- data/spec/spec_helper.rb +12 -0
- data/ssl/ca-bundle-s3.crt +3554 -0
- data/test_files/vagrant_fail/vagrant +2 -0
- metadata +339 -0
data/lib/hem/tasks/vm.rb
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
desc "VM related commands"
|
|
2
|
+
project_only
|
|
3
|
+
namespace :vm do
|
|
4
|
+
def vagrantfile &block
|
|
5
|
+
locate "*Vagrantfile" do
|
|
6
|
+
yield
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def vagrant_exec *args
|
|
11
|
+
opts = { :realtime => true, :indent => 2 }
|
|
12
|
+
color = Hem.ui.supports_color? ? '--color' : '--no-color'
|
|
13
|
+
|
|
14
|
+
if Hem.windows?
|
|
15
|
+
opts[:env] = { 'VAGRANT_HOME' => windows_short(dir) } if ENV['HOME'].match(/\s+/) && !ENV['VAGRANT_HOME']
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
args.unshift 'vagrant'
|
|
19
|
+
args.push color
|
|
20
|
+
args.push opts
|
|
21
|
+
|
|
22
|
+
shell *args
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def windows_short dir
|
|
26
|
+
segments = dir.gsub(/\\/, '/').split('/')
|
|
27
|
+
segments.map do |segment|
|
|
28
|
+
if segment.match /\s+/
|
|
29
|
+
# This may fail in some edge cases but better than naught
|
|
30
|
+
# See the following link for the correct solution
|
|
31
|
+
# http://stackoverflow.com/questions/10224572/convert-long-filename-to-short-filename-8-3
|
|
32
|
+
segment.upcase.gsub(/\s+/, '')[0...6] + '~1'
|
|
33
|
+
else
|
|
34
|
+
segment
|
|
35
|
+
end
|
|
36
|
+
end.join('/')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
desc "Start & provision VM"
|
|
40
|
+
task :up => [ 'assets:download', 'vm:start', 'vm:provision', 'deps:composer', 'assets:apply' ]
|
|
41
|
+
|
|
42
|
+
desc "Stop VM"
|
|
43
|
+
task :stop do
|
|
44
|
+
vagrantfile do
|
|
45
|
+
Hem.ui.title "Stopping VM"
|
|
46
|
+
vagrant_exec 'halt'
|
|
47
|
+
Hem.ui.separator
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
desc "Rebuild VM"
|
|
52
|
+
task :rebuild => [ 'vm:destroy', 'vm:up' ]
|
|
53
|
+
|
|
54
|
+
desc "Destroy VM"
|
|
55
|
+
task :destroy do
|
|
56
|
+
vagrantfile do
|
|
57
|
+
Hem.ui.title "Destroying VM"
|
|
58
|
+
vagrant_exec 'destroy', '--force'
|
|
59
|
+
Hem.ui.separator
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
desc "Start VM without provision"
|
|
64
|
+
task :start => [ "deps:gems", "deps:chef", "deps:vagrant_plugins" ] do
|
|
65
|
+
vagrantfile do
|
|
66
|
+
state = shell("vagrant --machine-readable status | grep ,state, | cut -d, -f4", :capture => true).strip
|
|
67
|
+
unless state == 'running'
|
|
68
|
+
Hem.ui.title "Starting vagrant VM"
|
|
69
|
+
args = ['up', '--no-provision']
|
|
70
|
+
|
|
71
|
+
provider = maybe(Hem.user_config.vm.provider)
|
|
72
|
+
provider ||= maybe(Hem.project_config.vm.provider)
|
|
73
|
+
|
|
74
|
+
if provider
|
|
75
|
+
args.concat ['--provider', provider]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
vagrant_exec *args
|
|
79
|
+
Hem.ui.separator
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
desc "Reload VM"
|
|
85
|
+
task :reload do
|
|
86
|
+
vagrantfile do
|
|
87
|
+
Hem.ui.title "Reloading VM"
|
|
88
|
+
vagrant_exec 'reload', '--no-provision'
|
|
89
|
+
Hem.ui.separator
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
desc "Provision VM"
|
|
94
|
+
task :provision => [ "deps:chef" ] do
|
|
95
|
+
vagrantfile do
|
|
96
|
+
Hem.ui.title "Provisioning VM"
|
|
97
|
+
vagrant_exec 'provision'
|
|
98
|
+
Hem.ui.separator
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
desc "Open an SSH connection"
|
|
103
|
+
task :ssh do |task|
|
|
104
|
+
execute = task.opts[:_unparsed]
|
|
105
|
+
opts = { :psuedo_tty => STDIN.tty? }
|
|
106
|
+
|
|
107
|
+
Hem.ui.success "Determining VM connection details..." if STDOUT.tty?
|
|
108
|
+
command = execute.empty? ? vm_command(nil, opts) : vm_command(execute, opts)
|
|
109
|
+
Hem.logger.debug "vm:ssh: #{command}"
|
|
110
|
+
|
|
111
|
+
Hem.ui.success "Connecting..." if STDOUT.tty?
|
|
112
|
+
exec command
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
desc "Open a MySQL cli connection"
|
|
116
|
+
option '-D=', '--db=', 'Database'
|
|
117
|
+
task :mysql do |task|
|
|
118
|
+
opts = { :psuedo_tty => STDIN.tty? }
|
|
119
|
+
opts[:db] = task.opts[:db] if task.opts[:db]
|
|
120
|
+
|
|
121
|
+
Hem.ui.success "Determining VM connection details..." if STDOUT.tty?
|
|
122
|
+
command = vm_mysql(opts)
|
|
123
|
+
Hem.logger.debug "vm:mysql: #{command}"
|
|
124
|
+
|
|
125
|
+
Hem.ui.success "Connecting..." if STDOUT.tty?
|
|
126
|
+
exec command
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
desc "Open a Redis cli connection"
|
|
130
|
+
task :redis do
|
|
131
|
+
opts = { :psuedo_tty => STDIN.tty? }
|
|
132
|
+
|
|
133
|
+
Hem.ui.success "Determining VM connection details..." if STDOUT.tty?
|
|
134
|
+
command = vm_command("redis-cli", opts)
|
|
135
|
+
Hem.logger.debug "vm:redis: #{command}"
|
|
136
|
+
|
|
137
|
+
Hem.ui.success "Connecting..." if STDOUT.tty?
|
|
138
|
+
exec command
|
|
139
|
+
end
|
|
140
|
+
end
|
data/lib/hem/ui.rb
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
module Hem
|
|
2
|
+
class << self
|
|
3
|
+
attr_accessor :ui
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
class Ui
|
|
7
|
+
include Hem::Logging
|
|
8
|
+
|
|
9
|
+
attr_accessor :interactive
|
|
10
|
+
|
|
11
|
+
COLORS = {
|
|
12
|
+
:debug => [ ],
|
|
13
|
+
:info => [ ],
|
|
14
|
+
:warning => [:yellow],
|
|
15
|
+
:error => [:red],
|
|
16
|
+
:success => [:green],
|
|
17
|
+
:opt => [:green],
|
|
18
|
+
:command => [:green],
|
|
19
|
+
:special => [:blue],
|
|
20
|
+
:title => [:green],
|
|
21
|
+
:help_title => [:yellow],
|
|
22
|
+
:description => [:bold]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
def initialize input = $stdin, output = $stdout, error = $stderr
|
|
26
|
+
require 'highline'
|
|
27
|
+
HighLine.color_scheme = HighLine::ColorScheme.new COLORS
|
|
28
|
+
@output_io = output
|
|
29
|
+
@out = ::HighLine.new input, output
|
|
30
|
+
@error = ::HighLine.new input, error
|
|
31
|
+
use_color supports_color?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def color_scheme scheme = nil
|
|
35
|
+
HighLine.color_scheme = scheme if scheme
|
|
36
|
+
HighLine.color_scheme
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def supports_color?
|
|
40
|
+
return @output_io.tty? unless Hem.windows?
|
|
41
|
+
return (ENV['ANSICON'] || ENV['TERM'] == 'xterm') && @output_io.tty? # ANSICON or MinTTY && output is TTY
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def use_color opt = nil
|
|
45
|
+
HighLine.use_color = opt unless opt.nil?
|
|
46
|
+
HighLine.use_color?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def ask question, opts = {}
|
|
50
|
+
opts = {
|
|
51
|
+
:validate => nil,
|
|
52
|
+
:default => nil,
|
|
53
|
+
:echo => true
|
|
54
|
+
}.merge(opts)
|
|
55
|
+
|
|
56
|
+
unless @interactive
|
|
57
|
+
raise Hem::NonInteractiveError.new(question) if opts[:default].nil?
|
|
58
|
+
return opts[:default].to_s
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
question = "#{question} [#{opts[:default]}]" if opts[:default]
|
|
62
|
+
question += ": "
|
|
63
|
+
begin
|
|
64
|
+
answer = @out.ask(question) do |q|
|
|
65
|
+
q.validate = opts[:validate] if opts[:validate]
|
|
66
|
+
q.echo = opts[:echo]
|
|
67
|
+
q.readline
|
|
68
|
+
end
|
|
69
|
+
answer = answer.to_s
|
|
70
|
+
answer.strip.empty? ? opts[:default].to_s : answer.strip
|
|
71
|
+
rescue EOFError
|
|
72
|
+
Hem.ui.info ""
|
|
73
|
+
""
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def ask_choice question, choices, opts = {}
|
|
78
|
+
unless @interactive
|
|
79
|
+
raise Hem::NonInteractiveError.new(question) if opts[:default].nil?
|
|
80
|
+
return opts[:default].to_s
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
question = "#{question} [#{opts[:default]}]" if opts[:default]
|
|
84
|
+
question += ":"
|
|
85
|
+
info question
|
|
86
|
+
|
|
87
|
+
choice_map = {}
|
|
88
|
+
choices.to_enum.with_index(1) do |choice, index|
|
|
89
|
+
choice_map[index.to_s] = choice
|
|
90
|
+
info "#{index}] #{choice}"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
begin
|
|
94
|
+
answer = @out.ask("? ") do |q|
|
|
95
|
+
q.validate = lambda do |a|
|
|
96
|
+
s = a.strip
|
|
97
|
+
s.empty? || (choice_map.keys + choices).include?(s)
|
|
98
|
+
end
|
|
99
|
+
q.readline
|
|
100
|
+
end
|
|
101
|
+
answer = answer.to_s
|
|
102
|
+
answer = choice_map[answer] if /^\d+$/.match(answer.strip)
|
|
103
|
+
answer.strip.empty? ? opts[:default].to_s : answer.strip
|
|
104
|
+
rescue EOFError
|
|
105
|
+
Hem.ui.info ""
|
|
106
|
+
""
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def editor initial_text
|
|
111
|
+
editor = Hem.user_config.editor.nil? ? ENV['EDITOR'] : Hem.user_config.editor
|
|
112
|
+
if editor.nil?
|
|
113
|
+
raise Hem::UndefinedEditorError.new
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
tmp = Tempfile.new('hem_tmp')
|
|
117
|
+
begin
|
|
118
|
+
tmp.write initial_text
|
|
119
|
+
tmp.close
|
|
120
|
+
system([editor, tmp.path].join(' '))
|
|
121
|
+
tmp.open
|
|
122
|
+
return tmp.read
|
|
123
|
+
rescue Exception => e
|
|
124
|
+
raise Hem::Error.new e.message
|
|
125
|
+
ensure
|
|
126
|
+
tmp.close
|
|
127
|
+
tmp.unlink
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def section title
|
|
132
|
+
Hem.ui.title title
|
|
133
|
+
yield
|
|
134
|
+
Hem.ui.separator
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def separator
|
|
138
|
+
info(supports_color? ? "" : "\n")
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def color *args
|
|
142
|
+
@out.color *args
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def debug message
|
|
146
|
+
say @out, message, :debug
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def info message
|
|
150
|
+
say @out, message, :info
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def warning message
|
|
154
|
+
say @error, message, :warning
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def error message
|
|
158
|
+
say @error, message, :error
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def success message
|
|
162
|
+
say @out, message, :success
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def output message
|
|
166
|
+
say @out, message, nil
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def title message
|
|
170
|
+
say @out, message, :title
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
private
|
|
174
|
+
|
|
175
|
+
def say channel, message, color
|
|
176
|
+
return if message.nil?
|
|
177
|
+
message = color ? channel.color(message, color) : message
|
|
178
|
+
channel.say(message) unless logger.level <= Logger::DEBUG
|
|
179
|
+
logger.debug(message)
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
data/lib/hem/util.rb
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Hem
|
|
2
|
+
class << self
|
|
3
|
+
|
|
4
|
+
attr_accessor :project_bar_cache
|
|
5
|
+
|
|
6
|
+
def relaunch! env = {}
|
|
7
|
+
Kernel.exec(env, 'hem', '--skip-host-checks', *$HEM_ARGV)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def in_project?
|
|
11
|
+
!!Hem.project_path
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def progress file, increment, total, type, opts = {}
|
|
15
|
+
require 'ruby-progressbar'
|
|
16
|
+
|
|
17
|
+
opts = {
|
|
18
|
+
:title => File.basename(file),
|
|
19
|
+
:total => total,
|
|
20
|
+
:format => "%t [%B] %p%% %e"
|
|
21
|
+
}.merge(opts)
|
|
22
|
+
|
|
23
|
+
# Hack to stop newline spam on windows
|
|
24
|
+
opts[:length] = 79 if Gem::win_platform?
|
|
25
|
+
|
|
26
|
+
@progress_bar_cache ||= {}
|
|
27
|
+
|
|
28
|
+
if type == :reset
|
|
29
|
+
type = :update
|
|
30
|
+
@progress_bar_cache.delete file
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
@progress_bar_cache[file] ||= ProgressBar.create(opts)
|
|
34
|
+
|
|
35
|
+
case type
|
|
36
|
+
when :update
|
|
37
|
+
@progress_bar_cache[file].progress += increment
|
|
38
|
+
when :finished
|
|
39
|
+
@progress_bar_cache[file].finish
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
return @progress_bar_cache[file]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def aws_credentials
|
|
46
|
+
{
|
|
47
|
+
:access_key_id => maybe(Hem.user_config.aws.access_key_id) || ENV['AWS_ACCESS_KEY_ID'],
|
|
48
|
+
:secret_access_key => maybe(Hem.user_config.aws.secret_access_key) || ENV['AWS_SECRET_ACCESS_KEY']
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def windows?
|
|
53
|
+
require 'rbconfig'
|
|
54
|
+
!!(RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def system_ruby?
|
|
58
|
+
require 'rbconfig'
|
|
59
|
+
File.join(RbConfig::CONFIG["bindir"], RbConfig::CONFIG["ruby_install_name"]).match(/\/rvm\/|\/\.rvm\/|\/\.rbenv/) != nil
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def chefdk_compat
|
|
63
|
+
return if maybe(Hem.user_config.hem.disable_chefdk_compat) || ENV['HEM_DISABLE_CHEFDK_COMPAT']
|
|
64
|
+
return if Hem.windows?
|
|
65
|
+
which_ruby = File.join(RbConfig::CONFIG["bindir"], RbConfig::CONFIG["ruby_install_name"])
|
|
66
|
+
if which_ruby =~ /rbenv/
|
|
67
|
+
split_path = ENV['PATH'].split ':'
|
|
68
|
+
paths = split_path.reject do |p|
|
|
69
|
+
p =~ /chefdk/
|
|
70
|
+
end
|
|
71
|
+
chef_paths = split_path - paths
|
|
72
|
+
ENV['PATH'] = (chef_paths + paths).join ':'
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
data/lib/hem/version.rb
ADDED
data/lib/hem.rb
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# External deps
|
|
2
|
+
require 'slop'
|
|
3
|
+
require 'rake'
|
|
4
|
+
require 'deepstruct'
|
|
5
|
+
require 'logger'
|
|
6
|
+
|
|
7
|
+
require 'shellwords'
|
|
8
|
+
require 'fileutils'
|
|
9
|
+
|
|
10
|
+
# DSL enhancements
|
|
11
|
+
require 'hem/metadata'
|
|
12
|
+
require 'hem/patches/rake'
|
|
13
|
+
require 'hem/patches/slop'
|
|
14
|
+
require 'hem/patches/deepstruct'
|
|
15
|
+
|
|
16
|
+
# Basics
|
|
17
|
+
require 'hem/version'
|
|
18
|
+
require 'hem/null'
|
|
19
|
+
require 'hem/paths'
|
|
20
|
+
require 'hem/errors'
|
|
21
|
+
require 'hem/logging'
|
|
22
|
+
require 'hem/ui'
|
|
23
|
+
require 'hem/util'
|
|
24
|
+
require 'hem/help_formatter'
|
|
25
|
+
require 'hem/error_handlers/exit_code_map'
|
|
26
|
+
require 'hem/error_handlers/debug'
|
|
27
|
+
require 'hem/error_handlers/friendly'
|
|
28
|
+
require 'hem/config/file'
|
|
29
|
+
require 'hem/config'
|
|
30
|
+
|
|
31
|
+
# Asset sync
|
|
32
|
+
require 'hem/lib/s3/sync'
|
|
33
|
+
require 'hem/lib/s3/local/file'
|
|
34
|
+
require 'hem/lib/s3/local/iohandler'
|
|
35
|
+
require 'hem/lib/s3/remote/file'
|
|
36
|
+
require 'hem/lib/s3/remote/iohandler'
|
|
37
|
+
|
|
38
|
+
# Task helpers
|
|
39
|
+
require 'hem/helper/shell'
|
|
40
|
+
require 'hem/helper/file_locator'
|
|
41
|
+
require 'hem/helper/github'
|
|
42
|
+
require 'hem/helper/http_download'
|
|
43
|
+
require 'hem/helper/vm_command'
|
|
44
|
+
|
|
45
|
+
require 'hem/lib/vm/inspector'
|
|
46
|
+
require 'hem/lib/vm/command'
|
|
47
|
+
|
|
48
|
+
# Asset applicators
|
|
49
|
+
require 'hem/asset_applicator'
|
|
50
|
+
require 'hem/asset_applicators/sqldump'
|
|
51
|
+
require 'hem/asset_applicators/files'
|
|
52
|
+
|
|
53
|
+
# Libs
|
|
54
|
+
require 'hem/lib/seed/project'
|
|
55
|
+
require 'hem/lib/seed/replacer'
|
|
56
|
+
require 'hem/lib/seed/seed'
|
|
57
|
+
require 'hem/lib/self_signed_cert_generator'
|
|
58
|
+
require 'hem/lib/github/api'
|
|
59
|
+
require 'hem/lib/github/client'
|
|
60
|
+
|
|
61
|
+
# Host checks
|
|
62
|
+
require 'hem/lib/host_check/git'
|
|
63
|
+
require 'hem/lib/host_check/vagrant'
|
|
64
|
+
require 'hem/lib/host_check/ruby'
|
|
65
|
+
require 'hem/lib/host_check/deps'
|
|
66
|
+
require 'hem/lib/host_check'
|
|
67
|
+
|
|
68
|
+
# App
|
|
69
|
+
require 'hem/cli'
|
|
70
|
+
|
|
71
|
+
# Hobo BC
|
|
72
|
+
Hobo = Hem
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
describe Hem::AssetApplicatorRegistry do
|
|
3
|
+
describe "asset_applicators accessor" do
|
|
4
|
+
it "should initialize registry if none exists" do
|
|
5
|
+
Hem.asset_applicators = nil
|
|
6
|
+
Hem.asset_applicators.should be_an_instance_of Hem::AssetApplicatorRegistry
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should return registry if exists" do
|
|
10
|
+
Hem.asset_applicators.register "test" do
|
|
11
|
+
"test"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
Hem.asset_applicators["test"].should be_an_instance_of Proc
|
|
15
|
+
Hem.asset_applicators["test"].call.should match "test"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "register" do
|
|
20
|
+
it "should store passed block with pattern" do
|
|
21
|
+
registry = Hem::AssetApplicatorRegistry.new
|
|
22
|
+
registry.register "abc" do
|
|
23
|
+
"block"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
registry["abc"].should be_an_instance_of Proc
|
|
27
|
+
registry["abc"].call.should match "block"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
|
|
2
|
+
describe Hem::Cli do
|
|
3
|
+
cli = nil
|
|
4
|
+
help = nil
|
|
5
|
+
hemfile = nil
|
|
6
|
+
|
|
7
|
+
def test_args args
|
|
8
|
+
args.concat([])
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
before do
|
|
12
|
+
Rake::Task.tasks.each do |task|
|
|
13
|
+
task.clear
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Hem.ui = double(Hem::Ui).as_null_object
|
|
17
|
+
help = double(Hem::HelpFormatter).as_null_object
|
|
18
|
+
host_check = double(Hem::Lib::HostCheck).as_null_object
|
|
19
|
+
cli = Hem::Cli.new help: help, host_check: host_check
|
|
20
|
+
|
|
21
|
+
hemfile = File.read(File.join(File.dirname(__FILE__), '../../Hemfile'))
|
|
22
|
+
|
|
23
|
+
Hem.project_path = nil
|
|
24
|
+
FakeFS.activate!
|
|
25
|
+
|
|
26
|
+
File.write('Hemfile', hemfile)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
after do
|
|
30
|
+
FakeFS::FileSystem.clear
|
|
31
|
+
FakeFS.deactivate!
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should load the hemfile if present" do
|
|
35
|
+
cli.start test_args([])
|
|
36
|
+
Rake::Task["test:non-interactive"].should_not be nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should load the user hemfile if present" do
|
|
40
|
+
FileUtils.mkdir_p(File.dirname(Hem.user_hemfile_path))
|
|
41
|
+
File.write(Hem.user_hemfile_path, "namespace :user do\ntask :user do\nend\nend")
|
|
42
|
+
cli.start test_args([])
|
|
43
|
+
Rake::Task["user:user"].should_not be nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should present Hemfile path in eval error" do
|
|
47
|
+
FileUtils.mkdir_p(File.dirname(Hem.hemfile_path))
|
|
48
|
+
File.write(Hem.hemfile_path, "An invalid hemfile")
|
|
49
|
+
begin
|
|
50
|
+
cli.start test_args([])
|
|
51
|
+
rescue Exception => e
|
|
52
|
+
e.backtrace[0].should match 'Hemfile'
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should load project config if present" do
|
|
57
|
+
FileUtils.mkdir_p("tools/hem/")
|
|
58
|
+
File.write("tools/hem/config.yaml", YAML::dump({ :project => "project_config" }))
|
|
59
|
+
cli.start test_args([])
|
|
60
|
+
Hem.project_config.project.should match "project_config"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should load user config if present" do
|
|
64
|
+
FileUtils.mkdir_p(Hem.config_path)
|
|
65
|
+
File.write(Hem.user_config_file, YAML::dump({ :user => "user_config" }))
|
|
66
|
+
cli.start test_args([])
|
|
67
|
+
Hem.user_config.user.should match "user_config"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should set command map on help formatter" do
|
|
71
|
+
help.should_recieve('command_map=')
|
|
72
|
+
cli.start test_args(["test", "subcommand"])
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "should propagate description metadata" do
|
|
76
|
+
map = nil
|
|
77
|
+
allow(help).to receive("command_map=") { |i| map = i }
|
|
78
|
+
cli.start test_args([])
|
|
79
|
+
map["test:metadata"].description.should match "description"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "should propagate long description metadata" do
|
|
83
|
+
map = nil
|
|
84
|
+
allow(help).to receive("command_map=") { |i| map = i }
|
|
85
|
+
cli.start test_args([])
|
|
86
|
+
map["test:metadata"].long_description.should match "long description"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "should propagate arg list metadata" do
|
|
90
|
+
map = nil
|
|
91
|
+
allow(help).to receive("command_map=") { |i| map = i }
|
|
92
|
+
cli.start test_args([])
|
|
93
|
+
expect(map["test:metadata"].arg_list).to eq [ :arg ]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "should propagate option metadata" do
|
|
97
|
+
map = nil
|
|
98
|
+
allow(help).to receive("command_map=") { |i| map = i }
|
|
99
|
+
cli.start test_args([])
|
|
100
|
+
map["test:metadata"].options.length.should be 2
|
|
101
|
+
expect(map["test:metadata"].options.map(&:short)).to eq [ 'o', 'h' ]
|
|
102
|
+
expect(map["test:metadata"].options.map(&:long)).to eq [ 'option', 'help' ]
|
|
103
|
+
expect(map["test:metadata"].options.map(&:description)).to eq [ 'Option description', 'Display help' ]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "should propagate hidden metadata" do
|
|
107
|
+
map = nil
|
|
108
|
+
allow(help).to receive("command_map=") { |i| map = i }
|
|
109
|
+
cli.start test_args([])
|
|
110
|
+
map["test:metadata"].hidden.should be true
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "should show help if no args or opts passed" do
|
|
114
|
+
help.should_receive(:help)
|
|
115
|
+
cli.start(test_args([]))
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "should show help for --help" do
|
|
119
|
+
help.should_receive(:help)
|
|
120
|
+
cli.start test_args(["--help"])
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "should execute a top level command" do
|
|
124
|
+
Hem.ui.should_recieve(:info).with("top level")
|
|
125
|
+
cli.start test_args(["top-level"])
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "should execute a subcommand" do
|
|
129
|
+
Hem.ui.should_recieve(:info).with("Subcommand test")
|
|
130
|
+
cli.start test_args(["test", "subcommand"])
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "should show help for a namespace" do
|
|
134
|
+
help.should_receive(:help).with(all: nil, target: "test")
|
|
135
|
+
cli.start test_args(["test"])
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it "should show command help for --help" do
|
|
139
|
+
help.should_receive(:help).with(all: nil, target: "test:subcommand")
|
|
140
|
+
cli.start test_args(["test", "subcommand", "--help"])
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "should propagate --all option to help" do
|
|
144
|
+
help.should_receive(:help).with(all: true, target: "test")
|
|
145
|
+
cli.start test_args(["test", "--all"])
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it "should propagate command opts to command" do
|
|
149
|
+
Hem.ui.should_receive(:info).with("1234")
|
|
150
|
+
cli.start test_args(["test", "option-test", "--testing=1234"])
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it "should propagate arguments to command" do
|
|
154
|
+
Hem.ui.should_receive(:info).with("1234")
|
|
155
|
+
cli.start test_args(["test", "argument-test", "1234"])
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "should propagate unparsed arguments in :_unparsed opt" do
|
|
159
|
+
Hem.ui.should_receive(:info).with("'ls' '--help'")
|
|
160
|
+
cli.start ["test", "unparsed", "--", "ls", "--help"]
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it "should raise an exception if not enough arguments were passed" do
|
|
164
|
+
expect { cli.start(test_args(["test", "metadata"])) }.to raise_error Hem::MissingArgumentsError
|
|
165
|
+
end
|
|
166
|
+
end
|