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,103 @@
1
+ desc "Dependency related tasks"
2
+ hidden true
3
+ namespace :deps do
4
+
5
+ desc "Install Gem dependencies"
6
+ task :gems do
7
+ locate "*Gemfile" do
8
+ required = shell("bundle", "check", :exit_status => true) != 0
9
+ if required
10
+ Hem.ui.title "Installing Gem dependencies"
11
+ shell "bundle", "install", realtime: true, indent: 2
12
+ Hem.ui.separator
13
+ end
14
+ end
15
+ end
16
+
17
+ desc "Install composer dependencies"
18
+ task :composer do
19
+ if File.exists? File.join(Hem.project_path, "composer.json")
20
+ Rake::Task["tools:composer"].invoke
21
+ Hem.ui.title "Installing composer dependencies"
22
+ Dir.chdir Hem.project_path do
23
+ ansi = Hem.ui.supports_color? ? '--ansi' : ''
24
+ args = [ "php bin/composer.phar install #{ansi} --prefer-dist", { realtime: true, indent: 2 } ]
25
+ complete = false
26
+
27
+ unless maybe(Hem.project_config.tasks.deps.composer.disable_host_run)
28
+ check = Hem::Lib::HostCheck.check(:filter => /php_present/)
29
+
30
+ if check[:php_present] == :ok
31
+ begin
32
+ shell *args
33
+ complete = true
34
+ rescue Hem::ExternalCommandError
35
+ Hem.ui.warning "Installing composer dependencies locally failed!"
36
+ end
37
+ end
38
+ end
39
+
40
+ if !complete
41
+ vm_shell *args
42
+ end
43
+
44
+ Hem.ui.success "Composer dependencies installed"
45
+ end
46
+
47
+ Hem.ui.separator
48
+ end
49
+ end
50
+
51
+ desc "Install vagrant plugins"
52
+ task :vagrant_plugins => [ "deps:gems" ] do
53
+ plugins = shell "vagrant plugin list", :capture => true
54
+ locate "*Vagrantfile" do
55
+ to_install = []
56
+ File.read("Vagrantfile").split("\n").each do |line|
57
+ if line.match /#\s*Hem.vagrant_plugin (.*)/ or line.match /#\s*Hobo.vagrant_plugin (.*)/
58
+ to_install << $1
59
+ else
60
+ next if line.match /^\s*#/
61
+ next unless line.match /Vagrant\.require_plugin (.*)/
62
+ to_install << $1
63
+ end
64
+ end
65
+
66
+ to_install.each do |plugin|
67
+ plugin.gsub!(/['"]*/, '')
68
+ next if plugins.include? "#{plugin} "
69
+ Hem.ui.title "Installing vagrant plugin: #{plugin}"
70
+ shell "vagrant", "plugin", "install", plugin, :realtime => true, :indent => 2
71
+ Hem.ui.separator
72
+ end
73
+ end
74
+ end
75
+
76
+ desc "Install chef dependencies"
77
+ task :chef => [ "deps:gems" ] do
78
+ locate "*Cheffile" do
79
+ Hem.ui.title "Installing chef dependencies via librarian"
80
+ bundle_shell "librarian-chef", "install", "--verbose", :realtime => true, :indent => 2 do |line|
81
+ line =~ /Installing.*</ ? line.strip + "\n" : nil
82
+ end
83
+ Hem.ui.separator
84
+ end
85
+
86
+ locate "*Berksfile" do
87
+ Hem.ui.title "Installing chef dependencies via berkshelf"
88
+ executor = (shell("bash -c 'which berks'", :capture => true).strip =~ /chefdk/) ?
89
+ lambda { |*args| shell *args } :
90
+ lambda { |*args| bundle_shell *args }
91
+
92
+ executor.call "berks", "install", :realtime => true, :indent => 2
93
+ version = executor.call "berks", "-v", :capture => true
94
+ if version =~ /^[3-9]/
95
+ shell "rm -rf cookbooks"
96
+ executor.call "berks", "vendor", "cookbooks"
97
+ else
98
+ executor.call "berks", "install", "--path", "cookbooks"
99
+ end
100
+ Hem.ui.separator
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,3 @@
1
+ task 'exec' do
2
+ exec(*$HEM_ARGV)
3
+ end
@@ -0,0 +1,281 @@
1
+ namespace :tools do
2
+ desc "Fetches the n98-magerun utility"
3
+ task :n98magerun do
4
+ FileUtils.mkdir_p "bin"
5
+ vm_shell '"wget" --no-check-certificate "https://raw.github.com/netz98/n98-magerun/master/n98-magerun.phar" -O bin/n98-magerun.phar'
6
+ FileUtils.chmod 0755, "bin/n98-magerun.phar"
7
+ end
8
+ end
9
+
10
+ desc "Magento related tasks"
11
+ namespace :magento do
12
+
13
+ desc "Patch tasks"
14
+ namespace :patches do
15
+ def magento_path
16
+ unless @magento_path
17
+ files = locate('*app/Mage.php')
18
+ unless files.length > 0
19
+ raise Hem::UserError.new "Could not find app/Mage.php in the git repository, this command should only be run for Magento projects"
20
+ end
21
+
22
+ /(?:(.*)\/)app\/Mage\.php/.match(files[0])
23
+ @magento_path = $1
24
+ end
25
+ @magento_path
26
+ end
27
+
28
+ def detect_clean
29
+ status = shell('git status -z', :capture => true, :strip => false)
30
+ status.split("\u0000").each do |line|
31
+ match = line.match(/^([\s\S]{2})\s+(.*)$/)
32
+ next if match.nil?
33
+
34
+ if ![' ', '?'].include?($1[0]) || $2.start_with?(magento_path)
35
+ raise Hem::UserError.new "Please remove all files from the git index, and stash all changes in '#{magento_path}' before continuing"
36
+ end
37
+ end
38
+ end
39
+
40
+ def detect_version
41
+ config_dirty = false
42
+ magento_version_file = "#{magento_path}/app/Mage.php"
43
+
44
+ if Hem.project_config[:magento_edition].nil?
45
+ magento_edition = nil
46
+ if magento_version_file
47
+ args = [ "php -r \"require '#{magento_version_file}'; echo Mage::getEdition();\""]
48
+
49
+ magento_edition = vm_shell(*args, :capture => true).to_s.downcase
50
+ end
51
+
52
+ edition_options = ['community', 'enterprise', 'professional', 'go']
53
+
54
+ unless edition_options.include? magento_edition
55
+ raise Hem::Error.new "Invalid Magento edition '#{magento_edition}' was found when calling Mage::getEdition(), skipping patches"
56
+ end
57
+
58
+ Hem.project_config[:magento_edition] = magento_edition
59
+ config_dirty = true
60
+ end
61
+
62
+ if Hem.project_config[:magento_version].nil?
63
+ magento_version = nil
64
+ if magento_version_file
65
+ args = [ "php -r \"require '#{magento_version_file}'; echo Mage::getVersion();\""]
66
+
67
+ magento_version = vm_shell(*args, :capture => true)
68
+ end
69
+
70
+ version_regex = /^\d+(\.\d+){3}$/
71
+
72
+ unless version_regex.match(magento_version)
73
+ raise Hem::Error.new "Invalid Magento version '#{magento_version}' was found when calling Mage::getVersion(), skipping patches"
74
+ end
75
+
76
+ Hem.project_config[:magento_version] = magento_version
77
+ config_dirty = true
78
+ end
79
+
80
+ if config_dirty
81
+ Hem::Config::File.save(Hem.project_config_file, Hem.project_config)
82
+ end
83
+ end
84
+
85
+ def detect_tools
86
+ use_vm = shell("which which", :exit_status => true) != 0
87
+
88
+ tools = ['patch', 'sed']
89
+ tools_command = tools.map {|tool| "which #{tool}"}.join " && "
90
+ status = 0
91
+
92
+ unless use_vm
93
+ status = shell(tools_command, :exit_status => true)
94
+ use_vm = status != 0
95
+ end
96
+
97
+ if use_vm
98
+ status = vm_shell(tools_command, :exit_status => true)
99
+ end
100
+
101
+ if status != 0
102
+ raise Hem::UserError.new "Please make sure '#{tools.join(',')}' is installed on your host or VM before continuing"
103
+ end
104
+
105
+ use_vm
106
+ end
107
+
108
+ desc "Apply patches to Magento"
109
+ task "apply" do
110
+ detect_clean
111
+ detect_version
112
+
113
+ config = Hem.project_config
114
+
115
+ sync = Hem::Lib::S3::Sync.new(Hem.aws_credentials)
116
+
117
+ patches_path = "#{Hem.project_path}/tools/patches"
118
+ incoming_path = "#{patches_path}/incoming"
119
+
120
+ Hem.ui.success("Downloading Magento #{config[:magento_edition].capitalize} #{config[:magento_version]} patches")
121
+ changes = sync.sync(
122
+ "s3://inviqa-assets-magento/#{config[:magento_edition]}/patches/#{config[:magento_version]}/",
123
+ "#{incoming_path}/",
124
+ :delete => false
125
+ )
126
+ Hem.ui.separator
127
+
128
+ use_vm = false
129
+ use_vm = detect_tools if Dir.glob("#{incoming_path}/*.sh").length > 0
130
+
131
+ patch_files = Dir.glob("#{incoming_path}/*.{sh,patch,diff}")
132
+
133
+ Hem.ui.success("#{patch_files.length} new patches found")
134
+
135
+ Hem.ui.separator
136
+
137
+ patch_files.each do |file|
138
+ filename = File.basename(file)
139
+ base_filename = File.basename(filename, File.extname(filename))
140
+
141
+ if File.exist?("#{patches_path}/#{filename}")
142
+ Hem.ui.debug("Patch #{filename} has already been applied, so skipping it")
143
+
144
+ File.delete file
145
+ next
146
+ end
147
+
148
+ if File.exist?("#{patches_path}/#{base_filename}.skip")
149
+ File.delete file
150
+ next
151
+ end
152
+
153
+ Hem.ui.success("Applying patch #{filename}")
154
+
155
+ yaml_file = File.join(File.dirname(file), base_filename + ".yaml")
156
+
157
+ metadata = {
158
+ 'commit_message' => "Apply Magento patch #{filename}"
159
+ }
160
+ if File.exist?(yaml_file)
161
+ metadata = Hem::Config::File.load(yaml_file)
162
+ end
163
+
164
+ Hem.ui.info(metadata['description']) unless metadata['description'].nil?
165
+
166
+ patch_options = %w( yes never skip )
167
+ answer = Hem.ui.ask_choice('Do you want to apply this patch?', patch_options)
168
+
169
+ if answer == 'skip'
170
+ next
171
+ end
172
+
173
+ if answer == 'never'
174
+ File.delete file
175
+ File.write("#{patches_path}/#{base_filename}.skip", '')
176
+
177
+ shell "git add '#{patches_path}/#{base_filename}.skip'"
178
+ shell "git commit -m 'Add a skip file for patch #{filename}'"
179
+ next
180
+ end
181
+
182
+ if /\.sh$/.match(file)
183
+ File.rename file, "#{magento_path}/#{filename}"
184
+ file = "#{magento_path}/#{filename}"
185
+ if use_vm
186
+ vm_shell "cd #{magento_path} && sh #{filename}", :realtime => true, :indent => 2
187
+ else
188
+ shell "cd #{magento_path} && sh #{filename}", :realtime => true, :indent => 2
189
+ end
190
+ else
191
+ shell "git apply --directory #{magento_path} #{file}"
192
+ end
193
+ File.rename file, "#{patches_path}/#{filename}"
194
+ shell "git add #{magento_path}"
195
+ shell "git add #{patches_path}/#{filename}"
196
+
197
+ if File.exist?(yaml_file)
198
+ yaml_filename = File.basename(yaml_file)
199
+ File.rename yaml_file, "#{patches_path}/#{yaml_filename}"
200
+ shell "git add #{patches_path}/#{yaml_filename}"
201
+ end
202
+ shell "git commit -m #{metadata['commit_message'].shellescape}"
203
+
204
+ Hem.ui.separator
205
+ end
206
+
207
+ Hem.ui.success("Finished applying #{patch_files.length} patches")
208
+ end
209
+ end
210
+
211
+ desc "Setup script tasks"
212
+ namespace :'setup-scripts' do
213
+ desc "Run magento setup scripts"
214
+ task :run => ['tools:n98magerun'] do
215
+ Hem.ui.success "Running setup scripts"
216
+ vm_shell("bin/n98-magerun.phar cache:clean config", :realtime => true, :indent => 2)
217
+ vm_shell("bin/n98-magerun.phar sys:setup:incremental -n", :realtime => true, :indent => 2)
218
+ Hem.ui.separator
219
+ end
220
+ end
221
+
222
+ desc "Cache tasks"
223
+ namespace :cache do
224
+ desc "Clear cache"
225
+ task :clear => ['tools:n98magerun'] do
226
+ Hem.ui.success "Clearing magento cache"
227
+ vm_shell("bin/n98-magerun.phar cache:flush", :realtime => true, :indent => 2)
228
+ Hem.ui.separator
229
+ end
230
+ end
231
+
232
+ desc "Configuration related tasks"
233
+ namespace :config do
234
+ desc "Configure magento base URLs"
235
+ task :'configure-urls' => ['tools:n98magerun'] do
236
+ Hem.ui.success "Configuring magento base urls"
237
+ domain = Hem.project_config.hostname
238
+ vm_shell("bin/n98-magerun.phar config:set web/unsecure/base_url 'http://#{domain}/'", :realtime => true, :indent => 2)
239
+ vm_shell("bin/n98-magerun.phar config:set web/secure/base_url 'https://#{domain}/'", :realtime => true, :indent => 2)
240
+ Hem.ui.separator
241
+ end
242
+
243
+ desc "Enable magento errors"
244
+ task :'enable-errors' do
245
+ error_config = File.join(Hem.project_path, 'public/errors/local.xml')
246
+
247
+ FileUtils.cp(
248
+ error_config + ".sample",
249
+ error_config
250
+ ) unless File.exists? error_config
251
+ end
252
+
253
+ desc "Create admin user"
254
+ task :'create-admin-user' do
255
+ initialized = vm_shell("bin/n98-magerun.phar admin:user:list | grep admin", :exit_status => true) == 0
256
+ unless initialized
257
+ Hem.ui.success "Creating admin user"
258
+ vm_shell("bin/n98-magerun.phar admin:user:create admin '' admin admin admin", :realtime => true, :indent => 2)
259
+ Hem.ui.separator
260
+ end
261
+ end
262
+
263
+ desc "Enable rewrites"
264
+ task :'enable-rewrites' do
265
+ Hem.ui.success "Enabling rewrites"
266
+ vm_shell("bin/n98-magerun.phar config:set web/seo/use_rewrites 1", :realtime => true, :indent => 2)
267
+ Hem.ui.separator
268
+ end
269
+ end
270
+
271
+ desc "Initializes magento specifics on the virtual machine after a fresh build"
272
+ task :'initialize-vm' => [
273
+ 'magento:config:enable-errors',
274
+ 'tools:n98magerun',
275
+ 'magento:setup-scripts:run',
276
+ 'magento:config:configure-urls',
277
+ 'magento:config:create-admin-user',
278
+ 'magento:config:enable-rewrites',
279
+ 'magento:cache:clear'
280
+ ]
281
+ end
@@ -0,0 +1,6 @@
1
+ namespace :ops do
2
+ task 'generate-self-signed-cert', [ 'domain' ] do |task, args|
3
+ cert = Hem::Lib::SelfSignedCertGenerator.generate args[:domain]
4
+ puts "Key:\n#{cert[:key]}\nCert:\n#{cert[:cert]}\n"
5
+ end
6
+ end
@@ -0,0 +1,45 @@
1
+ desc 'Perform pull request operations'
2
+ namespace :pr do
3
+ desc 'Create a new pull request'
4
+ task :create do
5
+ source_branch = Hem.ui.ask 'Source branch', default: (Hem::Helper.shell 'git rev-parse --abbrev-ref HEAD', :capture => true)
6
+ target_branch = Hem.ui.ask 'Target branch', default: 'develop'
7
+
8
+ pr_content = <<-prbody
9
+ # The line below this comment is the title of your pull request. Keep it short and on a single line.
10
+ PR_TITLE
11
+
12
+ # All text below this comment will appear as the body of the pull request.
13
+ # If your project has a DoD.md in the project root, it will be automatically included.
14
+ # Any line starting with a hash (comment) will be ignored
15
+
16
+ PR_DOD
17
+ prbody
18
+
19
+ pr_content['PR_TITLE'] = Hem::Helper.shell 'git log -1 --pretty=%B', :capture => true
20
+
21
+ dod_path = Hem::Helper.locate('DoD.md')
22
+
23
+ if dod_path && !dod_path.empty?
24
+ dod_file = File.open dod_path[0]
25
+ pr_content['PR_DOD'] = dod_file.read
26
+ dod_file.close
27
+ else
28
+ pr_content['PR_DOD'] = '# No DoD.md file found, add one to your project root.'
29
+ end
30
+
31
+ pr_body = Hem.ui.editor(pr_content).lines.reject{ |line| line[0] == '#' }.join
32
+
33
+ pr_title = pr_body.lines.to_a[0]
34
+
35
+ pr_body = pr_body.lines.to_a[1..-1].join
36
+
37
+ git_parts = Hem::Helper.parse_github_url(Hem.project_config.git_url)
38
+ repo = "#{git_parts[:owner]}/#{git_parts[:repo]}"
39
+
40
+ api = Hem::Lib::Github::Api.new
41
+ pr_url = api.create_pull_request(repo, target_branch, source_branch, pr_title, pr_body)
42
+
43
+ Hem::ui.success "Pull request created: #{pr_url}"
44
+ end
45
+ end
@@ -0,0 +1,61 @@
1
+
2
+ desc "Project seed commands"
3
+ namespace :seed do
4
+
5
+ desc "Create a new project from a seed repository"
6
+
7
+ option '-g=', '--git-url=', 'Git repository for project'
8
+ option '-s=', '--seed=', 'Seed name or URL to use'
9
+ option '-b=', '--branch=', 'Seed branch to use'
10
+ option '-d=', '--data=', 'Seed data to save to the project hem configuration', :as => Hash
11
+
12
+ task :plant, [ :name ] do |t, args|
13
+ name = args[:name]
14
+
15
+ Hem.project_path = File.join(Dir.pwd, name)
16
+
17
+ raise Hem::UserError.new "Name must match sprint zero guidelines" unless name.match /[a-z0-9\-]+/
18
+ raise Hem::UserError.new "#{Hem.project_path} already exists!" if File.exists? Hem.project_path
19
+
20
+ config = {
21
+ :name => name,
22
+ :project_path => Hem.project_path,
23
+ :git_url => t.opts[:'git-url'] || Hem.ui.ask("Repository URL", default: "git@github.com:inviqa/#{name}"),
24
+ :ref => t.opts[:branch] || 'master'
25
+ }
26
+
27
+ seed_options = %w( default magento symfony custom )
28
+
29
+ seed_name = t.opts[:seed] || Hem.ui.ask_choice('Project seed', seed_options, default: 'default')
30
+ use_short_seed_name = true
31
+
32
+ if seed_name == 'custom'
33
+ seed_name = Hem.ui.ask('Please enter a git url or a path to a local git checkout containing the seed')
34
+ use_short_seed_name = false
35
+ end
36
+
37
+ config[:seed] = {
38
+ :name => File.basename(seed_name, '.git'),
39
+ :url => Hem::Lib::Seed::Seed.name_to_url(seed_name, :use_short_seed_name => use_short_seed_name)
40
+ }
41
+
42
+ unless t.opts[:data].nil?
43
+ data = t.opts[:data].inject({}){|hash,(k,v)| hash[k.to_sym] = v; hash}
44
+ config.merge!(data)
45
+ end
46
+
47
+ seed = Hem::Lib::Seed::Seed.new(
48
+ File.join(Hem.seed_cache_path, config[:seed][:name]),
49
+ config[:seed][:url]
50
+ )
51
+
52
+ config[:vm_ip] = seed.vm_ip
53
+
54
+ Hem::Lib::Seed::Project.new().setup(seed, config)
55
+
56
+ Hem.ui.separator
57
+ Hem.ui.success "Your new project is available in #{Hem.project_path}."
58
+ Hem.ui.success "You will need to review the initial commit and if all is well, push the repository to github using `git push origin --all`."
59
+ Hem.ui.separator
60
+ end
61
+ end
@@ -0,0 +1,45 @@
1
+ desc "Internal hem debugging tools"
2
+ hidden true
3
+ namespace 'self' do
4
+
5
+ desc "REPL"
6
+ task :repl do
7
+ require 'pry'
8
+ Pry.config.prompt = if STDIN.tty?
9
+ proc { 'hem > '}
10
+ else
11
+ proc { '' }
12
+ end
13
+ pry
14
+ end
15
+
16
+ desc "Tasks for debugging hem"
17
+ namespace 'debug' do
18
+ desc "Display project paths"
19
+ project_only
20
+ task "paths" do
21
+ Hem.ui.info "<%=color('Project path:', :green)%> " + Hem.project_path
22
+ {
23
+ :gemfile => "*Gemfile",
24
+ :vagrantfile => "*Vagrantfile",
25
+ :cheffile => "*Cheffile",
26
+ :berksfile => "*Berksfile",
27
+ :'composer.json' => "composer.json"
28
+ }.each do |k,v|
29
+ path = nil
30
+ locate v do |file, full_file|
31
+ path = full_file
32
+ end
33
+ Hem.ui.info "<%=color('#{k.to_s}:', :green) %> #{path.nil? ? "none" : path}"
34
+ end
35
+ end
36
+
37
+ desc "Locate"
38
+ project_only
39
+ task "locate", [ :arg ] do |task, args|
40
+ locate args[:arg] do |file, full_file|
41
+ puts full_file
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ namespace 'shell-init' do
2
+ def posix_export_path
3
+ Hem.ui.output %Q(export PATH="#{ENV['PATH']}")
4
+ end
5
+
6
+ def fish_export_path
7
+ Hem.ui.output %Q(set -gx PATH "#{ENV['PATH'].split(':').join('" "')}" 2>/dev/null;)
8
+ end
9
+
10
+ task 'bash' do
11
+ posix_export_path
12
+ end
13
+
14
+ task 'sh' do
15
+ posix_export_path
16
+ end
17
+
18
+ task 'zsh' do
19
+ posix_export_path
20
+ end
21
+
22
+ task 'fish' do
23
+ fish_export_path
24
+ end
25
+ end
@@ -0,0 +1,76 @@
1
+ desc "System configuration related commands"
2
+ namespace :system do
3
+
4
+ desc "Shell completion related commands"
5
+ namespace :completions do
6
+
7
+ desc "Install shell completion helpers"
8
+ option '-f', '--fish', 'Install completions for FISH'
9
+ option '-b', '--bash', 'Install completions for Bash'
10
+ option '-z', '--zsh', 'Install completions for ZSH'
11
+ task "install" do |task|
12
+ if task.opts[:fish]
13
+ script = <<-EOF
14
+ function __hem_completion -d "Create hem completions"
15
+ set -l cache_dir "/tmp/fish_hem_completion_cache"
16
+ mkdir -p $cache_dir
17
+ set -l hashed_pwd (ruby -r 'digest' -e 'puts Digest::MD5.hexdigest(`pwd`)')
18
+ set -l hem_cache_file "$cache_dir/$hashed_pwd"
19
+
20
+ if not test -f "$hem_cache_file"
21
+ hem system completions fish --skip-host-checks > "$hem_cache_file"
22
+ end
23
+
24
+ cat "$hem_cache_file"
25
+ end
26
+
27
+ function __hem_scope_test -d "Hem scoped completion test"
28
+ set cmd (commandline -opc)
29
+ if [ "$cmd" = "$argv" ]
30
+ return 0
31
+ end
32
+ return 1
33
+ end
34
+
35
+ eval (__hem_completion)
36
+ EOF
37
+ target = File.join(ENV['HOME'], '.config/fish/completions/hem.fish')
38
+ FileUtils.mkdir_p(File.dirname(target))
39
+ File.write(target, script)
40
+ end
41
+
42
+ if task.opts[:bash]
43
+ raise "Bash completions not yet implemented"
44
+ end
45
+
46
+ if task.opts[:zsh]
47
+ raise "ZSH completions not yet implemented"
48
+ end
49
+ end
50
+
51
+ desc "Display FISH shell completion commands"
52
+ task :fish do
53
+ Hem.cli.slop.options.each do |option|
54
+ short = option.short.nil? ? '' : "-s #{option.short}"
55
+ long = option.long.nil? ? '' : "-l #{option.long}"
56
+ arg = option.config[:argument] ? '' : '-x'
57
+ puts "complete #{arg} -c hem #{short} #{long} --description '#{option.description}';"
58
+ end
59
+
60
+ map = Hem.cli.help_formatter.command_map
61
+ map.each do |k, v|
62
+ next if v.description.nil? || v.description.empty?
63
+ k = k.split(':')
64
+ k.unshift 'hem'
65
+ c = k.pop
66
+ puts "complete -x -c hem -n '__hem_scope_test #{k.join(' ')}' -a #{c} --description '#{v.description}';"
67
+ v.options.each do |option|
68
+ short = option.short.nil? ? '' : "-s #{option.short}"
69
+ long = option.long.nil? ? '' : "-l #{option.long}"
70
+ arg = option.config[:argument] ? '' : '-x'
71
+ puts "complete #{arg} -c hem -n '__hem_scope_test #{k.concat([c]).join(' ')}' #{short} #{long} --description '#{option.description}';"
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,18 @@
1
+ desc "System configuration related commands"
2
+ namespace :system do
3
+
4
+ desc "Check system configuration for potential problems"
5
+ task :check do
6
+ Hem::Lib::HostCheck.check.each do |k,v|
7
+ name = k.to_s.gsub('_', ' ')
8
+ name[0] = name[0].upcase
9
+
10
+ if v == :ok
11
+ Hem.ui.success "#{name}: OK"
12
+ else
13
+ Hem.ui.error "#{name}: FAILED\n"
14
+ Hem.ui.warning v.advice.gsub(/^/, ' ')
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ desc "Tasks to retrieve common tools"
2
+ hidden
3
+ namespace :tools do
4
+
5
+ desc "Fetch composer"
6
+ task :composer do
7
+ bin_file = File.join(Hem.project_bin_path, "composer.phar")
8
+ unless File.exists?(bin_file)
9
+ Hem.ui.success "Getting composer"
10
+ FileUtils.mkdir_p File.dirname(bin_file)
11
+ vm_shell "cd bin && php -r \"readfile('https://getcomposer.org/installer');\" | php", :realtime => true, :indent => 2
12
+ else
13
+ Hem.ui.success "Composer already available in bin/composer.phar"
14
+ end
15
+ Hem.ui.separator
16
+ end
17
+ end