whtt-eric-beet 0.6.10
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.
- data/Gemfile +12 -0
- data/Gemfile.lock +25 -0
- data/LICENSE +20 -0
- data/README.rdoc +13 -0
- data/Rakefile +59 -0
- data/TODO +25 -0
- data/VERSION +1 -0
- data/bin/beet +114 -0
- data/features/generating.feature +24 -0
- data/features/step_definitions/beet_steps.rb +7 -0
- data/features/step_definitions/common_steps.rb +172 -0
- data/features/support/common.rb +33 -0
- data/features/support/env.rb +25 -0
- data/lib/beet.rb +13 -0
- data/lib/beet/capistrano.rb +14 -0
- data/lib/beet/command_execution.rb +56 -0
- data/lib/beet/executor.rb +236 -0
- data/lib/beet/file_system.rb +163 -0
- data/lib/beet/files/swfupload/images/cancelbutton.gif +0 -0
- data/lib/beet/files/swfupload/images/header-bg.jpg +0 -0
- data/lib/beet/files/swfupload/images/logo.gif +0 -0
- data/lib/beet/files/swfupload/js/handlers.js +290 -0
- data/lib/beet/gem_location_map.rb +65 -0
- data/lib/beet/interaction.rb +47 -0
- data/lib/beet/logger.rb +44 -0
- data/lib/beet/rails.rb +175 -0
- data/lib/beet/recipes/passenger/vhost.rb +17 -0
- data/lib/beet/recipes/rack/middleware.rb +17 -0
- data/lib/beet/recipes/rails/auth/authlogic.rb +302 -0
- data/lib/beet/recipes/rails/auth/clearance.rb +22 -0
- data/lib/beet/recipes/rails/auth/devise.rb +22 -0
- data/lib/beet/recipes/rails/clean_files.rb +4 -0
- data/lib/beet/recipes/rails/cms/bcms_blog.rb +21 -0
- data/lib/beet/recipes/rails/cms/bcms_event.rb +24 -0
- data/lib/beet/recipes/rails/css/blueprint.rb +5 -0
- data/lib/beet/recipes/rails/css/compass.rb +35 -0
- data/lib/beet/recipes/rails/css/nifty_layout.rb +5 -0
- data/lib/beet/recipes/rails/css/reset.rb +10 -0
- data/lib/beet/recipes/rails/db/mongo.rb +57 -0
- data/lib/beet/recipes/rails/db/mysql.rb +47 -0
- data/lib/beet/recipes/rails/db/postgres.rb +52 -0
- data/lib/beet/recipes/rails/git.rb +23 -0
- data/lib/beet/recipes/rails/jquery.rb +11 -0
- data/lib/beet/recipes/rails/swfupload.rb +305 -0
- data/lib/beet/recipes/rails/testing/rspec.rb +3 -0
- data/lib/beet/recipes/rails/testing/shoulda.rb +1 -0
- data/lib/beet/recipes/rails3/admin_interface/active_scaffold.rb +10 -0
- data/lib/beet/recipes/rails3/admin_interface/rails_admin.rb +9 -0
- data/lib/beet/recipes/rails3/auth/devise.rb +17 -0
- data/lib/beet/recipes/rails3/clean_files.rb +3 -0
- data/lib/beet/recipes/rails3/css/boilerplate.rb +41 -0
- data/lib/beet/recipes/rails3/css/reset.rb +10 -0
- data/lib/beet/recipes/rails3/css/sass.rb +3 -0
- data/lib/beet/recipes/rails3/db/mysql.rb +35 -0
- data/lib/beet/recipes/rails3/file_uploads/paperclip.rb +29 -0
- data/lib/beet/recipes/rails3/git.rb +16 -0
- data/lib/beet/recipes/rails3/jammit.rb +26 -0
- data/lib/beet/recipes/rails3/js/jquery.rb +12 -0
- data/lib/beet/recipes/rails3/markup/haml.rb +3 -0
- data/lib/beet/recipes/rails3/testing/cucumber.rb +19 -0
- data/lib/beet/recipes/rails3/testing/rspec.rb +40 -0
- data/lib/beet/recipes/standalone/hades.rb +61 -0
- data/lib/beet/recipes/system/rvmrc.rb +15 -0
- data/lib/beet/scm.rb +36 -0
- data/lib/beet/scm/git.rb +15 -0
- data/lib/beet/scm/svn.rb +5 -0
- data/lib/beet/template_location_map.rb +15 -0
- data/test/executor_test.rb +24 -0
- data/test/file_system_test.rb +59 -0
- data/test/test_helper.rb +12 -0
- data/whtt-eric-beet.gemspec +120 -0
- metadata +203 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
module CommonHelpers
|
2
|
+
def in_tmp_folder(&block)
|
3
|
+
FileUtils.chdir(@tmp_root, &block)
|
4
|
+
end
|
5
|
+
|
6
|
+
def in_project_folder(&block)
|
7
|
+
project_folder = @active_project_folder || @tmp_root
|
8
|
+
FileUtils.chdir(project_folder, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def in_project_subfolder(folder, &block)
|
12
|
+
FileUtils.chdir(File.join(@active_project_folder, folder), &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def in_home_folder(&block)
|
16
|
+
FileUtils.chdir(@home_path, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def force_local_lib_override(project_name = @project_name)
|
20
|
+
rakefile = File.read(File.join(project_name, 'Rakefile'))
|
21
|
+
File.open(File.join(project_name, 'Rakefile'), "w+") do |f|
|
22
|
+
f << "$:.unshift('#{@lib_path}')\n"
|
23
|
+
f << rakefile
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup_active_project_folder project_name
|
28
|
+
@active_project_folder = File.join(@tmp_root, project_name)
|
29
|
+
@project_name = project_name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
World(CommonHelpers)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
gem 'cucumber'
|
2
|
+
require 'cucumber'
|
3
|
+
gem 'rspec'
|
4
|
+
require 'spec'
|
5
|
+
|
6
|
+
Before do
|
7
|
+
@tmp_root = File.dirname(__FILE__) + "/../../tmp"
|
8
|
+
@home_path = File.expand_path(File.join(@tmp_root, "home"))
|
9
|
+
FileUtils.rm_rf @tmp_root
|
10
|
+
FileUtils.mkdir_p @home_path
|
11
|
+
ENV['HOME'] = @home_path
|
12
|
+
end
|
13
|
+
|
14
|
+
After do
|
15
|
+
unless ENV['LEAVE_CUCUMBER_GENERATED_OUTPUT']
|
16
|
+
FileUtils.rm_rf @active_project_folder
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
gem "fakeweb"
|
21
|
+
require "fakeweb"
|
22
|
+
|
23
|
+
Before do
|
24
|
+
FakeWeb.allow_net_connect = false
|
25
|
+
end
|
data/lib/beet.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# TODO similarly, figure out how to require things as needed by the template
|
2
|
+
require 'beet/command_execution'
|
3
|
+
require 'beet/file_system'
|
4
|
+
require 'beet/interaction'
|
5
|
+
require 'beet/capistrano'
|
6
|
+
require 'beet/rails'
|
7
|
+
require 'beet/scm'
|
8
|
+
require 'beet/executor'
|
9
|
+
require 'beet/gem_location_map'
|
10
|
+
require 'beet/template_location_map'
|
11
|
+
|
12
|
+
# for camelize and others
|
13
|
+
require 'active_support/inflector'
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Beet
|
2
|
+
module CommandExecution
|
3
|
+
# Executes a command
|
4
|
+
#
|
5
|
+
# ==== Example
|
6
|
+
#
|
7
|
+
# inside('vendor') do
|
8
|
+
# run('ln -s ~/edge rails)
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
def run(command, log_action = true)
|
12
|
+
log 'executing', "#{command} from #{Dir.pwd}" if log_action
|
13
|
+
system(command)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Executes a command with sudo
|
17
|
+
#
|
18
|
+
# ==== Example
|
19
|
+
#
|
20
|
+
# inside('vendor') do
|
21
|
+
# sudo('mkdir /var/log/something')
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
def sudo(command, log_action = true)
|
25
|
+
command = "#{SUDO}#{command}"
|
26
|
+
run(command,log_action)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Executes a ruby script (taking into account WIN32 platform quirks)
|
30
|
+
def run_ruby_script(command, log_action = true)
|
31
|
+
ruby_command = RUBY_PLATFORM=~ /win32/ ? 'ruby ' : ''
|
32
|
+
rvm("#{ruby_command}#{command}", log_action)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Runs the supplied rake task
|
36
|
+
#
|
37
|
+
# ==== Example
|
38
|
+
#
|
39
|
+
# rake("db:migrate")
|
40
|
+
# rake("db:migrate", :env => "production")
|
41
|
+
# rake("gems:install", :sudo => true)
|
42
|
+
#
|
43
|
+
def rake(command, options = {})
|
44
|
+
log 'rake', command
|
45
|
+
env = options[:env] || 'development'
|
46
|
+
sudo = options[:sudo] ? 'sudo ' : ''
|
47
|
+
in_root { run("#{sudo}rake #{command} RAILS_ENV=#{env}", false) }
|
48
|
+
end
|
49
|
+
|
50
|
+
# Installs the gems using the specified ruby if rvmrc recipe is included
|
51
|
+
def rvm(command, log_action = true)
|
52
|
+
command = "rvm #{@ruby_version} exec #{command}" unless @ruby_version.nil?
|
53
|
+
run(command, log_action)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,236 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'beet/logger'
|
3
|
+
require 'yaml'
|
4
|
+
require 'find'
|
5
|
+
begin
|
6
|
+
require 'ruby-debug'
|
7
|
+
rescue LoadError
|
8
|
+
# not required to actually run beet
|
9
|
+
end
|
10
|
+
|
11
|
+
module Beet
|
12
|
+
class Executor
|
13
|
+
BEET_DATA_FILE = "~/.beet.yml"
|
14
|
+
include Beet::CommandExecution
|
15
|
+
include Beet::FileSystem
|
16
|
+
include Beet::Interaction
|
17
|
+
|
18
|
+
include Beet::Rails
|
19
|
+
include Beet::Capistrano
|
20
|
+
include Beet::SCM
|
21
|
+
|
22
|
+
attr_reader :root, :logger, :options, :template
|
23
|
+
attr_accessor :recipes, :project_name, :gems, :todo_items, :ruby_version
|
24
|
+
|
25
|
+
def initialize(project_name, options={}) # :nodoc:
|
26
|
+
@root = calculate_project_root(project_name)
|
27
|
+
@project_name = ((project_name == '.') ? File.basename(Dir.pwd) : project_name)
|
28
|
+
@logger = Beet::Logger.new
|
29
|
+
@gems = []
|
30
|
+
@template = options[:template]
|
31
|
+
@options = options
|
32
|
+
@todo_items = ''
|
33
|
+
@recipes = []
|
34
|
+
@project_type = (options[:project_type] && options[:project_type].to_sym) || :rails3
|
35
|
+
@generate = true unless options[:generate] == false
|
36
|
+
@display = options[:display]
|
37
|
+
extract_commands_from_options
|
38
|
+
end
|
39
|
+
|
40
|
+
def start
|
41
|
+
if options[:use]
|
42
|
+
puts "Loading saved configuration: #{@options[:use]}"
|
43
|
+
data = load_saved_recipe_file
|
44
|
+
if config = data[@options[:use]]
|
45
|
+
@gems.concat(config[:gems]) if config[:gems]
|
46
|
+
@template = config[:template] if config[:template]
|
47
|
+
@recipes.concat(config[:recipes]) if config[:recipes]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if @display && @template
|
52
|
+
puts open(TEMPLATE_LOCATIONS[@template]).read
|
53
|
+
else
|
54
|
+
if @generate
|
55
|
+
# TODO maybe let people specify path to rails 3 script rather than just assume its 'rails'
|
56
|
+
if @project_type == :rails3
|
57
|
+
puts "Generating rails 3 project #{project_name}..."
|
58
|
+
if @template
|
59
|
+
system("rails new #{project_name} -m #{TEMPLATE_LOCATIONS[@template]}")
|
60
|
+
else
|
61
|
+
system("rails new #{project_name}")
|
62
|
+
end
|
63
|
+
else
|
64
|
+
unless rails2_version = search_for_rails_2
|
65
|
+
puts "Please create a rails2 command which points to rails 2.x executable."
|
66
|
+
exit
|
67
|
+
else
|
68
|
+
puts "Generating rails project #{project_name}..."
|
69
|
+
if @template
|
70
|
+
system("rails _#{rails2_version}_ #{project_name} -m #{TEMPLATE_LOCATIONS[@template]}")
|
71
|
+
else
|
72
|
+
system("rails _#{rails2_version}_ #{project_name}")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
add_gems
|
79
|
+
|
80
|
+
print_todo
|
81
|
+
|
82
|
+
if options[:save]
|
83
|
+
save_run
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
run_recipes
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
def run_recipes
|
92
|
+
@recipes.each do |recipe|
|
93
|
+
begin
|
94
|
+
code = open(recipe).read
|
95
|
+
if @display
|
96
|
+
puts code
|
97
|
+
else
|
98
|
+
in_root { instance_eval(code)}
|
99
|
+
end
|
100
|
+
rescue LoadError, Errno::ENOENT => e
|
101
|
+
raise "The recipe [#{recipe}] could not be loaded. Error: #{e}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def log(*args)
|
107
|
+
logger.log(*args)
|
108
|
+
end
|
109
|
+
|
110
|
+
def todo(string=nil, &block)
|
111
|
+
self.todo_items << (string || block.call)
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def print_todo
|
117
|
+
unless todo_items.empty?
|
118
|
+
puts '#' * 30
|
119
|
+
puts "TODO Items:"
|
120
|
+
puts todo_items
|
121
|
+
puts '#' * 30
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def calculate_project_root(project_name)
|
126
|
+
# if the name looks like ~/projects/foobar then thats the root
|
127
|
+
if project_name.include?('/')
|
128
|
+
project_name
|
129
|
+
# if we're running inside the app, then current dir is it
|
130
|
+
elsif File.basename(Dir.pwd) == project_name
|
131
|
+
Dir.pwd
|
132
|
+
# assume the root is ./project_name
|
133
|
+
else
|
134
|
+
File.join(Dir.pwd, project_name)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def add_gems
|
139
|
+
if @gems
|
140
|
+
@gems.each do |gem_data|
|
141
|
+
duped_data = gem_data.clone # to avoid removing :name from @gems
|
142
|
+
name = duped_data.delete(:name)
|
143
|
+
gem(name, duped_data)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def extract_commands_from_options
|
149
|
+
if options[:gems]
|
150
|
+
options[:gems].split(/[\s,]+/).each do |gem|
|
151
|
+
if gem_info = gem_location(gem)
|
152
|
+
if gem_info.is_a?(Hash)
|
153
|
+
@gems << {:name => gem}.merge(gem_info)
|
154
|
+
else
|
155
|
+
@gems << {:name => gem, :source => gem_info}
|
156
|
+
end
|
157
|
+
else
|
158
|
+
@gems << {:name => gem}
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
if options[:recipes]
|
163
|
+
options[:recipes].split(/[\s,]+/).each do |recipe|
|
164
|
+
if file = recipe_location(recipe)
|
165
|
+
@recipes << file
|
166
|
+
else
|
167
|
+
puts "Can't find recipe #{recipe}"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def save_run
|
174
|
+
name = if options[:save] == true
|
175
|
+
ask("Enter a name for this configuration: ")
|
176
|
+
else
|
177
|
+
options[:save]
|
178
|
+
end
|
179
|
+
data = load_saved_recipe_file
|
180
|
+
data[name] = {:gems => @gems, :recipes => @recipes, :template => @template}
|
181
|
+
write_saved_recipe_file(data)
|
182
|
+
end
|
183
|
+
|
184
|
+
def beet_data_file
|
185
|
+
File.expand_path(BEET_DATA_FILE)
|
186
|
+
end
|
187
|
+
|
188
|
+
def load_saved_recipe_file
|
189
|
+
if File.exists?(beet_data_file)
|
190
|
+
::YAML.load_file(beet_data_file) || {} # if for some reason is nil, give back an empty hash
|
191
|
+
else
|
192
|
+
{}
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def write_saved_recipe_file(data)
|
197
|
+
File.open(beet_data_file, "wb") do |f|
|
198
|
+
f.write(YAML::dump(data))
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def gem_location(gem_name)
|
203
|
+
GEM_LOCATIONS[gem_name]
|
204
|
+
end
|
205
|
+
|
206
|
+
def recipe_location(recipe)
|
207
|
+
return recipe if File.exists?(recipe) or recipe.include?('http://')
|
208
|
+
locations = []
|
209
|
+
recipe_paths = []
|
210
|
+
locations << File.expand_path(ENV['BEET_RECIPES_DIR']) if ENV['BEET_RECIPES_DIR']
|
211
|
+
locations << File.expand_path(File.join(File.dirname(__FILE__), 'recipes'))
|
212
|
+
|
213
|
+
Find.find(locations * ", ") do |path|
|
214
|
+
recipe_paths << path if path.include?("#{recipe}.rb")
|
215
|
+
end
|
216
|
+
|
217
|
+
filename = if recipe_paths.length > 1
|
218
|
+
@project_type == :rails3 ?
|
219
|
+
recipe_paths.find {|path| path.include?("rails3")} :
|
220
|
+
recipe_paths.find {|path| path.include?("rails")}
|
221
|
+
else
|
222
|
+
recipe_paths.first
|
223
|
+
end
|
224
|
+
|
225
|
+
return filename
|
226
|
+
end
|
227
|
+
|
228
|
+
def search_for_rails_2
|
229
|
+
rails_versions = `gem list rails`.chomp
|
230
|
+
clean_versions = rails_versions.match /\((.*)\)/
|
231
|
+
numbered_versions = clean_versions[1].split(', ')
|
232
|
+
numbered_versions.find {|v| v.split('.').first.to_i == 2}
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
module Beet
|
3
|
+
module FileSystem
|
4
|
+
# Create a new file in the project folder. Specify the
|
5
|
+
# relative path from the project's root. Data is the return value of a block
|
6
|
+
# or a data string.
|
7
|
+
#
|
8
|
+
# ==== Examples
|
9
|
+
#
|
10
|
+
# file("lib/fun_party.rb") do
|
11
|
+
# hostname = ask("What is the virtual hostname I should use?")
|
12
|
+
# "vhost.name = #{hostname}"
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# file("config/apach.conf", "your apache config")
|
16
|
+
def file(filename, data = nil, log_action = true, &block)
|
17
|
+
log 'file', filename if log_action
|
18
|
+
dir, file = [File.dirname(filename), File.basename(filename)]
|
19
|
+
|
20
|
+
inside(dir) do
|
21
|
+
File.open(file, "w") do |f|
|
22
|
+
data = block.call if block_given?
|
23
|
+
f.write(remove_blank_start(data))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Create a new file in the lib/ directory. Code can be specified
|
29
|
+
# in a block or a data string can be given.
|
30
|
+
#
|
31
|
+
# ==== Examples
|
32
|
+
#
|
33
|
+
# lib("crypto.rb") do
|
34
|
+
# "crypted_special_value = '#{rand}--#{Time.now}--#{rand(1337)}--'"
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# lib("foreign.rb", "# Foreign code is fun")
|
38
|
+
#
|
39
|
+
def lib(filename, data = nil, &block)
|
40
|
+
log 'lib', filename
|
41
|
+
file("lib/#{filename}", data, false, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Create a new Rakefile with the provided code (either in a block or a string).
|
45
|
+
#
|
46
|
+
# ==== Examples
|
47
|
+
#
|
48
|
+
# rakefile("bootstrap.rake") do
|
49
|
+
# project = ask("What is the UNIX name of your project?")
|
50
|
+
#
|
51
|
+
# <<-TASK
|
52
|
+
# namespace :#{project} do
|
53
|
+
# task :bootstrap do
|
54
|
+
# puts "i like boots!"
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
# TASK
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# rakefile("seed.rake", "puts 'im plantin ur seedz'")
|
61
|
+
#
|
62
|
+
def rakefile(filename, data = nil, &block)
|
63
|
+
log 'rakefile', filename
|
64
|
+
file("lib/tasks/#{filename}", data, false, &block)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Do something in the root of the project or
|
68
|
+
# a provided subfolder; the full path is yielded to the block you provide.
|
69
|
+
# The path is set back to the previous path when the method exits.
|
70
|
+
def inside(dir = '', &block)
|
71
|
+
folder = File.join(root, dir)
|
72
|
+
FileUtils.mkdir_p(folder) unless File.exist?(folder)
|
73
|
+
FileUtils.cd(folder) { block.arity == 1 ? yield(folder) : yield }
|
74
|
+
end
|
75
|
+
|
76
|
+
def in_root
|
77
|
+
FileUtils.cd(root) { yield }
|
78
|
+
end
|
79
|
+
|
80
|
+
# Run a regular expression replacement on a file
|
81
|
+
#
|
82
|
+
# ==== Example
|
83
|
+
#
|
84
|
+
# gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1'
|
85
|
+
#
|
86
|
+
def gsub_file(path, regexp, *args, &block)
|
87
|
+
#path = destination_path(relative_destination)
|
88
|
+
content = File.read(path)
|
89
|
+
check_for = args.first || yield('')
|
90
|
+
regex = Regexp.new(regexp.source + Regexp.escape(check_for))
|
91
|
+
return if content =~ regex # if we can match the text and its leadin regex, don't add again
|
92
|
+
content = content.gsub(regexp, *args, &block)
|
93
|
+
File.open(path, 'wb') { |file| file.write(content) }
|
94
|
+
end
|
95
|
+
|
96
|
+
# Append text to a file
|
97
|
+
#
|
98
|
+
# ==== Example
|
99
|
+
#
|
100
|
+
# append_file 'config/environments/test.rb', 'config.gem "rspec"'
|
101
|
+
#
|
102
|
+
def append_file(relative_destination, data)
|
103
|
+
path = destination_path(relative_destination)
|
104
|
+
File.open(path, 'ab') { |file| file.write("\n#{data}") }
|
105
|
+
end
|
106
|
+
|
107
|
+
# Add text after matching line
|
108
|
+
#
|
109
|
+
# ==== Example
|
110
|
+
#
|
111
|
+
# add_after 'config/environment.rb', '# config.gem "aws-s3", :lib => "aws/s3"'
|
112
|
+
#
|
113
|
+
def add_after(filename, matching_text, data=nil, &block)
|
114
|
+
gsub_file filename, /(\s*#{Regexp.escape(matching_text)})/mi do |match|
|
115
|
+
"#{match}\n#{data || block.call}"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Add text after matching line, otherwise append to file wrapped in before/after text
|
120
|
+
#
|
121
|
+
# ==== Example
|
122
|
+
#
|
123
|
+
# add_after_or_append 'Gemfile', 'group :test', "gem 'rspec-rails'", "group :test do", "end"
|
124
|
+
#
|
125
|
+
def add_after_or_append(filename, matching_text, text_to_add, before_text, after_text)
|
126
|
+
content = File.read(filename)
|
127
|
+
if content.include?(matching_text)
|
128
|
+
add_after(filename, matching_text, text_to_add)
|
129
|
+
else
|
130
|
+
append_file(filename, [before_text, text_to_add, after_text].join("\n"))
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Add text before matching line
|
135
|
+
#
|
136
|
+
# ==== Example
|
137
|
+
#
|
138
|
+
# add_before 'config/environment.rb', '# config.gem "aws-s3", :lib => "aws/s3"'
|
139
|
+
#
|
140
|
+
def add_before(filename, matching_text, data=nil, &block)
|
141
|
+
gsub_file filename, /^(\s*#{Regexp.escape(matching_text)})/mi do |match|
|
142
|
+
"#{data || block.call}#{match}"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
protected
|
147
|
+
|
148
|
+
def destination_path(relative_destination)
|
149
|
+
File.join(root, relative_destination)
|
150
|
+
end
|
151
|
+
|
152
|
+
# it's common for multi-line strings to be coded in a way so that their first character is a newline
|
153
|
+
# like this
|
154
|
+
# string = %{
|
155
|
+
# foo
|
156
|
+
# }
|
157
|
+
# string => "\nfoo\n"
|
158
|
+
# This is bad when it needs to be #!/usr/bin/something so we remove that newline in a dumb but effective way for now
|
159
|
+
def remove_blank_start(string)
|
160
|
+
string.reverse.chomp.reverse
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|