swiftly 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.gitignore +2 -0
  4. data/Dropbox/Development/www/Swiftlyfile +8 -0
  5. data/Gemfile +3 -0
  6. data/bin/swiftly +15 -0
  7. data/lib/swiftly/Rakefile +38 -0
  8. data/lib/swiftly/app_module.rb +320 -0
  9. data/lib/swiftly/clean.rb +33 -0
  10. data/lib/swiftly/cli.rb +36 -0
  11. data/lib/swiftly/config.rb +131 -0
  12. data/lib/swiftly/config_global_generator.rb +35 -0
  13. data/lib/swiftly/config_plugins_generator.rb +33 -0
  14. data/lib/swiftly/config_project_generator.rb +32 -0
  15. data/lib/swiftly/config_swiftlyfile_generator.rb +34 -0
  16. data/lib/swiftly/config_templates_generator.rb +33 -0
  17. data/lib/swiftly/configure.rb +27 -0
  18. data/lib/swiftly/configure_all.rb +181 -0
  19. data/lib/swiftly/configure_local.rb +34 -0
  20. data/lib/swiftly/configure_production.rb +42 -0
  21. data/lib/swiftly/configure_staging.rb +41 -0
  22. data/lib/swiftly/create.rb +94 -0
  23. data/lib/swiftly/create_git.rb +40 -0
  24. data/lib/swiftly/create_project.rb +67 -0
  25. data/lib/swiftly/create_wordpress.rb +185 -0
  26. data/lib/swiftly/database.rb +213 -0
  27. data/lib/swiftly/destroy.rb +53 -0
  28. data/lib/swiftly/enable.rb +13 -0
  29. data/lib/swiftly/enable_wordpress.rb +22 -0
  30. data/lib/swiftly/generate.rb +23 -0
  31. data/lib/swiftly/generate_post_type.rb +50 -0
  32. data/lib/swiftly/init.rb +130 -0
  33. data/lib/swiftly/packages.rb +137 -0
  34. data/lib/swiftly/project.rb +127 -0
  35. data/lib/swiftly/pull.rb +25 -0
  36. data/lib/swiftly/push.rb +60 -0
  37. data/lib/swiftly/rollback.rb +78 -0
  38. data/lib/swiftly/setup.rb +34 -0
  39. data/lib/swiftly/ssh.rb +36 -0
  40. data/lib/swiftly/templates/config_global.erb +3 -0
  41. data/lib/swiftly/templates/config_project.erb +11 -0
  42. data/lib/swiftly/templates/gitignore.erb +7 -0
  43. data/lib/swiftly/templates/post_type.erb +98 -0
  44. data/lib/swiftly/templates/swiftlyfile.erb +21 -0
  45. data/lib/swiftly/version.rb +4 -0
  46. data/swiftly.gemspec +61 -0
  47. data/test/test_swiftly_spec.rb +18 -0
  48. metadata +175 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d920ce23bc206002d40268d1dea454b6d82b7d87
4
+ data.tar.gz: 934149c743f4039d829c6a5d635e85b5342d1b1a
5
+ SHA512:
6
+ metadata.gz: 99de03c5e7da92d0f66966e1475236f4a0fc93825ffe7261746160caa6ec637f96e291ace162900a3562edbdf31d284c95cc35490d28040ddcfaece60ea63bd5
7
+ data.tar.gz: dc0ae651c5dabba3197debe8a7232c861a14e5be3df674d0932cc901f35bd34ff6a41c6fa48ef5ff8be19853dbbb7708ae5d67f85ec2b783fc8b7d5e4f134626
data/.DS_Store ADDED
Binary file
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ Gemfile.lock
2
+ *.gem
@@ -0,0 +1,8 @@
1
+ # :wordpress:
2
+ # :template:
3
+ # - :name:
4
+ # :remote: https://github.com/micalexander/mask/archive/master.zip
5
+ # :status: :disabled
6
+ # :plugins:
7
+ # - advanced-custom-fields-pro/acf.php
8
+ # - ambrosite-body-class-enhanced/ambrosite-body-class.php
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/bin/swiftly ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ APP_ROOT = File.expand_path("../../lib",__FILE__)
4
+ $:.unshift( APP_ROOT )
5
+
6
+ require 'yaml'
7
+ require 'swiftly/cli'
8
+ require 'swiftly/init'
9
+
10
+ Swiftly::Init.start unless File.exist? File.join( Dir.home, ".swiftly" )
11
+
12
+ global_config = YAML.load_file File.join( Dir.home, ".swiftly" ) unless !File.exists? File.join( Dir.home, ".swiftly" )
13
+
14
+ Swiftly::Init.start unless File.exist? File.join( global_config[:sites_path], "Swiftlyfile" )
15
+ Swiftly::CLI.start unless !File.exist? File.join( global_config[:sites_path], "Swiftlyfile" )
@@ -0,0 +1,38 @@
1
+ require 'mina/git'
2
+ # require 'mina/rollback'
3
+
4
+ set :repository, ENV['repo']
5
+ set :branch, ENV['branch']
6
+
7
+ set :user, ENV['user']
8
+ set :domain, ENV['domain']
9
+ set :deploy_to, ENV['path']
10
+
11
+ set :shared_paths, ['wp-content/uploads']
12
+ set :forward_agent, true
13
+
14
+ task :setup => :environment do
15
+
16
+ queue! %[mkdir -p "#{deploy_to}/shared/wp-content/uploads"]
17
+
18
+ end
19
+
20
+ task :deploy => :environment do
21
+
22
+ deploy do
23
+
24
+ # Put things that will set up an empty directory into a fully set-up
25
+ # instance of your project.
26
+ invoke :'git:clone'
27
+ invoke :'deploy:link_shared_paths'
28
+
29
+ end
30
+ end
31
+
32
+ desc "Rollback to previous verison."
33
+
34
+ task :rollback => :environment do
35
+
36
+ invoke :'deploy:rollback'
37
+
38
+ end
@@ -0,0 +1,320 @@
1
+ require 'Thor'
2
+ require 'pathname'
3
+ require 'awesome_print'
4
+
5
+ class String
6
+
7
+ # Unindent heredocs so they look better
8
+ def unindent
9
+
10
+ gsub(/^[\t|\s]*|[\t]*/, "")
11
+
12
+ end
13
+ end
14
+
15
+ module Swiftly
16
+ module Helpers
17
+
18
+ thor = Thor.new
19
+
20
+ def zip zipfile_name, directory
21
+
22
+ Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
23
+
24
+ Dir[ File.join(directory, '**', '**') ].each do |file|
25
+
26
+ zipfile.add(file.sub( directory, '' ), file )
27
+
28
+ end
29
+ end
30
+ end
31
+
32
+ def unzip zipfile_name, directory
33
+
34
+ Zip::File.open( zipfile_name ) do |zipfile|
35
+
36
+ zipfile.each do |entry|
37
+
38
+ path = entry.name.to_s.gsub(/^.+?#{File::SEPARATOR}/, "#{directory}#{File::SEPARATOR}")
39
+
40
+ say_status "unzip", zipfile.extract( entry, path.to_s ) unless File.exist?(path)
41
+
42
+ end
43
+ end
44
+ end
45
+
46
+ def find_and_replace(hash)
47
+
48
+ if hash[:file] == true
49
+
50
+ if File.exists? hash[:input]
51
+
52
+ replace = File.read(hash[:input]).gsub(hash[:pattern], hash[:output])
53
+
54
+ File.open(hash[:input], "w") {|file| file.puts replace }
55
+
56
+ return hash[:input]
57
+
58
+ else
59
+
60
+ say_status "#{APP_NAME}:", "file #{hash[:input]} does not exist", :yellow
61
+
62
+ end
63
+
64
+ else
65
+
66
+ return hash[:input].gsub(hash[:pattern], hash[:output])
67
+
68
+ end
69
+ end
70
+
71
+ def find_and_replace_all(array)
72
+
73
+ array.each do |hash|
74
+
75
+ find_and_replace(hash)
76
+
77
+ end
78
+ end
79
+
80
+ def return_cmd cmd
81
+
82
+ cmd_return = ""
83
+
84
+ Open3.popen2e(cmd) do |stdin, stdout_err, wait_thr|
85
+
86
+ exit_status = wait_thr.value
87
+
88
+ while line = stdout_err.gets
89
+
90
+ cmd_return = line
91
+
92
+ end
93
+
94
+ say #spacer
95
+
96
+ unless exit_status.success?
97
+
98
+ # TURN ON FOR SIMPLE DEBUGGING
99
+ # abort "\n\s\s\s\s#{APP_NAME}: command failed - #{cmd}\n\n"
100
+
101
+ end
102
+ end
103
+
104
+ cmd_return
105
+
106
+ end
107
+
108
+ def swiftly_shell(cmd, command_status = nil)
109
+
110
+ Open3.popen2e(cmd) do |stdin, stdout_err, wait_thr|
111
+
112
+ exit_status = wait_thr.value
113
+
114
+ while line = stdout_err.gets
115
+
116
+ say_status cmd.split( ' ' ).first.gsub(/^mina/, APP_NAME), line.gsub(/^mina/, APP_NAME).gsub(/----->/, " \033[34m\e[1m#{command_status}\e[0m\033[0m")
117
+
118
+ end
119
+
120
+ say #spacer
121
+
122
+ unless exit_status.success?
123
+
124
+ # TURN ON FOR SIMPLE DEBUGGING
125
+ # abort "\n\s\s\s\s#{APP_NAME}: command failed - #{cmd}\n\n"
126
+
127
+ end
128
+ end
129
+ end
130
+
131
+ def verifiy_mina_credentials environment, settings, verbage
132
+
133
+ if settings[environment][:repo].nil?
134
+
135
+ say_status "#{APP_NAME}:", "Could not #{verbage} to #{environment} environment, because the repository is not set.", :red
136
+ say #spacer
137
+
138
+ end
139
+
140
+ if settings[environment][:branch].nil?
141
+
142
+ say_status "#{APP_NAME}:", "Could not #{verbage} to #{environment} environment, because the branch is not set.", :red
143
+ say #spacer
144
+
145
+ end
146
+
147
+ if settings[environment][:ssh_user].nil?
148
+
149
+ say_status "#{APP_NAME}:", "Could not #{verbage} to #{environment} environment, because the ssh user is not set.", :red
150
+ say #spacer
151
+
152
+ end
153
+
154
+ if settings[environment][:ssh_path].nil?
155
+
156
+ say_status "#{APP_NAME}:", "Could not #{verbage} to #{environment} environment, because the ssh path is not set.", :red
157
+ say #spacer
158
+
159
+ end
160
+
161
+ if settings[environment][:domain].nil?
162
+
163
+ say_status "#{APP_NAME}:", "Could not #{verbage} to #{environment} environment, because the domain is not set.", :red
164
+ say #spacer
165
+
166
+ end
167
+
168
+ abort if settings[environment][:repo].nil?
169
+ abort if settings[environment][:branch].nil?
170
+ abort if settings[environment][:ssh_user].nil?
171
+ abort if settings[environment][:domain].nil?
172
+ abort if settings[environment][:ssh_path].nil?
173
+
174
+ end
175
+
176
+ def mina cmd, environment, project_name
177
+
178
+ settings = Swiftly::Project.settings( project_name )
179
+
180
+ inside settings[:project][:path] do
181
+
182
+ cmd_status = cmd.include?(':') ? cmd.split(':').last : cmd
183
+
184
+ mina = <<-EOF.unindent
185
+ mina #{cmd} \
186
+ -f '#{File.join(File.dirname(__FILE__), "Rakefile")}' \
187
+ repo='#{settings[environment][:repo]}' \
188
+ branch='#{settings[environment][:branch]}' \
189
+ user='#{settings[environment][:ssh_user]}' \
190
+ domain='#{settings[environment][:domain].gsub(/http:\/\//, '')}' \
191
+ path='#{settings[environment][:ssh_path]}'
192
+ EOF
193
+
194
+ if cmd == 'ssh'
195
+
196
+ exec mina
197
+
198
+ else
199
+
200
+ swiftly_shell mina, cmd_status
201
+
202
+ end
203
+ end
204
+ end
205
+
206
+ def update_setting environment, setting, value
207
+
208
+ config = Swiftly::Config.load :swiftly
209
+ config[environment][setting] = value
210
+
211
+ File.open(Swiftly::Config.swiftlyfile,'w') do |h|
212
+
213
+ h.write config.to_yaml
214
+
215
+ end
216
+ end
217
+
218
+ def update_setting_dialog( environment, setting, value )
219
+
220
+ nouns = {
221
+ domain: 'domain',
222
+ db_host: 'host',
223
+ db_user: 'username',
224
+ db_pass: 'password'
225
+ }
226
+
227
+ say # spacer
228
+
229
+ swiftly_setting = Swiftly::Config.load :swiftly
230
+ current_setting = swiftly[environment][setting]
231
+ current_value = current_setting.nil? ? 'nothing' : current_setting
232
+
233
+ say_status "#{APP_NAME}:", "The staging #{nouns[setting]} is currently set to #{current_value}.", :yellow
234
+
235
+ say # spacer
236
+
237
+ if value
238
+
239
+ if yes? "Are you sure you want to set it to (#{value})? [Y|n]", :yellow
240
+
241
+ update_setting environment, setting, value
242
+
243
+ new_swiftly_setting = Swiftly::Config.load :swiftly
244
+ new_setting = new_swiftly_setting[environment][setting]
245
+
246
+ say # spacer
247
+
248
+ say_status "#{APP_NAME}:", "Change successful! The value is set to #{new_setting}"
249
+
250
+ end
251
+
252
+ else
253
+
254
+ value = ask "\n--> What would you like to set it to?", :yellow
255
+
256
+ say # spacer
257
+
258
+ if value == ""
259
+
260
+ say_status "#{APP_NAME}:", "Change unsuccessful, #{nouns[setting]} is still set to #{current_value}", :yellow
261
+
262
+ else
263
+
264
+ update_setting environment, setting, value
265
+
266
+ new_swiftly_setting = Swiftly::Config.load :swiftly
267
+ new_setting = new_swiftly_setting[environment][setting]
268
+
269
+ say # spacer
270
+
271
+ say_status "#{APP_NAME}:", "Change successful! #{nouns[setting]} is now set to #{new_setting}"
272
+
273
+ end
274
+ end
275
+ end
276
+
277
+ def fix_serialization file
278
+
279
+ Encoding.default_external = Encoding::UTF_8
280
+ Encoding.default_internal = Encoding::UTF_8
281
+ string = File.read file
282
+ fixed = fix_text string
283
+
284
+ open file, 'w' do |io|
285
+
286
+ io.write fixed
287
+
288
+ end
289
+
290
+ return file
291
+
292
+ end
293
+
294
+ # php escapes:
295
+ # "\\" #Backslash,
296
+ # '"' Double quotes,
297
+ # "\'" Single quotes,
298
+ # "\a" Bell/alert,
299
+ # "\b" Backspace,
300
+ # "\r" Carriage Return,
301
+ # "\n" New Line,
302
+ # "\s" Space,
303
+ # "\t" Tab
304
+ def fix_text string
305
+
306
+ pattern = /(s\s*:\s*)(\d+)((\s*:\\*["&])(.*?)(\\?\"\s*;))/
307
+ php_escapes = /(\\"|\\'|\\\\|\\a|\\b|\\n|\\r|\\s|\\t|\\v)/
308
+
309
+ string.gsub( pattern ) do |match|
310
+
311
+ head = $1
312
+ tail = $3
313
+ count = $5.bytesize - $5.scan(php_escapes).length
314
+
315
+ "#{head}#{count}#{tail}"
316
+ end
317
+ end
318
+ end
319
+ end
320
+
@@ -0,0 +1,33 @@
1
+ require 'swiftly/app_module'
2
+
3
+ module Swiftly
4
+ class Clean < Thor
5
+
6
+ include Thor::Actions
7
+ include Helpers
8
+
9
+ desc "staging PROJECT_NAME", "Clean production environment"
10
+
11
+ def staging( project_name )
12
+
13
+ settings = Swiftly::Project.settings( project_name )
14
+
15
+ verifiy_mina_credentials :staging, settings, 'clean the'
16
+
17
+ mina 'deploy:cleanup', :staging, project_name
18
+
19
+ end
20
+
21
+ desc "production PROJECT_NAME", "Clean production environment"
22
+
23
+ def production( project_name )
24
+
25
+ settings = Swiftly::Project.settings( project_name )
26
+
27
+ verifiy_mina_credentials :production, settings, 'clean the'
28
+
29
+ mina 'deploy:cleanup', :production, project_name
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,36 @@
1
+ require 'thor'
2
+ require 'json'
3
+ require 'swiftly/app_module'
4
+ require 'swiftly/config'
5
+ require 'swiftly/create'
6
+ require 'swiftly/configure'
7
+ require 'swiftly/push'
8
+ require 'swiftly/pull'
9
+ require 'swiftly/ssh'
10
+ require 'swiftly/clean'
11
+ require 'swiftly/setup'
12
+ require 'swiftly/rollback'
13
+ require 'swiftly/generate'
14
+ require 'swiftly/enable'
15
+ require 'swiftly/destroy'
16
+
17
+ module Swiftly
18
+ class CLI < Thor
19
+
20
+ include Thor::Actions
21
+ include Helpers
22
+
23
+ register Swiftly::Create, "create", "Create COMMAND PROJECT_NAME", "Create projects by passing a project name"
24
+ register Swiftly::Configure, "configure", "configure COMMAND", "Configure settings"
25
+ register Swiftly::Setup, "setup", "setup COMMAND PROJECT_NAME", "Setup [environment] on server"
26
+ register Swiftly::Push, "push", "push COMMAND PROJECT_NAME", "Push [environment] database and files to server"
27
+ register Swiftly::Pull, "pull", "pull COMMAND PROJECT_NAME", "Pull [environment] database and files to local"
28
+ register Swiftly::Rollback, "rollback", "rollback COMMAND PROJECT_NAME", "Rollback the [environment] database and files on server"
29
+ register Swiftly::SSH, "ssh", "ssh COMMAND PROJECT_NAME", "SSH into the [environment] server and cd into site path"
30
+ register Swiftly::Clean, "clean", "clean COMMAND PROJECT_NAME", "Clean the [environment] releases on server"
31
+ register Swiftly::Generate, "generate", "generate POSTTYPE FILTER PROJECT_NAME", "Generate a custom post type"
32
+ register Swiftly::Enable, "enable", "enable COMMAND FRAMEWORK", "Enable global framework intergrations"
33
+ register Swiftly::Destroy, "destroy", "destroy PROJECT_NAME", "Destroy local project!"
34
+
35
+ end
36
+ end
@@ -0,0 +1,131 @@
1
+ require 'yaml'
2
+ require 'swiftly/version'
3
+ require 'swiftly/app_module'
4
+
5
+ module Swiftly
6
+ class Config < Thor
7
+
8
+ include Helpers
9
+
10
+ no_commands do
11
+
12
+ def self.global_file
13
+
14
+ File.join(
15
+ Dir.home,
16
+ ".#{APP_NAME}"
17
+ ) unless !File.exists? File.join(
18
+ Dir.home,
19
+ ".#{APP_NAME}"
20
+ )
21
+
22
+ end
23
+
24
+ def self.swiftlyfile
25
+
26
+ global_config = self.load :global
27
+
28
+ File.join(
29
+ global_config[:sites_path],
30
+ "#{APP_NAME}file".capitalize
31
+ ) unless !File.exists? File.join(
32
+ global_config[:sites_path],
33
+ "#{APP_NAME}file".capitalize
34
+ )
35
+
36
+ end
37
+
38
+ def self.project_file project_name
39
+
40
+ global_config = self.load :global, project_name
41
+
42
+ File.join(
43
+ global_config[:sites_path],
44
+ project_name, 'config', 'config.yml'
45
+ ) unless !File.exists? File.join(
46
+ global_config[:sites_path],
47
+ project_name, 'config', 'config.yml'
48
+ )
49
+
50
+ end
51
+
52
+ def self.wp_config_file project_name
53
+
54
+ global_config = self.load :global, project_name
55
+
56
+ File.join(
57
+ global_config[:sites_path],
58
+ project_name,
59
+ "wp-config.php"
60
+ ) unless !File.exists? File.join(
61
+ global_config[:sites_path],
62
+ project_name,
63
+ "wp-config.php"
64
+ )
65
+
66
+ end
67
+
68
+ def self.load file, project_name = nil
69
+
70
+ case file
71
+ when :wp_config
72
+
73
+ if wp_config_file( project_name )
74
+
75
+ # load the wp-config file environment settings for wp-enabled environments
76
+ wp_local = File.read(
77
+ wp_config_file(
78
+ project_name
79
+ )
80
+ )[/\$local\s*?=[\s|\S]*?({[\s|\S]*?})/, 1]
81
+
82
+ wp_staging = File.read(
83
+ wp_config_file(
84
+ project_name
85
+ )
86
+ )[/\$staging\s*?=[\s|\S]*?({[\s|\S]*?})/, 1]
87
+
88
+ wp_production = File.read(
89
+ wp_config_file(
90
+ project_name
91
+ )
92
+ )[/\$production\s*?=[\s|\S]*?({[\s|\S]*?})/, 1]
93
+
94
+ if wp_local.nil? || wp_staging.nil? || wp_production.nil?
95
+
96
+ return {
97
+ local: {},
98
+ staging: {},
99
+ production: {}
100
+ }
101
+
102
+ end
103
+
104
+ load_hash = {
105
+ local: JSON.parse(wp_local).inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo},
106
+ staging: JSON.parse(wp_staging).inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo},
107
+ production: JSON.parse(wp_production).inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
108
+ }
109
+
110
+ end
111
+
112
+ when :project
113
+
114
+ load_hash = YAML.load_file( project_file( project_name ) )
115
+
116
+ when :swiftly
117
+
118
+ load_hash = YAML.load_file( swiftlyfile )
119
+
120
+ when :global
121
+
122
+ load_hash = YAML.load_file( global_file )
123
+
124
+ end
125
+
126
+ load_hash
127
+
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,35 @@
1
+ require "swiftly/version"
2
+ require "thor/group"
3
+
4
+ module Swiftly
5
+ class ConfigGlobalGenerator < Thor::Group
6
+
7
+ include Thor::Actions
8
+
9
+ argument :sites_path
10
+
11
+ desc "Handles the creation of the config file."
12
+
13
+ def self.source_root
14
+ File.dirname(__FILE__)
15
+ end
16
+
17
+ def create
18
+
19
+ @version = VERSION
20
+
21
+ template(
22
+ File.join(
23
+ 'templates',
24
+ 'config_global.erb'
25
+ ),
26
+ File.join(
27
+ Dir.home,
28
+ ".#{APP_NAME}"
29
+ ),
30
+ :verbose => false
31
+ )
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,33 @@
1
+ require "thor/group"
2
+
3
+ module Swiftly
4
+ class ConfigPluginsGenerator < Thor::Group
5
+
6
+ include Thor::Actions
7
+
8
+ desc "Handles the creation of the _plugins file."
9
+
10
+ def self.source_root
11
+ File.dirname(__FILE__)
12
+ end
13
+
14
+ def create
15
+
16
+ settings = Swiftly::Config.load :global
17
+
18
+ template(
19
+ File.join(
20
+ "templates",
21
+ "config_plugins.erb"
22
+ ),
23
+ File.join(
24
+ settings[:sites_path],
25
+ 'config',
26
+ 'plugins',
27
+ '_plugins.yml'
28
+ )
29
+ )
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ require "thor/group"
2
+
3
+ module Swiftly
4
+ class ConfigProjectGenerator < Thor::Group
5
+
6
+ include Thor::Actions
7
+
8
+ desc "Handles the creation of the config file."
9
+
10
+ def self.source_root
11
+
12
+ File.dirname(__FILE__)
13
+
14
+ end
15
+
16
+ def create( project_path )
17
+
18
+ template(
19
+ File.join(
20
+ 'templates',
21
+ 'config_project.erb'
22
+ ),
23
+ File.join(
24
+ project_path,
25
+ 'config',
26
+ 'config.yml'
27
+ )
28
+ )
29
+
30
+ end
31
+ end
32
+ end