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.
Files changed (72) hide show
  1. data/Gemfile +12 -0
  2. data/Gemfile.lock +25 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +13 -0
  5. data/Rakefile +59 -0
  6. data/TODO +25 -0
  7. data/VERSION +1 -0
  8. data/bin/beet +114 -0
  9. data/features/generating.feature +24 -0
  10. data/features/step_definitions/beet_steps.rb +7 -0
  11. data/features/step_definitions/common_steps.rb +172 -0
  12. data/features/support/common.rb +33 -0
  13. data/features/support/env.rb +25 -0
  14. data/lib/beet.rb +13 -0
  15. data/lib/beet/capistrano.rb +14 -0
  16. data/lib/beet/command_execution.rb +56 -0
  17. data/lib/beet/executor.rb +236 -0
  18. data/lib/beet/file_system.rb +163 -0
  19. data/lib/beet/files/swfupload/images/cancelbutton.gif +0 -0
  20. data/lib/beet/files/swfupload/images/header-bg.jpg +0 -0
  21. data/lib/beet/files/swfupload/images/logo.gif +0 -0
  22. data/lib/beet/files/swfupload/js/handlers.js +290 -0
  23. data/lib/beet/gem_location_map.rb +65 -0
  24. data/lib/beet/interaction.rb +47 -0
  25. data/lib/beet/logger.rb +44 -0
  26. data/lib/beet/rails.rb +175 -0
  27. data/lib/beet/recipes/passenger/vhost.rb +17 -0
  28. data/lib/beet/recipes/rack/middleware.rb +17 -0
  29. data/lib/beet/recipes/rails/auth/authlogic.rb +302 -0
  30. data/lib/beet/recipes/rails/auth/clearance.rb +22 -0
  31. data/lib/beet/recipes/rails/auth/devise.rb +22 -0
  32. data/lib/beet/recipes/rails/clean_files.rb +4 -0
  33. data/lib/beet/recipes/rails/cms/bcms_blog.rb +21 -0
  34. data/lib/beet/recipes/rails/cms/bcms_event.rb +24 -0
  35. data/lib/beet/recipes/rails/css/blueprint.rb +5 -0
  36. data/lib/beet/recipes/rails/css/compass.rb +35 -0
  37. data/lib/beet/recipes/rails/css/nifty_layout.rb +5 -0
  38. data/lib/beet/recipes/rails/css/reset.rb +10 -0
  39. data/lib/beet/recipes/rails/db/mongo.rb +57 -0
  40. data/lib/beet/recipes/rails/db/mysql.rb +47 -0
  41. data/lib/beet/recipes/rails/db/postgres.rb +52 -0
  42. data/lib/beet/recipes/rails/git.rb +23 -0
  43. data/lib/beet/recipes/rails/jquery.rb +11 -0
  44. data/lib/beet/recipes/rails/swfupload.rb +305 -0
  45. data/lib/beet/recipes/rails/testing/rspec.rb +3 -0
  46. data/lib/beet/recipes/rails/testing/shoulda.rb +1 -0
  47. data/lib/beet/recipes/rails3/admin_interface/active_scaffold.rb +10 -0
  48. data/lib/beet/recipes/rails3/admin_interface/rails_admin.rb +9 -0
  49. data/lib/beet/recipes/rails3/auth/devise.rb +17 -0
  50. data/lib/beet/recipes/rails3/clean_files.rb +3 -0
  51. data/lib/beet/recipes/rails3/css/boilerplate.rb +41 -0
  52. data/lib/beet/recipes/rails3/css/reset.rb +10 -0
  53. data/lib/beet/recipes/rails3/css/sass.rb +3 -0
  54. data/lib/beet/recipes/rails3/db/mysql.rb +35 -0
  55. data/lib/beet/recipes/rails3/file_uploads/paperclip.rb +29 -0
  56. data/lib/beet/recipes/rails3/git.rb +16 -0
  57. data/lib/beet/recipes/rails3/jammit.rb +26 -0
  58. data/lib/beet/recipes/rails3/js/jquery.rb +12 -0
  59. data/lib/beet/recipes/rails3/markup/haml.rb +3 -0
  60. data/lib/beet/recipes/rails3/testing/cucumber.rb +19 -0
  61. data/lib/beet/recipes/rails3/testing/rspec.rb +40 -0
  62. data/lib/beet/recipes/standalone/hades.rb +61 -0
  63. data/lib/beet/recipes/system/rvmrc.rb +15 -0
  64. data/lib/beet/scm.rb +36 -0
  65. data/lib/beet/scm/git.rb +15 -0
  66. data/lib/beet/scm/svn.rb +5 -0
  67. data/lib/beet/template_location_map.rb +15 -0
  68. data/test/executor_test.rb +24 -0
  69. data/test/file_system_test.rb +59 -0
  70. data/test/test_helper.rb +12 -0
  71. data/whtt-eric-beet.gemspec +120 -0
  72. 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
@@ -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,14 @@
1
+ module Beet
2
+ module Capistrano
3
+ # Just run the capify command in root
4
+ #
5
+ # ==== Example
6
+ #
7
+ # capify!
8
+ #
9
+ def capify!
10
+ log 'capifying'
11
+ in_root { run('capify .', false) }
12
+ end
13
+ end
14
+ end
@@ -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