jeweler 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/ChangeLog.markdown +64 -0
  2. data/LICENSE +20 -0
  3. data/README.markdown +164 -0
  4. data/Rakefile +89 -0
  5. data/TODO +11 -0
  6. data/VERSION.yml +4 -0
  7. data/bin/jeweler +8 -0
  8. data/lib/jeweler.rb +154 -0
  9. data/lib/jeweler/commands.rb +12 -0
  10. data/lib/jeweler/commands/build_gem.rb +31 -0
  11. data/lib/jeweler/commands/install_gem.rb +26 -0
  12. data/lib/jeweler/commands/release.rb +59 -0
  13. data/lib/jeweler/commands/release_to_rubyforge.rb +51 -0
  14. data/lib/jeweler/commands/setup_rubyforge.rb +38 -0
  15. data/lib/jeweler/commands/validate_gemspec.rb +30 -0
  16. data/lib/jeweler/commands/version/base.rb +41 -0
  17. data/lib/jeweler/commands/version/bump_major.rb +13 -0
  18. data/lib/jeweler/commands/version/bump_minor.rb +12 -0
  19. data/lib/jeweler/commands/version/bump_patch.rb +14 -0
  20. data/lib/jeweler/commands/version/write.rb +12 -0
  21. data/lib/jeweler/commands/write_gemspec.rb +39 -0
  22. data/lib/jeweler/errors.rb +20 -0
  23. data/lib/jeweler/gemspec_helper.rb +51 -0
  24. data/lib/jeweler/generator.rb +347 -0
  25. data/lib/jeweler/generator/application.rb +45 -0
  26. data/lib/jeweler/generator/options.rb +68 -0
  27. data/lib/jeweler/tasks.rb +119 -0
  28. data/lib/jeweler/templates/.document +5 -0
  29. data/lib/jeweler/templates/.gitignore +5 -0
  30. data/lib/jeweler/templates/LICENSE +20 -0
  31. data/lib/jeweler/templates/README.rdoc +7 -0
  32. data/lib/jeweler/templates/Rakefile +125 -0
  33. data/lib/jeweler/templates/bacon/flunking.rb +7 -0
  34. data/lib/jeweler/templates/bacon/helper.rb +8 -0
  35. data/lib/jeweler/templates/features/default.feature +9 -0
  36. data/lib/jeweler/templates/features/support/env.rb +11 -0
  37. data/lib/jeweler/templates/micronaut/flunking.rb +7 -0
  38. data/lib/jeweler/templates/micronaut/helper.rb +17 -0
  39. data/lib/jeweler/templates/minitest/flunking.rb +7 -0
  40. data/lib/jeweler/templates/minitest/helper.rb +11 -0
  41. data/lib/jeweler/templates/rspec/flunking.rb +7 -0
  42. data/lib/jeweler/templates/rspec/helper.rb +9 -0
  43. data/lib/jeweler/templates/shoulda/flunking.rb +7 -0
  44. data/lib/jeweler/templates/shoulda/helper.rb +10 -0
  45. data/lib/jeweler/templates/testunit/flunking.rb +7 -0
  46. data/lib/jeweler/templates/testunit/helper.rb +9 -0
  47. data/lib/jeweler/version_helper.rb +83 -0
  48. data/test/fixtures/bar/VERSION.yml +4 -0
  49. data/test/fixtures/existing-project-with-version/LICENSE +20 -0
  50. data/test/fixtures/existing-project-with-version/README.rdoc +7 -0
  51. data/test/fixtures/existing-project-with-version/Rakefile +82 -0
  52. data/test/fixtures/existing-project-with-version/VERSION.yml +4 -0
  53. data/test/fixtures/existing-project-with-version/existing-project-with-version.gemspec +29 -0
  54. data/test/fixtures/existing-project-with-version/lib/existing_project_with_version.rb +0 -0
  55. data/test/fixtures/existing-project-with-version/test/existing_project_with_version_test.rb +7 -0
  56. data/test/fixtures/existing-project-with-version/test/test_helper.rb +10 -0
  57. data/test/geminstaller.yml +12 -0
  58. data/test/generators/initialization_test.rb +146 -0
  59. data/test/jeweler/commands/test_build_gem.rb +72 -0
  60. data/test/jeweler/commands/test_install_gem.rb +21 -0
  61. data/test/jeweler/commands/test_release.rb +180 -0
  62. data/test/jeweler/commands/test_release_to_rubyforge.rb +157 -0
  63. data/test/jeweler/commands/test_setup_rubyforge.rb +88 -0
  64. data/test/jeweler/commands/test_validate_gemspec.rb +27 -0
  65. data/test/jeweler/commands/test_write_gemspec.rb +92 -0
  66. data/test/jeweler/commands/version/test_base.rb +32 -0
  67. data/test/jeweler/commands/version/test_bump_major.rb +22 -0
  68. data/test/jeweler/commands/version/test_bump_minor.rb +19 -0
  69. data/test/jeweler/commands/version/test_bump_patch.rb +20 -0
  70. data/test/jeweler/commands/version/test_write.rb +23 -0
  71. data/test/shoulda_macros/jeweler_macros.rb +35 -0
  72. data/test/test_application.rb +113 -0
  73. data/test/test_gemspec_helper.rb +36 -0
  74. data/test/test_generator.rb +183 -0
  75. data/test/test_helper.rb +118 -0
  76. data/test/test_jeweler.rb +177 -0
  77. data/test/test_options.rb +96 -0
  78. data/test/test_tasks.rb +41 -0
  79. data/test/test_version_helper.rb +115 -0
  80. data/test/version_tmp/VERSION.yml +4 -0
  81. metadata +171 -0
@@ -0,0 +1,347 @@
1
+ require 'git'
2
+ require 'erb'
3
+
4
+ require 'net/http'
5
+ require 'uri'
6
+
7
+ class Jeweler
8
+ class NoGitUserName < StandardError
9
+ end
10
+ class NoGitUserEmail < StandardError
11
+ end
12
+ class FileInTheWay < StandardError
13
+ end
14
+ class NoGitHubRepoNameGiven < StandardError
15
+ end
16
+ class NoGitHubUser < StandardError
17
+ end
18
+ class NoGitHubToken < StandardError
19
+ end
20
+ class GitInitFailed < StandardError
21
+ end
22
+
23
+ class Generator
24
+ attr_accessor :target_dir, :user_name, :user_email, :summary, :testing_framework,
25
+ :github_repo_name, :github_username, :github_token,
26
+ :repo, :should_create_repo, :should_use_cucumber, :should_setup_rubyforge
27
+
28
+ SUPPORTED_TESTING_FRAMEWORKS = [:shoulda, :testunit, :bacon, :rspec, :micronaut, :minitest]
29
+
30
+ def initialize(github_repo_name, options = {})
31
+ if github_repo_name.nil? || github_repo_name.squeeze.strip == ""
32
+ raise NoGitHubRepoNameGiven
33
+ end
34
+
35
+ self.github_repo_name = github_repo_name
36
+
37
+ self.testing_framework = (options[:testing_framework] || :shoulda).to_sym
38
+ unless SUPPORTED_TESTING_FRAMEWORKS.include? self.testing_framework
39
+ raise ArgumentError, "Unsupported testing framework (#{testing_framework})"
40
+ end
41
+
42
+ self.target_dir = options[:directory] || self.github_repo_name
43
+
44
+ self.should_create_repo = options[:create_repo]
45
+ self.summary = options[:summary] || 'TODO'
46
+ self.should_use_cucumber= options[:use_cucumber]
47
+ self.should_setup_rubyforge = options[:rubyforge]
48
+
49
+ use_user_git_config
50
+
51
+ end
52
+
53
+ def run
54
+ create_files
55
+ gitify
56
+ $stdout.puts "Jeweler has prepared your gem in #{github_repo_name}"
57
+ if should_create_repo
58
+ create_and_push_repo
59
+ $stdout.puts "Jeweler has pushed your repo to #{github_url}"
60
+ enable_gem_for_repo
61
+ $stdout.puts "Jeweler has enabled gem building for your repo"
62
+ end
63
+ end
64
+
65
+ # Directory where 'tests' live
66
+ def test_dir
67
+ test_or_spec
68
+ end
69
+
70
+ # Default rake task to use
71
+ def default_task
72
+ case testing_framework.to_sym
73
+ when :shoulda, :testunit, :minitest
74
+ 'test'
75
+ when :bacon, :rspec
76
+ 'spec'
77
+ when :micronaut
78
+ 'examples'
79
+ else
80
+ raise ArgumentError, "Don't know default task for #{testing_framework}"
81
+ end
82
+ end
83
+
84
+ def feature_support_require
85
+ case testing_framework.to_sym
86
+ when :testunit, :shoulda, :bacon # NOTE bacon doesn't really work inside of cucumber
87
+ 'test/unit/assertions'
88
+ when :minitest
89
+ 'mini/test'
90
+ when :rspec
91
+ 'spec/expectations'
92
+ when :micronaut
93
+ 'micronaut/expectations'
94
+ else
95
+ raise "Don't know what to require for #{testing_framework}"
96
+ end
97
+ end
98
+
99
+ def feature_support_extend
100
+ case testing_framework.to_sym
101
+ when :testunit, :shoulda, :bacon # NOTE bacon doesn't really work inside of cucumber
102
+ 'Test::Unit::Assertions'
103
+ when :minitest
104
+ 'Mini::Test::Assertions'
105
+ when :rspec
106
+ nil
107
+ when :micronaut
108
+ 'Micronaut::Matchers'
109
+ else
110
+ raise "Don't know what to extend for #{testing_framework}"
111
+ end
112
+ end
113
+
114
+ def github_remote
115
+ "git@github.com:#{github_username}/#{github_repo_name}.git"
116
+ end
117
+
118
+ def github_url
119
+ "http://github.com/#{github_username}/#{github_repo_name}"
120
+ end
121
+
122
+
123
+ def constant_name
124
+ self.github_repo_name.split(/[-_]/).collect{|each| each.capitalize }.join
125
+ end
126
+
127
+ def file_name_prefix
128
+ self.github_repo_name.gsub('-', '_')
129
+ end
130
+
131
+ def lib_dir
132
+ 'lib'
133
+ end
134
+
135
+ def test_dir
136
+ case testing_framework.to_sym
137
+ when :shoulda, :testunit, :minitest
138
+ 'test'
139
+ when :bacon, :rspec
140
+ 'spec'
141
+ when :micronaut
142
+ 'examples'
143
+ else
144
+ raise ArgumentError, "Don't know test dir for #{testing_framework.inspect}"
145
+ end
146
+ end
147
+
148
+ def test_filename
149
+ "#{file_name_prefix}_#{test_or_spec}.rb"
150
+ end
151
+
152
+ def test_helper_filename
153
+ "#{test_or_spec}_helper.rb"
154
+ end
155
+
156
+ def feature_filename
157
+ "#{file_name_prefix}.feature"
158
+ end
159
+
160
+ def steps_filename
161
+ "#{file_name_prefix}_steps.rb"
162
+ end
163
+
164
+ def features_dir
165
+ 'features'
166
+ end
167
+
168
+ def features_support_dir
169
+ File.join(features_dir, 'support')
170
+ end
171
+
172
+ def features_steps_dir
173
+ File.join(features_dir, 'step_definitions')
174
+ end
175
+
176
+ def test_or_spec
177
+ case testing_framework.to_sym
178
+ when :shoulda, :testunit, :minitest
179
+ 'test'
180
+ when :bacon, :rspec
181
+ 'spec'
182
+ when :micronaut
183
+ 'example'
184
+ else
185
+ raise ArgumentError, "Unknown test style: #{testing_framework}"
186
+ end
187
+ end
188
+
189
+
190
+ protected
191
+
192
+ # This is in a separate method so we can stub it out during testing
193
+ def read_git_config
194
+ # we could just use Git::Base's .config, but that relies on a repo being around already
195
+ # ... which we don't have yet, since this is part of a sanity check
196
+ lib = Git::Lib.new(nil, nil)
197
+ config = lib.parse_config '~/.gitconfig'
198
+ end
199
+
200
+ private
201
+ def create_files
202
+ unless File.exists?(target_dir) || File.directory?(target_dir)
203
+ FileUtils.mkdir target_dir
204
+ else
205
+ raise FileInTheWay, "The directory #{target_dir} already exists, aborting. Maybe move it out of the way before continuing?"
206
+ end
207
+
208
+
209
+ output_template_in_target '.gitignore'
210
+ output_template_in_target 'Rakefile'
211
+ output_template_in_target 'LICENSE'
212
+ output_template_in_target 'README.rdoc'
213
+ output_template_in_target '.document'
214
+
215
+ mkdir_in_target lib_dir
216
+ touch_in_target File.join(lib_dir, "#{file_name_prefix}.rb")
217
+
218
+ mkdir_in_target test_dir
219
+ output_template_in_target File.join(testing_framework.to_s, 'helper.rb'), File.join(test_dir, test_helper_filename)
220
+ output_template_in_target File.join(testing_framework.to_s, 'flunking.rb'), File.join(test_dir, test_filename)
221
+
222
+ if should_use_cucumber
223
+ mkdir_in_target features_dir
224
+ output_template_in_target File.join(%w(features default.feature)), File.join('features', feature_filename)
225
+
226
+ mkdir_in_target features_support_dir
227
+ output_template_in_target File.join(features_support_dir, 'env.rb')
228
+
229
+ mkdir_in_target features_steps_dir
230
+ touch_in_target File.join(features_steps_dir, steps_filename)
231
+ end
232
+
233
+ end
234
+
235
+ def use_user_git_config
236
+ git_config = self.read_git_config
237
+
238
+ unless git_config.has_key? 'user.name'
239
+ raise NoGitUserName
240
+ end
241
+
242
+ unless git_config.has_key? 'user.email'
243
+ raise NoGitUserEmail
244
+ end
245
+
246
+ unless git_config.has_key? 'github.user'
247
+ raise NoGitHubUser
248
+ end
249
+
250
+ unless git_config.has_key? 'github.token'
251
+ raise NoGitHubToken
252
+ end
253
+
254
+ self.user_name = git_config['user.name']
255
+ self.user_email = git_config['user.email']
256
+ self.github_username = git_config['github.user']
257
+ self.github_token = git_config['github.token']
258
+ end
259
+
260
+ def output_template_in_target(source, destination = source)
261
+ final_destination = File.join(target_dir, destination)
262
+
263
+ template_contents = File.read(File.join(template_dir, source))
264
+ template = ERB.new(template_contents, nil, '<>')
265
+
266
+ template_result = template.result(binding)
267
+
268
+ File.open(final_destination, 'w') {|file| file.write(template_result)}
269
+
270
+ $stdout.puts "\tcreate\t#{destination}"
271
+ end
272
+
273
+ def template_dir
274
+ File.join(File.dirname(__FILE__), 'templates')
275
+ end
276
+
277
+ def mkdir_in_target(directory)
278
+ final_destination = File.join(target_dir, directory)
279
+
280
+ FileUtils.mkdir final_destination
281
+
282
+ $stdout.puts "\tcreate\t#{directory}"
283
+ end
284
+
285
+ def touch_in_target(destination)
286
+ final_destination = File.join(target_dir, destination)
287
+ FileUtils.touch final_destination
288
+ $stdout.puts "\tcreate\t#{destination}"
289
+ end
290
+
291
+ def gitify
292
+ saved_pwd = Dir.pwd
293
+ Dir.chdir(target_dir)
294
+ begin
295
+ begin
296
+ @repo = Git.init()
297
+ rescue Git::GitExecuteError => e
298
+ raise GitInitFailed, "Encountered an error during gitification. Maybe the repo already exists, or has already been pushed to?"
299
+ end
300
+
301
+ begin
302
+ @repo.add('.')
303
+ rescue Git::GitExecuteError => e
304
+ #raise GitAddFailed, "There was some problem adding this directory to the git changeset"
305
+ raise
306
+ end
307
+
308
+ begin
309
+ @repo.commit "Initial commit to #{github_repo_name}."
310
+ rescue Git::GitExecuteError => e
311
+ raise
312
+ end
313
+
314
+ begin
315
+ @repo.add_remote('origin', github_remote)
316
+ rescue Git::GitExecuteError => e
317
+ puts "Encountered an error while adding origin remote. Maybe you have some weird settings in ~/.gitconfig?"
318
+ raise
319
+ end
320
+ ensure
321
+ Dir.chdir(saved_pwd)
322
+ end
323
+ end
324
+
325
+ def create_and_push_repo
326
+ Net::HTTP.post_form URI.parse('http://github.com/repositories'),
327
+ 'login' => github_username,
328
+ 'token' => github_token,
329
+ 'repository[description]' => summary,
330
+ 'repository[name]' => github_repo_name
331
+ # TODO do a HEAD request to see when it's ready
332
+ @repo.push('origin')
333
+ end
334
+
335
+ def enable_gem_for_repo
336
+ url = "https://github.com/#{github_username}/#{github_repo_name}/update"
337
+ `curl -F 'login=#{github_username}' -F 'token=#{github_token}' -F 'field=repository_rubygem' -F 'value=1' #{url} 2>/dev/null`
338
+ # FIXME use NET::HTTP instead of curl
339
+ #Net::HTTP.post_form URI.parse(url),
340
+ #'login' => github_username,
341
+ #'token' => github_token,
342
+ #'field' => 'repository_rubygem',
343
+ #'value' => '1'
344
+ end
345
+
346
+ end
347
+ end
@@ -0,0 +1,45 @@
1
+ class Jeweler
2
+ class Generator
3
+ class Application
4
+ class << self
5
+ def run!(*arguments)
6
+ options = Jeweler::Generator::Options.new(arguments)
7
+
8
+ if options[:show_help]
9
+ $stderr.puts options.opts
10
+ return 1
11
+ end
12
+
13
+ unless arguments.size == 1
14
+ $stderr.puts options.opts
15
+ return 1
16
+ end
17
+
18
+ github_repo_name = arguments.first
19
+
20
+ begin
21
+ generator = Jeweler::Generator.new(github_repo_name, options)
22
+ generator.run
23
+ return 0
24
+ rescue Jeweler::NoGitUserName
25
+ $stderr.puts %Q{No user.name found in ~/.gitconfig. Please tell git about yourself (see http://github.com/guides/tell-git-your-user-name-and-email-address for details). For example: git config --global user.name "mad voo"}
26
+ return 1
27
+ rescue Jeweler::NoGitUserEmail
28
+ $stderr.puts %Q{No user.email found in ~/.gitconfig. Please tell git about yourself (see http://github.com/guides/tell-git-your-user-name-and-email-address for details). For example: git config --global user.email mad.vooo@gmail.com}
29
+ return 1
30
+ rescue Jeweler::NoGitHubUser
31
+ $stderr.puts %Q{No github.user found in ~/.gitconfig. Please tell git about your GitHub account (see http://github.com/blog/180-local-github-config for details). For example: git config --global github.user defunkt}
32
+ return 1
33
+ rescue Jeweler::NoGitHubToken
34
+ $stderr.puts %Q{No github.token found in ~/.gitconfig. Please tell git about your GitHub account (see http://github.com/blog/180-local-github-config for details). For example: git config --global github.token 6ef8395fecf207165f1a82178ae1b984}
35
+ return 1
36
+ rescue Jeweler::FileInTheWay
37
+ $stderr.puts "The directory #{github_repo_name} already exists. Maybe move it out of the way before continuing?"
38
+ return 1
39
+ end
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,68 @@
1
+ class Jeweler
2
+ class Generator
3
+ class Options < Hash
4
+ attr_reader :opts
5
+
6
+ def initialize(args)
7
+ super()
8
+
9
+ self[:testing_framework] = :shoulda
10
+
11
+ @opts = OptionParser.new do |o|
12
+ o.banner = "Usage: #{File.basename($0)} [options] reponame\ne.g. #{File.basename($0)} the-perfect-gem"
13
+
14
+ o.on('--bacon', 'generate bacon specifications') do
15
+ self[:testing_framework] = :bacon
16
+ end
17
+
18
+ o.on('--shoulda', 'generate shoulda tests') do
19
+ self[:testing_framework] = :shoulda
20
+ end
21
+
22
+ o.on('--testunit', 'generate test/unit tests') do
23
+ self[:testing_framework] = :testunit
24
+ end
25
+
26
+ o.on('--minitest', 'generate minitest tests') do
27
+ self[:testing_framework] = :minitest
28
+ end
29
+
30
+ o.on('--rspec', 'generate rspec code examples') do
31
+ self[:testing_framework] = :rspec
32
+ end
33
+
34
+ o.on('--micronaut', 'generate micronaut examples') do
35
+ self[:testing_framework] = :micronaut
36
+ end
37
+
38
+ o.on('--cucumber', 'generate cucumber stories in addition to the other tests') do
39
+ self[:use_cucumber] = true
40
+ end
41
+
42
+ o.on('--create-repo', 'create the repository on GitHub') do
43
+ self[:create_repo] = true
44
+ end
45
+
46
+ o.on('--rubyforge', 'setup project for rubyforge') do
47
+ self[:rubyforge] = true
48
+ end
49
+
50
+ o.on('--summary [SUMMARY]', 'specify the summary of the project') do |summary|
51
+ self[:summary] = summary
52
+ end
53
+
54
+ o.on('--directory [DIRECTORY]', 'specify the directory to generate into') do |directory|
55
+ self[:directory] = directory
56
+ end
57
+
58
+ o.on_tail('-h', '--help', 'display this help and exit') do
59
+ self[:show_help] = true
60
+ end
61
+ end
62
+
63
+ @opts.parse!(args)
64
+ end
65
+
66
+ end
67
+ end
68
+ end