monkeyhelper-jeweler 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. data/.gitignore +7 -0
  2. data/ChangeLog.markdown +83 -0
  3. data/LICENSE +20 -0
  4. data/README.markdown +170 -0
  5. data/ROADMAP +12 -0
  6. data/Rakefile +106 -0
  7. data/VERSION.yml +4 -0
  8. data/bin/jeweler +8 -0
  9. data/features/generator/cucumber.feature +83 -0
  10. data/features/generator/directory_layout.feature +76 -0
  11. data/features/generator/dotdocument.feature +14 -0
  12. data/features/generator/env_options.feature +9 -0
  13. data/features/generator/git.feature +94 -0
  14. data/features/generator/license.feature +11 -0
  15. data/features/generator/rakefile.feature +110 -0
  16. data/features/generator/readme.feature +12 -0
  17. data/features/generator/test.feature +41 -0
  18. data/features/generator/test_helper.feature +49 -0
  19. data/features/placeholder.feature +5 -0
  20. data/features/step_definitions/debug_steps.rb +6 -0
  21. data/features/step_definitions/filesystem_steps.rb +65 -0
  22. data/features/step_definitions/generator_steps.rb +251 -0
  23. data/features/step_definitions/task_steps.rb +6 -0
  24. data/features/support/env.rb +19 -0
  25. data/features/tasks/build_gem.feature +9 -0
  26. data/features/tasks/version.feature +24 -0
  27. data/features/tasks/version_bumping.feature +33 -0
  28. data/jeweler.gemspec +204 -0
  29. data/lib/jeweler.rb +142 -0
  30. data/lib/jeweler/commands.rb +12 -0
  31. data/lib/jeweler/commands/build_gem.rb +31 -0
  32. data/lib/jeweler/commands/install_gem.rb +26 -0
  33. data/lib/jeweler/commands/release.rb +83 -0
  34. data/lib/jeweler/commands/release_to_rubyforge.rb +51 -0
  35. data/lib/jeweler/commands/setup_rubyforge.rb +38 -0
  36. data/lib/jeweler/commands/validate_gemspec.rb +30 -0
  37. data/lib/jeweler/commands/version/base.rb +41 -0
  38. data/lib/jeweler/commands/version/bump_major.rb +13 -0
  39. data/lib/jeweler/commands/version/bump_minor.rb +12 -0
  40. data/lib/jeweler/commands/version/bump_patch.rb +14 -0
  41. data/lib/jeweler/commands/version/write.rb +12 -0
  42. data/lib/jeweler/commands/write_gemspec.rb +39 -0
  43. data/lib/jeweler/errors.rb +20 -0
  44. data/lib/jeweler/gemspec_helper.rb +76 -0
  45. data/lib/jeweler/generator.rb +284 -0
  46. data/lib/jeweler/generator/application.rb +54 -0
  47. data/lib/jeweler/generator/bacon_mixin.rb +39 -0
  48. data/lib/jeweler/generator/micronaut_mixin.rb +38 -0
  49. data/lib/jeweler/generator/minitest_mixin.rb +39 -0
  50. data/lib/jeweler/generator/options.rb +77 -0
  51. data/lib/jeweler/generator/rspec_mixin.rb +39 -0
  52. data/lib/jeweler/generator/shoulda_mixin.rb +39 -0
  53. data/lib/jeweler/generator/testunit_mixin.rb +39 -0
  54. data/lib/jeweler/rubyforge_tasks.rb +46 -0
  55. data/lib/jeweler/specification.rb +67 -0
  56. data/lib/jeweler/tasks.rb +124 -0
  57. data/lib/jeweler/templates/.document +5 -0
  58. data/lib/jeweler/templates/.gitignore +5 -0
  59. data/lib/jeweler/templates/LICENSE +20 -0
  60. data/lib/jeweler/templates/README.rdoc +7 -0
  61. data/lib/jeweler/templates/Rakefile +102 -0
  62. data/lib/jeweler/templates/bacon/flunking.rb +7 -0
  63. data/lib/jeweler/templates/bacon/helper.rb +8 -0
  64. data/lib/jeweler/templates/features/default.feature +9 -0
  65. data/lib/jeweler/templates/features/support/env.rb +8 -0
  66. data/lib/jeweler/templates/micronaut/flunking.rb +7 -0
  67. data/lib/jeweler/templates/micronaut/helper.rb +17 -0
  68. data/lib/jeweler/templates/minitest/flunking.rb +7 -0
  69. data/lib/jeweler/templates/minitest/helper.rb +11 -0
  70. data/lib/jeweler/templates/rspec/flunking.rb +7 -0
  71. data/lib/jeweler/templates/rspec/helper.rb +9 -0
  72. data/lib/jeweler/templates/shoulda/flunking.rb +7 -0
  73. data/lib/jeweler/templates/shoulda/helper.rb +10 -0
  74. data/lib/jeweler/templates/testunit/flunking.rb +7 -0
  75. data/lib/jeweler/templates/testunit/helper.rb +9 -0
  76. data/lib/jeweler/version_helper.rb +128 -0
  77. data/test/fixtures/bar/VERSION.yml +4 -0
  78. data/test/fixtures/bar/bin/foo_the_ultimate_bin +1 -0
  79. data/test/fixtures/bar/hey_include_me_in_gemspec +0 -0
  80. data/test/fixtures/bar/lib/foo_the_ultimate_lib.rb +1 -0
  81. data/test/fixtures/existing-project-with-version-plaintext/.document +5 -0
  82. data/test/fixtures/existing-project-with-version-plaintext/.gitignore +5 -0
  83. data/test/fixtures/existing-project-with-version-plaintext/LICENSE +20 -0
  84. data/test/fixtures/existing-project-with-version-plaintext/README.rdoc +7 -0
  85. data/test/fixtures/existing-project-with-version-plaintext/Rakefile +82 -0
  86. data/test/fixtures/existing-project-with-version-plaintext/VERSION +1 -0
  87. data/test/fixtures/existing-project-with-version-plaintext/existing-project-with-version.gemspec +29 -0
  88. data/test/fixtures/existing-project-with-version-plaintext/lib/existing_project_with_version.rb +0 -0
  89. data/test/fixtures/existing-project-with-version-plaintext/test/existing_project_with_version_test.rb +7 -0
  90. data/test/fixtures/existing-project-with-version-plaintext/test/test_helper.rb +10 -0
  91. data/test/fixtures/existing-project-with-version-yaml/.document +5 -0
  92. data/test/fixtures/existing-project-with-version-yaml/.gitignore +5 -0
  93. data/test/fixtures/existing-project-with-version-yaml/LICENSE +20 -0
  94. data/test/fixtures/existing-project-with-version-yaml/README.rdoc +7 -0
  95. data/test/fixtures/existing-project-with-version-yaml/Rakefile +82 -0
  96. data/test/fixtures/existing-project-with-version-yaml/VERSION.yml +4 -0
  97. data/test/fixtures/existing-project-with-version-yaml/existing-project-with-version.gemspec +29 -0
  98. data/test/fixtures/existing-project-with-version-yaml/lib/existing_project_with_version.rb +0 -0
  99. data/test/fixtures/existing-project-with-version-yaml/test/existing_project_with_version_test.rb +7 -0
  100. data/test/fixtures/existing-project-with-version-yaml/test/test_helper.rb +10 -0
  101. data/test/geminstaller.yml +12 -0
  102. data/test/jeweler/commands/test_build_gem.rb +72 -0
  103. data/test/jeweler/commands/test_install_gem.rb +21 -0
  104. data/test/jeweler/commands/test_release.rb +405 -0
  105. data/test/jeweler/commands/test_release_to_rubyforge.rb +157 -0
  106. data/test/jeweler/commands/test_setup_rubyforge.rb +88 -0
  107. data/test/jeweler/commands/test_validate_gemspec.rb +27 -0
  108. data/test/jeweler/commands/test_write_gemspec.rb +92 -0
  109. data/test/jeweler/commands/version/test_base.rb +32 -0
  110. data/test/jeweler/commands/version/test_bump_major.rb +22 -0
  111. data/test/jeweler/commands/version/test_bump_minor.rb +19 -0
  112. data/test/jeweler/commands/version/test_bump_patch.rb +20 -0
  113. data/test/jeweler/commands/version/test_write.rb +23 -0
  114. data/test/shoulda_macros/jeweler_macros.rb +35 -0
  115. data/test/test_application.rb +139 -0
  116. data/test/test_gemspec_helper.rb +40 -0
  117. data/test/test_generator.rb +154 -0
  118. data/test/test_generator_initialization.rb +113 -0
  119. data/test/test_generator_mixins.rb +18 -0
  120. data/test/test_helper.rb +133 -0
  121. data/test/test_jeweler.rb +174 -0
  122. data/test/test_options.rb +116 -0
  123. data/test/test_specification.rb +61 -0
  124. data/test/test_tasks.rb +51 -0
  125. data/test/test_version_helper.rb +153 -0
  126. metadata +228 -0
@@ -0,0 +1,13 @@
1
+ class Jeweler
2
+ module Commands
3
+ module Version
4
+ class BumpMajor < Base
5
+
6
+ def update_version
7
+ self.version_helper.bump_major
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ class Jeweler
2
+ module Commands
3
+ module Version
4
+ class BumpMinor < Base
5
+
6
+ def update_version
7
+ self.version_helper.bump_minor
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ class Jeweler
2
+ module Commands
3
+ module Version
4
+ class BumpPatch < Base
5
+
6
+ def update_version
7
+ self.version_helper.bump_patch
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,12 @@
1
+ class Jeweler
2
+ module Commands
3
+ module Version
4
+ class Write < Base
5
+ attr_accessor :major, :minor, :patch
6
+ def update_version
7
+ version_helper.update_to major, minor, patch
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,39 @@
1
+ class Jeweler
2
+ module Commands
3
+ class WriteGemspec
4
+ attr_accessor :base_dir, :gemspec, :version, :output, :gemspec_helper, :version_helper
5
+
6
+ def initialize
7
+ self.output = $stdout
8
+ end
9
+
10
+ def run
11
+ version_helper.refresh
12
+ gemspec_helper.spec.version = version_helper.to_s
13
+ gemspec_helper.spec.date = Time.now
14
+
15
+ gemspec_helper.write
16
+
17
+ output.puts "Generated: #{gemspec_helper.path}"
18
+ end
19
+
20
+ def gemspec_helper
21
+ @gemspec_helper ||= GemSpecHelper.new(self.gemspec, self.base_dir)
22
+ end
23
+
24
+ def self.build_for(jeweler)
25
+ command = new
26
+
27
+ command.base_dir = jeweler.base_dir
28
+ command.gemspec = jeweler.gemspec
29
+ command.version = jeweler.version
30
+ command.output = jeweler.output
31
+ command.gemspec_helper = jeweler.gemspec_helper
32
+ command.version_helper = jeweler.version_helper
33
+
34
+ command
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,20 @@
1
+ class Jeweler
2
+ # Gemspec related error
3
+ class GemspecError < StandardError
4
+ end
5
+
6
+ class VersionYmlError < StandardError
7
+ end
8
+
9
+ # Occurs when interacting with RubyForge, and an expected project isn't available on RubyForge.
10
+ class MissingRubyForgePackageError < StandardError
11
+ end
12
+
13
+ # Occurs when interacting with RubyForge, and 'rubyforge_project' isn't set on the Gem::Specification
14
+ class NoRubyForgeProjectInGemspecError < StandardError
15
+ end
16
+
17
+ # Occurs when interacting with RubyForge, and the 'rubyforge_project' isn't setup in ~/.rubyforge/autoconfig.yml or it doesn't exist on RubyForge
18
+ class RubyForgeProjectNotConfiguredError < StandardError
19
+ end
20
+ end
@@ -0,0 +1,76 @@
1
+ class Jeweler
2
+
3
+ class GemSpecHelper
4
+
5
+ attr_accessor :spec, :base_dir
6
+
7
+ def initialize(spec, base_dir = nil)
8
+ self.spec = spec
9
+ self.base_dir = base_dir || ''
10
+
11
+ yield spec if block_given?
12
+ end
13
+
14
+ def valid?
15
+ begin
16
+ parse
17
+ true
18
+ rescue
19
+ false
20
+ end
21
+ end
22
+
23
+ def write
24
+ normalize_files(:files)
25
+ normalize_files(:files)
26
+ normalize_files(:extra_rdoc_files)
27
+
28
+ File.open(path, 'w') do |f|
29
+ gemspec_ruby = @spec.to_ruby
30
+ gemspec_ruby = prettyify_array(gemspec_ruby, :files)
31
+ gemspec_ruby = prettyify_array(gemspec_ruby, :test_files)
32
+ gemspec_ruby = prettyify_array(gemspec_ruby, :extra_rdoc_files)
33
+ f.write gemspec_ruby
34
+ end
35
+ end
36
+
37
+ def path
38
+ denormalized_path = File.join(@base_dir, "#{@spec.name}.gemspec")
39
+ absolute_path = File.expand_path(denormalized_path)
40
+ absolute_path.gsub(Dir.getwd + File::SEPARATOR, '')
41
+ end
42
+
43
+ def parse
44
+ data = File.read(path)
45
+ parsed_gemspec = nil
46
+ Thread.new { parsed_gemspec = eval("$SAFE = 3\n#{data}", binding, path) }.join
47
+ parsed_gemspec
48
+ end
49
+
50
+ def normalize_files(array_name)
51
+ array = @spec.send(array_name)
52
+ # only keep files, no directories, and sort
53
+ array = array.select do |path|
54
+ File.file? File.join(@base_dir, path)
55
+ end.sort
56
+
57
+ @spec.send("#{array_name}=", array)
58
+ end
59
+
60
+ def prettyify_array(gemspec_ruby, array_name)
61
+ gemspec_ruby.gsub(/s\.#{array_name.to_s} = \[.+?\]/) do |match|
62
+ leadin, files = match[0..-2].split("[")
63
+ leadin + "[\n #{files.split(",").join(",\n ")}\n ]"
64
+ end
65
+ end
66
+
67
+ def gem_path
68
+ File.join(@base_dir, 'pkg', parse.file_name)
69
+ end
70
+
71
+ def update_version(version)
72
+ @spec.version = version.to_s
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,284 @@
1
+ require 'git'
2
+ require 'erb'
3
+
4
+ require 'net/http'
5
+ require 'uri'
6
+
7
+ require 'jeweler/generator/bacon_mixin'
8
+ require 'jeweler/generator/micronaut_mixin'
9
+ require 'jeweler/generator/minitest_mixin'
10
+ require 'jeweler/generator/rspec_mixin'
11
+ require 'jeweler/generator/shoulda_mixin'
12
+ require 'jeweler/generator/testunit_mixin'
13
+
14
+ class Jeweler
15
+ class NoGitUserName < StandardError
16
+ end
17
+ class NoGitUserEmail < StandardError
18
+ end
19
+ class FileInTheWay < StandardError
20
+ end
21
+ class NoGitHubRepoNameGiven < StandardError
22
+ end
23
+ class NoGitHubUser < StandardError
24
+ end
25
+ class NoGitHubToken < StandardError
26
+ end
27
+ class GitInitFailed < StandardError
28
+ end
29
+
30
+ class Generator
31
+ attr_accessor :target_dir, :user_name, :user_email, :summary, :testing_framework,
32
+ :project_name, :github_username, :github_token,
33
+ :repo, :should_create_repo, :should_use_cucumber, :should_setup_rubyforge
34
+
35
+ DEFAULT_TESTING_FRAMEWORK = :shoulda
36
+
37
+ def initialize(project_name, options = {})
38
+ if project_name.nil? || project_name.squeeze.strip == ""
39
+ raise NoGitHubRepoNameGiven
40
+ end
41
+
42
+ self.project_name = project_name
43
+
44
+ self.testing_framework = (options[:testing_framework] || DEFAULT_TESTING_FRAMEWORK).to_sym
45
+ begin
46
+ generator_mixin_name = "#{self.testing_framework.to_s.capitalize}Mixin"
47
+ generator_mixin = self.class.const_get(generator_mixin_name)
48
+ extend generator_mixin
49
+ rescue NameError => e
50
+ raise ArgumentError, "Unsupported testing framework (#{testing_framework})"
51
+ end
52
+
53
+
54
+ self.target_dir = options[:directory] || self.project_name
55
+
56
+ self.should_create_repo = options[:create_repo]
57
+ self.summary = options[:summary] || 'TODO'
58
+ self.should_use_cucumber = options[:use_cucumber]
59
+ self.should_setup_rubyforge = options[:rubyforge]
60
+
61
+ use_user_git_config
62
+
63
+ end
64
+
65
+ def run
66
+ create_files
67
+ gitify
68
+ $stdout.puts "Jeweler has prepared your gem in #{target_dir}"
69
+ if should_create_repo
70
+ create_and_push_repo
71
+ $stdout.puts "Jeweler has pushed your repo to #{project_homepage}"
72
+ enable_gem_for_repo
73
+ $stdout.puts "Jeweler has enabled gem building for your repo"
74
+ end
75
+ end
76
+
77
+ def git_remote
78
+ "git@github.com:#{github_username}/#{project_name}.git"
79
+ end
80
+
81
+ def project_homepage
82
+ "http://github.com/#{github_username}/#{project_name}"
83
+ end
84
+
85
+ def constant_name
86
+ self.project_name.split(/[-_]/).collect{|each| each.capitalize }.join
87
+ end
88
+
89
+ def lib_filename
90
+ "#{project_name}.rb"
91
+ end
92
+
93
+ def require_name
94
+ self.project_name
95
+ end
96
+
97
+ def file_name_prefix
98
+ self.project_name.gsub('-', '_')
99
+ end
100
+
101
+ def lib_dir
102
+ 'lib'
103
+ end
104
+
105
+ def feature_filename
106
+ "#{project_name}.feature"
107
+ end
108
+
109
+ def steps_filename
110
+ "#{project_name}_steps.rb"
111
+ end
112
+
113
+ def features_dir
114
+ 'features'
115
+ end
116
+
117
+ def features_support_dir
118
+ File.join(features_dir, 'support')
119
+ end
120
+
121
+ def features_steps_dir
122
+ File.join(features_dir, 'step_definitions')
123
+ end
124
+
125
+ protected
126
+
127
+ # This is in a separate method so we can stub it out during testing
128
+ def read_git_config
129
+ # we could just use Git::Base's .config, but that relies on a repo being around already
130
+ # ... which we don't have yet, since this is part of a sanity check
131
+ lib = Git::Lib.new(nil, nil)
132
+ config = lib.parse_config '~/.gitconfig'
133
+ end
134
+
135
+ private
136
+ def create_files
137
+ unless File.exists?(target_dir) || File.directory?(target_dir)
138
+ FileUtils.mkdir target_dir
139
+ else
140
+ raise FileInTheWay, "The directory #{target_dir} already exists, aborting. Maybe move it out of the way before continuing?"
141
+ end
142
+
143
+
144
+ output_template_in_target '.gitignore'
145
+ output_template_in_target 'Rakefile'
146
+ output_template_in_target 'LICENSE'
147
+ output_template_in_target 'README.rdoc'
148
+ output_template_in_target '.document'
149
+
150
+ mkdir_in_target lib_dir
151
+ touch_in_target File.join(lib_dir, lib_filename)
152
+
153
+ mkdir_in_target test_dir
154
+ output_template_in_target File.join(testing_framework.to_s, 'helper.rb'), File.join(test_dir, test_helper_filename)
155
+ output_template_in_target File.join(testing_framework.to_s, 'flunking.rb'), File.join(test_dir, test_filename)
156
+
157
+ if should_use_cucumber
158
+ mkdir_in_target features_dir
159
+ output_template_in_target File.join(%w(features default.feature)), File.join('features', feature_filename)
160
+
161
+ mkdir_in_target features_support_dir
162
+ output_template_in_target File.join(features_support_dir, 'env.rb')
163
+
164
+ mkdir_in_target features_steps_dir
165
+ touch_in_target File.join(features_steps_dir, steps_filename)
166
+ end
167
+
168
+ end
169
+
170
+ def use_user_git_config
171
+ git_config = self.read_git_config
172
+
173
+ unless git_config.has_key? 'user.name'
174
+ raise NoGitUserName
175
+ end
176
+
177
+ unless git_config.has_key? 'user.email'
178
+ raise NoGitUserEmail
179
+ end
180
+
181
+ unless git_config.has_key? 'github.user'
182
+ raise NoGitHubUser
183
+ end
184
+
185
+ if should_create_repo
186
+ unless git_config.has_key? 'github.token'
187
+ raise NoGitHubToken
188
+ end
189
+ end
190
+
191
+ self.user_name = git_config['user.name']
192
+ self.user_email = git_config['user.email']
193
+ self.github_username = git_config['github.user']
194
+ self.github_token = git_config['github.token']
195
+ end
196
+
197
+ def output_template_in_target(source, destination = source)
198
+ final_destination = File.join(target_dir, destination)
199
+
200
+ template_contents = File.read(File.join(template_dir, source))
201
+ template = ERB.new(template_contents, nil, '<>')
202
+
203
+ template_result = template.result(binding)
204
+
205
+ File.open(final_destination, 'w') {|file| file.write(template_result)}
206
+
207
+ $stdout.puts "\tcreate\t#{destination}"
208
+ end
209
+
210
+ def template_dir
211
+ File.join(File.dirname(__FILE__), 'templates')
212
+ end
213
+
214
+ def mkdir_in_target(directory)
215
+ final_destination = File.join(target_dir, directory)
216
+
217
+ FileUtils.mkdir final_destination
218
+
219
+ $stdout.puts "\tcreate\t#{directory}"
220
+ end
221
+
222
+ def touch_in_target(destination)
223
+ final_destination = File.join(target_dir, destination)
224
+ FileUtils.touch final_destination
225
+ $stdout.puts "\tcreate\t#{destination}"
226
+ end
227
+
228
+ def gitify
229
+ saved_pwd = Dir.pwd
230
+ Dir.chdir(target_dir)
231
+ begin
232
+ begin
233
+ @repo = Git.init()
234
+ rescue Git::GitExecuteError => e
235
+ raise GitInitFailed, "Encountered an error during gitification. Maybe the repo already exists, or has already been pushed to?"
236
+ end
237
+
238
+ begin
239
+ @repo.add('.')
240
+ rescue Git::GitExecuteError => e
241
+ #raise GitAddFailed, "There was some problem adding this directory to the git changeset"
242
+ raise
243
+ end
244
+
245
+ begin
246
+ @repo.commit "Initial commit to #{project_name}."
247
+ rescue Git::GitExecuteError => e
248
+ raise
249
+ end
250
+
251
+ begin
252
+ @repo.add_remote('origin', git_remote)
253
+ rescue Git::GitExecuteError => e
254
+ puts "Encountered an error while adding origin remote. Maybe you have some weird settings in ~/.gitconfig?"
255
+ raise
256
+ end
257
+ ensure
258
+ Dir.chdir(saved_pwd)
259
+ end
260
+ end
261
+
262
+ def create_and_push_repo
263
+ Net::HTTP.post_form URI.parse('http://github.com/repositories'),
264
+ 'login' => github_username,
265
+ 'token' => github_token,
266
+ 'repository[description]' => summary,
267
+ 'repository[name]' => project_name
268
+ # TODO do a HEAD request to see when it's ready
269
+ @repo.push('origin')
270
+ end
271
+
272
+ def enable_gem_for_repo
273
+ url = "https://github.com/#{github_username}/#{project_name}/update"
274
+ `curl -F 'login=#{github_username}' -F 'token=#{github_token}' -F 'field=repository_rubygem' -F 'value=1' #{url} 2>/dev/null`
275
+ # FIXME use NET::HTTP instead of curl
276
+ #Net::HTTP.post_form URI.parse(url),
277
+ #'login' => github_username,
278
+ #'token' => github_token,
279
+ #'field' => 'repository_rubygem',
280
+ #'value' => '1'
281
+ end
282
+
283
+ end
284
+ end