bueller 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/ChangeLog.markdown +141 -0
  2. data/LICENSE +20 -0
  3. data/README.markdown +182 -0
  4. data/bin/bueller +5 -0
  5. data/lib/bueller/commands/build_gem.rb +50 -0
  6. data/lib/bueller/commands/git_tag_release.rb +63 -0
  7. data/lib/bueller/commands/install_gem.rb +36 -0
  8. data/lib/bueller/commands/release_to_github.rb +41 -0
  9. data/lib/bueller/commands/release_to_rubygems.rb +26 -0
  10. data/lib/bueller/commands/version/base.rb +36 -0
  11. data/lib/bueller/commands/version/bump_major.rb +11 -0
  12. data/lib/bueller/commands/version/bump_minor.rb +12 -0
  13. data/lib/bueller/commands/version/bump_patch.rb +14 -0
  14. data/lib/bueller/commands/version/write.rb +21 -0
  15. data/lib/bueller/commands/write_gemspec.rb +29 -0
  16. data/lib/bueller/commands.rb +18 -0
  17. data/lib/bueller/errors.rb +8 -0
  18. data/lib/bueller/gemspec_helper.rb +83 -0
  19. data/lib/bueller/generator/application.rb +51 -0
  20. data/lib/bueller/generator/bacon_mixin.rb +43 -0
  21. data/lib/bueller/generator/github_mixin.rb +29 -0
  22. data/lib/bueller/generator/micronaut_mixin.rb +41 -0
  23. data/lib/bueller/generator/minitest_mixin.rb +42 -0
  24. data/lib/bueller/generator/options.rb +154 -0
  25. data/lib/bueller/generator/rdoc_mixin.rb +9 -0
  26. data/lib/bueller/generator/riot_mixin.rb +42 -0
  27. data/lib/bueller/generator/rspec_mixin.rb +50 -0
  28. data/lib/bueller/generator/shindo_mixin.rb +44 -0
  29. data/lib/bueller/generator/shoulda_mixin.rb +42 -0
  30. data/lib/bueller/generator/testspec_mixin.rb +42 -0
  31. data/lib/bueller/generator/testunit_mixin.rb +39 -0
  32. data/lib/bueller/generator/yard_mixin.rb +14 -0
  33. data/lib/bueller/generator.rb +291 -0
  34. data/lib/bueller/rubyforge_tasks.rb +88 -0
  35. data/lib/bueller/tasks.rb +133 -0
  36. data/lib/bueller/templates/.document +11 -0
  37. data/lib/bueller/templates/.gitignore +40 -0
  38. data/lib/bueller/templates/Gemfile +1 -0
  39. data/lib/bueller/templates/LICENSE +20 -0
  40. data/lib/bueller/templates/README.rdoc +17 -0
  41. data/lib/bueller/templates/Rakefile +20 -0
  42. data/lib/bueller/templates/bacon/flunking.rb +7 -0
  43. data/lib/bueller/templates/bacon/helper.rb +8 -0
  44. data/lib/bueller/templates/bueller_tasks.erb +10 -0
  45. data/lib/bueller/templates/features/default.feature +9 -0
  46. data/lib/bueller/templates/features/support/env.rb +16 -0
  47. data/lib/bueller/templates/gemspec +27 -0
  48. data/lib/bueller/templates/micronaut/flunking.rb +7 -0
  49. data/lib/bueller/templates/micronaut/helper.rb +17 -0
  50. data/lib/bueller/templates/minitest/flunking.rb +7 -0
  51. data/lib/bueller/templates/minitest/helper.rb +11 -0
  52. data/lib/bueller/templates/other_tasks.erb +84 -0
  53. data/lib/bueller/templates/riot/flunking.rb +11 -0
  54. data/lib/bueller/templates/riot/helper.rb +3 -0
  55. data/lib/bueller/templates/rspec/.rspec +1 -0
  56. data/lib/bueller/templates/rspec/flunking.rb +7 -0
  57. data/lib/bueller/templates/rspec/helper.rb +19 -0
  58. data/lib/bueller/templates/shindo/flunking.rb +8 -0
  59. data/lib/bueller/templates/shindo/helper.rb +5 -0
  60. data/lib/bueller/templates/shoulda/flunking.rb +7 -0
  61. data/lib/bueller/templates/shoulda/helper.rb +10 -0
  62. data/lib/bueller/templates/testspec/flunking.rb +7 -0
  63. data/lib/bueller/templates/testspec/helper.rb +7 -0
  64. data/lib/bueller/templates/testunit/flunking.rb +7 -0
  65. data/lib/bueller/templates/testunit/helper.rb +9 -0
  66. data/lib/bueller/version_helper.rb +59 -0
  67. data/lib/bueller.rb +139 -0
  68. data/spec/bueller/commands/build_gem_spec.rb +38 -0
  69. data/spec/bueller/commands/git_tag_release_spec.rb +79 -0
  70. data/spec/bueller/commands/install_gem_spec.rb +11 -0
  71. data/spec/bueller/commands/release_to_github_spec.rb +54 -0
  72. data/spec/bueller/commands/release_to_rubygems_spec.rb +15 -0
  73. data/spec/bueller/commands/version/bump_major_spec.rb +12 -0
  74. data/spec/bueller/commands/version/bump_minor_spec.rb +12 -0
  75. data/spec/bueller/commands/version/bump_patch_spec.rb +12 -0
  76. data/spec/bueller/commands/write_gemspec_spec.rb +32 -0
  77. data/spec/bueller/gemspec_helper_spec.rb +55 -0
  78. data/spec/bueller/generator/application_spec.rb +67 -0
  79. data/spec/bueller/generator/options_spec.rb +206 -0
  80. data/spec/bueller/generator_mixins_spec.rb +23 -0
  81. data/spec/bueller/generator_spec.rb +274 -0
  82. data/spec/bueller/tasks_spec.rb +29 -0
  83. data/spec/bueller/version_helper_spec.rb +57 -0
  84. data/spec/bueller_spec.rb +94 -0
  85. data/spec/fixtures/bar/bar.gemspec +41 -0
  86. data/spec/fixtures/bar/bin/foo_the_ultimate_bin +1 -0
  87. data/spec/fixtures/bar/hey_include_me_in_gemspec +0 -0
  88. data/spec/fixtures/bar/lib/foo_the_ultimate_lib.rb +1 -0
  89. data/spec/fixtures/existing-project/LICENSE +20 -0
  90. data/spec/fixtures/existing-project/README.rdoc +7 -0
  91. data/spec/fixtures/existing-project/Rakefile +69 -0
  92. data/spec/fixtures/existing-project/existing-project.gemspec +20 -0
  93. data/spec/fixtures/existing-project/lib/existing_project_with_version.rb +0 -0
  94. data/spec/fixtures/existing-project/test/existing_project_with_version_test.rb +7 -0
  95. data/spec/fixtures/existing-project/test/test_helper.rb +10 -0
  96. data/spec/fixtures/existing-project-with-version-constant/LICENSE +20 -0
  97. data/spec/fixtures/existing-project-with-version-constant/README.rdoc +7 -0
  98. data/spec/fixtures/existing-project-with-version-constant/Rakefile +69 -0
  99. data/spec/fixtures/existing-project-with-version-constant/existing-project-with-version.gemspec +19 -0
  100. data/spec/fixtures/existing-project-with-version-constant/lib/existing_project_with_version.rb +0 -0
  101. data/spec/fixtures/existing-project-with-version-constant/test/existing_project_with_version_test.rb +7 -0
  102. data/spec/fixtures/existing-project-with-version-constant/test/test_helper.rb +10 -0
  103. data/spec/spec_helper.rb +11 -0
  104. data/spec/support/application.rb +28 -0
  105. data/spec/support/file_system.rb +24 -0
  106. data/spec/support/gemspec.rb +28 -0
  107. data/spec/support/git.rb +19 -0
  108. data/spec/support/have_version.rb +18 -0
  109. metadata +381 -0
@@ -0,0 +1,42 @@
1
+ class Bueller
2
+ class Generator
3
+ module TestspecMixin
4
+ def self.extended(generator)
5
+ generator.development_dependencies << 'test-spec'
6
+ end
7
+
8
+ def default_task
9
+ 'test'
10
+ end
11
+
12
+ def feature_support_require
13
+ 'test/unit/assertions'
14
+ end
15
+
16
+ def feature_support_extend
17
+ 'Test::Unit::Assertions'
18
+ end
19
+
20
+ def test_dir
21
+ 'test'
22
+ end
23
+
24
+ def test_task
25
+ 'test'
26
+ end
27
+
28
+ def test_pattern
29
+ 'test/**/*_test.rb'
30
+ end
31
+
32
+ def test_filename
33
+ "#{require_name}_test.rb"
34
+ end
35
+
36
+ def test_helper_filename
37
+ "test_helper.rb"
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,39 @@
1
+ class Bueller
2
+ class Generator
3
+ module TestunitMixin
4
+
5
+ def default_task
6
+ 'test'
7
+ end
8
+
9
+ def feature_support_require
10
+ 'test/unit/assertions'
11
+ end
12
+
13
+ def feature_support_extend
14
+ 'Test::Unit::Assertions'
15
+ end
16
+
17
+ def test_dir
18
+ 'test'
19
+ end
20
+
21
+ def test_task
22
+ 'test'
23
+ end
24
+
25
+ def test_pattern
26
+ 'test/**/test_*.rb'
27
+ end
28
+
29
+ def test_filename
30
+ "test_#{require_name}.rb"
31
+ end
32
+
33
+ def test_helper_filename
34
+ "helper.rb"
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,14 @@
1
+ class Bueller
2
+ class Generator
3
+ module YardMixin
4
+ def self.extended(generator)
5
+ generator.development_dependencies << 'yard'
6
+ end
7
+
8
+ def doc_task
9
+ 'yardoc'
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,291 @@
1
+ require 'git'
2
+ require 'erb'
3
+
4
+ require 'net/http'
5
+ require 'uri'
6
+
7
+ require 'fileutils'
8
+
9
+ class Bueller
10
+ class NoGitUserName < StandardError
11
+ end
12
+ class NoGitUserEmail < StandardError
13
+ end
14
+ class FileInTheWay < StandardError
15
+ end
16
+ class NoGitHubRepoNameGiven < StandardError
17
+ end
18
+ class NoGitHubUser < StandardError
19
+ end
20
+ class NoGitHubToken < StandardError
21
+ end
22
+ class GitInitFailed < StandardError
23
+ end
24
+
25
+ # Generator for creating a bueller-enabled project
26
+ class Generator
27
+ require 'bueller/generator/options'
28
+ require 'bueller/generator/application'
29
+
30
+ require 'bueller/generator/github_mixin'
31
+
32
+ require 'bueller/generator/bacon_mixin'
33
+ require 'bueller/generator/micronaut_mixin'
34
+ require 'bueller/generator/minitest_mixin'
35
+ require 'bueller/generator/rspec_mixin'
36
+ require 'bueller/generator/shoulda_mixin'
37
+ require 'bueller/generator/testspec_mixin'
38
+ require 'bueller/generator/testunit_mixin'
39
+ require 'bueller/generator/riot_mixin'
40
+ require 'bueller/generator/shindo_mixin'
41
+
42
+ require 'bueller/generator/rdoc_mixin'
43
+ require 'bueller/generator/yard_mixin'
44
+
45
+ attr_accessor :target_dir, :user_name, :user_email, :summary, :homepage,
46
+ :description, :project_name, :github_username, :github_token,
47
+ :repo, :create_remote_repo,
48
+ :testing_framework, :documentation_framework,
49
+ :use_cucumber, :setup_gemcutter,
50
+ :setup_rubyforge, :use_reek, :use_roodi,
51
+ :development_dependencies,
52
+ :options,
53
+ :git_remote
54
+
55
+ alias :create_remote_repo? :create_remote_repo
56
+ alias :use_cucumber? :use_cucumber
57
+ alias :setup_rubyforge? :setup_rubyforge
58
+ alias :use_reek? :use_reek
59
+ alias :use_roodi? :use_roodi
60
+
61
+ def self.run(options = {})
62
+ generator = self.new(options)
63
+ generator.run
64
+ end
65
+
66
+ def initialize(options = {})
67
+ self.options = options
68
+
69
+ self.project_name = options[:project_name]
70
+ if self.project_name.nil? || self.project_name.squeeze.strip == ""
71
+ raise NoGitHubRepoNameGiven
72
+ end
73
+
74
+ self.development_dependencies = []
75
+ self.testing_framework = options[:testing_framework]
76
+ self.documentation_framework = options[:documentation_framework]
77
+ begin
78
+ generator_mixin_name = "#{testing_framework.to_s.capitalize}Mixin"
79
+ generator_mixin = self.class.const_get(generator_mixin_name)
80
+ extend generator_mixin
81
+ rescue NameError => e
82
+ raise ArgumentError, "Unsupported testing framework (#{testing_framework})"
83
+ end
84
+
85
+ begin
86
+ generator_mixin_name = "#{self.documentation_framework.to_s.capitalize}Mixin"
87
+ generator_mixin = self.class.const_get(generator_mixin_name)
88
+ extend generator_mixin
89
+ rescue NameError => e
90
+ raise ArgumentError, "Unsupported documentation framework (#{documentation_framework})"
91
+ end
92
+
93
+ self.target_dir = options[:directory] || self.project_name
94
+
95
+ self.summary = options[:summary] || 'TODO: one-line summary of your gem'
96
+ self.description = options[:description] || 'TODO: detailed description of your gem'
97
+ self.use_cucumber = options[:use_cucumber]
98
+ self.use_reek = options[:use_reek]
99
+ self.use_roodi = options[:use_roodi]
100
+ self.setup_gemcutter = options[:gemcutter]
101
+ self.setup_rubyforge = options[:rubyforge]
102
+
103
+ development_dependencies << 'cucumber' if use_cucumber?
104
+
105
+ development_dependencies << 'bundler'
106
+ development_dependencies << 'bueller'
107
+ development_dependencies << 'rake'
108
+ development_dependencies << 'rcov'
109
+
110
+ development_dependencies << 'reek' if use_reek?
111
+ development_dependencies << 'roodi' if use_roodi?
112
+
113
+ self.user_name = options[:user_name]
114
+ self.user_email = options[:user_email]
115
+ self.homepage = options[:homepage]
116
+
117
+ self.git_remote = options[:git_remote]
118
+
119
+ raise NoGitUserName unless self.user_name
120
+ raise NoGitUserEmail unless self.user_email
121
+
122
+ extend GithubMixin
123
+ end
124
+
125
+ def run
126
+ create_files
127
+ create_version_control
128
+ $stdout.puts "Bueller has prepared your gem in #{target_dir}"
129
+ if create_remote_repo?
130
+ create_and_push_repo
131
+ $stdout.puts "Bueller has pushed your repo to #{homepage}"
132
+ end
133
+ end
134
+
135
+ def constant_name
136
+ self.project_name.split(/[-_]/).collect{|each| each.capitalize }.join
137
+ end
138
+
139
+ def lib_filename
140
+ "#{project_name}.rb"
141
+ end
142
+
143
+ def require_name
144
+ self.project_name
145
+ end
146
+
147
+ def file_name_prefix
148
+ self.project_name.gsub('-', '_')
149
+ end
150
+
151
+ def lib_dir
152
+ 'lib'
153
+ end
154
+
155
+ def feature_filename
156
+ "#{project_name}.feature"
157
+ end
158
+
159
+ def steps_filename
160
+ "#{project_name}_steps.rb"
161
+ end
162
+
163
+ def features_dir
164
+ 'features'
165
+ end
166
+
167
+ def features_support_dir
168
+ File.join(features_dir, 'support')
169
+ end
170
+
171
+ def features_steps_dir
172
+ File.join(features_dir, 'step_definitions')
173
+ end
174
+
175
+ private
176
+
177
+ def create_files
178
+ unless File.exists?(target_dir) || File.directory?(target_dir)
179
+ FileUtils.mkdir target_dir
180
+ else
181
+ raise FileInTheWay, "The directory #{target_dir} already exists, aborting. Maybe move it out of the way before continuing?"
182
+ end
183
+
184
+
185
+ output_template_in_target '.gitignore'
186
+ output_template_in_target 'Rakefile'
187
+ output_template_in_target 'Gemfile'
188
+ output_template_in_target 'LICENSE'
189
+ output_template_in_target 'README.rdoc'
190
+ output_template_in_target '.document'
191
+ output_template_in_target 'gemspec', "#{project_name}.gemspec"
192
+
193
+ mkdir_in_target lib_dir
194
+ File.open File.join(target_dir, lib_dir, lib_filename), 'w' do |f|
195
+ f.puts "module #{constant_name}\n\nend"
196
+ end
197
+
198
+ mkdir_in_target test_dir
199
+ output_template_in_target File.join(testing_framework.to_s, 'helper.rb'),
200
+ File.join(test_dir, test_helper_filename)
201
+ output_template_in_target File.join(testing_framework.to_s, 'flunking.rb'),
202
+ File.join(test_dir, test_filename)
203
+
204
+ if use_cucumber?
205
+ mkdir_in_target features_dir
206
+ output_template_in_target File.join(%w(features default.feature)), File.join('features', feature_filename)
207
+
208
+ mkdir_in_target features_support_dir
209
+ output_template_in_target File.join(features_support_dir, 'env.rb')
210
+
211
+ mkdir_in_target features_steps_dir
212
+ touch_in_target File.join(features_steps_dir, steps_filename)
213
+ end
214
+ end
215
+
216
+ def render_template(source)
217
+ template_contents = File.read(File.join(template_dir, source))
218
+ template = ERB.new(template_contents, nil, '<>')
219
+
220
+ # squish extraneous whitespace from some of the conditionals
221
+ template.result(binding).gsub(/\n\n\n+/, "\n\n")
222
+ end
223
+
224
+ def output_template_in_target(source, destination = source)
225
+ final_destination = File.join(target_dir, destination)
226
+ template_result = render_template(source)
227
+
228
+ File.open(final_destination, 'w') {|file| file.write(template_result)}
229
+
230
+ $stdout.puts "\tcreate\t#{destination}"
231
+ end
232
+
233
+ def template_dir
234
+ File.join(File.dirname(__FILE__), 'templates')
235
+ end
236
+
237
+ def mkdir_in_target(directory)
238
+ final_destination = File.join(target_dir, directory)
239
+
240
+ FileUtils.mkdir final_destination
241
+
242
+ $stdout.puts "\tcreate\t#{directory}"
243
+ end
244
+
245
+ def touch_in_target(destination)
246
+ final_destination = File.join(target_dir, destination)
247
+ FileUtils.touch final_destination
248
+ $stdout.puts "\tcreate\t#{destination}"
249
+ end
250
+
251
+ def create_version_control
252
+ Dir.chdir(target_dir) do
253
+ begin
254
+ @repo = Git.init()
255
+ rescue Git::GitExecuteError => e
256
+ raise GitInitFailed, "Encountered an error during gitification. Maybe the repo already exists, or has already been pushed to?"
257
+ end
258
+
259
+ begin
260
+ @repo.add('.')
261
+ rescue Git::GitExecuteError => e
262
+ #raise GitAddFailed, "There was some problem adding this directory to the git changeset"
263
+ raise
264
+ end
265
+
266
+ begin
267
+ @repo.commit "Initial commit to #{project_name}."
268
+ rescue Git::GitExecuteError => e
269
+ raise
270
+ end
271
+
272
+ begin
273
+ @repo.add_remote('origin', git_remote)
274
+ rescue Git::GitExecuteError => e
275
+ puts "Encountered an error while adding origin remote. Maybe you have some weird settings in ~/.gitconfig?"
276
+ raise
277
+ end
278
+ end
279
+ end
280
+
281
+ def create_and_push_repo
282
+ Net::HTTP.post_form URI.parse('http://github.com/api/v2/yaml/repos/create'),
283
+ 'login' => github_username,
284
+ 'token' => github_token,
285
+ 'description' => summary,
286
+ 'name' => project_name
287
+ # TODO do a HEAD request to see when it's ready?
288
+ @repo.push('origin')
289
+ end
290
+ end
291
+ end
@@ -0,0 +1,88 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+
4
+ class Bueller
5
+ # (Mostly deprecated) Rake tasks for putting a Bueller gem on Rubyforge.
6
+ #
7
+ # Bueller::Tasks.new needs to be used before this.
8
+ #
9
+ # Basic usage:
10
+ #
11
+ # Bueller::RubyforgeTasks.new
12
+ #
13
+ # There are a few options you can tweak:
14
+ #
15
+ # * project: the rubyforge project to operate on. This defaults to whatever you specified in your gemspec. Defaults to your gem name.
16
+ # * remote_doc_path: the place to upload docs to on Rubyforge under /var/www/gforge-projects/#{project}/
17
+ #
18
+ # See also http://wiki.github.com/technicalpickles/bueller/rubyforge
19
+ class RubyforgeTasks < ::Rake::TaskLib
20
+ # The RubyForge project to interact with. Defaults to whatever is in your bueller gemspec.
21
+ attr_accessor :project
22
+ # The path to upload docs to. It is relative to /var/www/gforge-projects/#{project}/, and defaults to your gemspec's name
23
+ attr_accessor :remote_doc_path
24
+ # Task to be used for generating documentation, before they are uploaded. Defaults to rdoc.
25
+ attr_accessor :doc_task
26
+
27
+ attr_accessor :bueller
28
+
29
+ def initialize
30
+ yield self if block_given?
31
+
32
+ define
33
+ end
34
+
35
+ def bueller
36
+ @bueller ||= Rake.application.bueller
37
+ end
38
+
39
+ def remote_doc_path
40
+ @remote_doc_path ||= bueller.gemspec.name
41
+ end
42
+
43
+ def project
44
+ @project ||= bueller.gemspec.rubyforge_project
45
+ end
46
+
47
+ def define
48
+ namespace :rubyforge do
49
+ namespace :release do
50
+ desc "Pretend to release the current gem version to RubyForge, but actually release to Gemcutter."
51
+ task :gem => 'gemcutter:release'
52
+
53
+ if publish_documentation?
54
+ desc "Publish docs to RubyForge."
55
+ task :docs => doc_task do
56
+ config = YAML.load(
57
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
58
+ )
59
+
60
+ host = "#{config['username']}@rubyforge.org"
61
+ remote_dir = "/var/www/gforge-projects/#{project}/#{remote_doc_path}"
62
+
63
+ local_dir = case self.doc_task.to_sym
64
+ when :rdoc then 'rdoc'
65
+ when :yardoc then 'doc'
66
+ else
67
+ raise "Unsure what to run to generate documentation. Please set doc_task and re-run."
68
+ end
69
+
70
+ sh %{rsync --archive --verbose --delete #{local_dir}/ #{host}:#{remote_dir}}
71
+ end
72
+ end
73
+ end
74
+
75
+ if publish_documentation?
76
+ desc "Release RDoc documentation to RubyForge"
77
+ task :release => "rubyforge:release:docs"
78
+ end
79
+ end
80
+
81
+ task :release => 'rubyforge:release'
82
+ end
83
+
84
+ def publish_documentation?
85
+ ! (doc_task == false || doc_task == :none)
86
+ end
87
+ end
88
+ end