hem 1.0.1.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +10 -0
  3. data/.gitignore +3 -0
  4. data/.rspec +2 -0
  5. data/CHANGELOG.md +125 -0
  6. data/DoD.md +5 -0
  7. data/Gemfile +4 -0
  8. data/Gemfile.lock +71 -0
  9. data/Guardfile +14 -0
  10. data/Hemfile +43 -0
  11. data/LICENSE +21 -0
  12. data/README.md +42 -0
  13. data/Rakefile +23 -0
  14. data/bin/hem +64 -0
  15. data/features/deps.feature +43 -0
  16. data/features/hem/basic.feature +43 -0
  17. data/features/hem/help.feature +16 -0
  18. data/features/hem/subcommands.feature +15 -0
  19. data/features/seed/plant.feature +64 -0
  20. data/features/step_definitions/env.rb +6 -0
  21. data/features/step_definitions/seed.rb +11 -0
  22. data/features/support/env.rb +6 -0
  23. data/hem.gemspec +47 -0
  24. data/lib/hem/asset_applicator.rb +33 -0
  25. data/lib/hem/asset_applicators/files.rb +5 -0
  26. data/lib/hem/asset_applicators/sqldump.rb +38 -0
  27. data/lib/hem/cli.rb +252 -0
  28. data/lib/hem/config/file.rb +22 -0
  29. data/lib/hem/config.rb +5 -0
  30. data/lib/hem/error_handlers/debug.rb +12 -0
  31. data/lib/hem/error_handlers/exit_code_map.rb +17 -0
  32. data/lib/hem/error_handlers/friendly.rb +58 -0
  33. data/lib/hem/errors.rb +89 -0
  34. data/lib/hem/help_formatter.rb +118 -0
  35. data/lib/hem/helper/file_locator.rb +44 -0
  36. data/lib/hem/helper/github.rb +10 -0
  37. data/lib/hem/helper/http_download.rb +41 -0
  38. data/lib/hem/helper/shell.rb +101 -0
  39. data/lib/hem/helper/vm_command.rb +30 -0
  40. data/lib/hem/lib/github/api.rb +48 -0
  41. data/lib/hem/lib/github/client.rb +52 -0
  42. data/lib/hem/lib/host_check/deps.rb +39 -0
  43. data/lib/hem/lib/host_check/git.rb +76 -0
  44. data/lib/hem/lib/host_check/ruby.rb +53 -0
  45. data/lib/hem/lib/host_check/vagrant.rb +45 -0
  46. data/lib/hem/lib/host_check.rb +34 -0
  47. data/lib/hem/lib/s3/local/file.rb +40 -0
  48. data/lib/hem/lib/s3/local/iohandler.rb +36 -0
  49. data/lib/hem/lib/s3/remote/file.rb +57 -0
  50. data/lib/hem/lib/s3/remote/iohandler.rb +38 -0
  51. data/lib/hem/lib/s3/sync.rb +134 -0
  52. data/lib/hem/lib/seed/project.rb +71 -0
  53. data/lib/hem/lib/seed/replacer.rb +56 -0
  54. data/lib/hem/lib/seed/seed.rb +111 -0
  55. data/lib/hem/lib/self_signed_cert_generator.rb +38 -0
  56. data/lib/hem/lib/vm/command.rb +131 -0
  57. data/lib/hem/lib/vm/inspector.rb +73 -0
  58. data/lib/hem/logging.rb +20 -0
  59. data/lib/hem/metadata.rb +42 -0
  60. data/lib/hem/null.rb +31 -0
  61. data/lib/hem/patches/deepstruct.rb +21 -0
  62. data/lib/hem/patches/rake.rb +101 -0
  63. data/lib/hem/patches/rubygems.rb +6 -0
  64. data/lib/hem/patches/slop.rb +69 -0
  65. data/lib/hem/paths.rb +96 -0
  66. data/lib/hem/tasks/assets.rb +92 -0
  67. data/lib/hem/tasks/config.rb +15 -0
  68. data/lib/hem/tasks/deps.rb +103 -0
  69. data/lib/hem/tasks/exec.rb +3 -0
  70. data/lib/hem/tasks/magento.rb +281 -0
  71. data/lib/hem/tasks/ops.rb +6 -0
  72. data/lib/hem/tasks/pr.rb +45 -0
  73. data/lib/hem/tasks/seed.rb +61 -0
  74. data/lib/hem/tasks/self.rb +45 -0
  75. data/lib/hem/tasks/shell_init.rb +25 -0
  76. data/lib/hem/tasks/system/completions.rb +76 -0
  77. data/lib/hem/tasks/system.rb +18 -0
  78. data/lib/hem/tasks/tools.rb +17 -0
  79. data/lib/hem/tasks/vm.rb +140 -0
  80. data/lib/hem/ui.rb +182 -0
  81. data/lib/hem/util.rb +76 -0
  82. data/lib/hem/version.rb +3 -0
  83. data/lib/hem.rb +72 -0
  84. data/lib/hobo/tasks/magento.rb +3 -0
  85. data/spec/hem/asset_applicator_spec.rb +30 -0
  86. data/spec/hem/cli_spec.rb +166 -0
  87. data/spec/hem/config/file_spec.rb +55 -0
  88. data/spec/hem/error_handlers/debug_spec.rb +43 -0
  89. data/spec/hem/error_handlers/friendly_spec.rb +97 -0
  90. data/spec/hem/error_spec.rb +0 -0
  91. data/spec/hem/help_formatter_spec.rb +162 -0
  92. data/spec/hem/helpers/file_locator_spec.rb +11 -0
  93. data/spec/hem/helpers/github_spec.rb +31 -0
  94. data/spec/hem/helpers/shell_spec.rb +22 -0
  95. data/spec/hem/helpers/vm_command_spec.rb +96 -0
  96. data/spec/hem/lib/github/api_spec.rb +92 -0
  97. data/spec/hem/lib/s3/sync_spec.rb +16 -0
  98. data/spec/hem/lib/seed/project_spec.rb +80 -0
  99. data/spec/hem/lib/seed/replacer_spec.rb +45 -0
  100. data/spec/hem/lib/seed/seed_spec.rb +127 -0
  101. data/spec/hem/logging_spec.rb +27 -0
  102. data/spec/hem/metadata_spec.rb +55 -0
  103. data/spec/hem/null_spec.rb +30 -0
  104. data/spec/hem/patches/rake_spec.rb +230 -0
  105. data/spec/hem/paths_spec.rb +75 -0
  106. data/spec/hem/ui_spec.rb +189 -0
  107. data/spec/hem/util_spec.rb +74 -0
  108. data/spec/spec_helper.rb +12 -0
  109. data/ssl/ca-bundle-s3.crt +3554 -0
  110. data/test_files/vagrant_fail/vagrant +2 -0
  111. metadata +339 -0
@@ -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
@@ -0,0 +1,3 @@
1
+ module Hem
2
+ VERSION = '1.0.1-beta1'
3
+ end
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,3 @@
1
+ Hem.ui.warning 'require \'hobo/tasks/magento\' in Hobofile is deprecated, and will be removed in a future release.'
2
+
3
+ require 'hem/tasks/magento'
@@ -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