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.
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