hoe 1.12.2 → 2.0.0

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.tar.gz.sig CHANGED
Binary file
@@ -1,3 +1,22 @@
1
+ === 2.0.0 / 2009-06-02
2
+
3
+ * 3 major enhancements:
4
+
5
+ * Added a plugin system and extracted nearly everything into separate plugins.
6
+ * Added Clean, Debug, Deps, Flay, Flog, Inline, Package, Publish, Rake, Rcov, Signing, and Test plugins
7
+
8
+ * 9 minor enhancements:
9
+
10
+ * Added Hoe::spec replacing old Hoe.new spec form. Now with DSL flavors!
11
+ * Added DEFAULT_CONFIG so plugins can add to it.
12
+ * Added pluggable! to declare your package depends on rubygems 1.3.1+.
13
+ * Changes are now included in the gem's description.
14
+ * Deprecated Hoe.new spec form.
15
+ * Filled in all the blanks on rdoc.
16
+ * Refactored nearly all the spec logic down to much smaller/cleaner pieces.
17
+ * Updated templates to use new form. No clue how best to update yours. :P
18
+ * Version number is now auto-searchable by grepping in all the files.
19
+
1
20
  === 1.12.2 / 2009-04-16
2
21
 
3
22
  * 1 minor enhancement:
@@ -4,6 +4,18 @@ README.txt
4
4
  Rakefile
5
5
  bin/sow
6
6
  lib/hoe.rb
7
+ lib/hoe/clean.rb
8
+ lib/hoe/debug.rb
9
+ lib/hoe/deps.rb
10
+ lib/hoe/flay.rb
11
+ lib/hoe/flog.rb
12
+ lib/hoe/inline.rb
13
+ lib/hoe/package.rb
14
+ lib/hoe/publish.rb
15
+ lib/hoe/rake.rb
16
+ lib/hoe/rcov.rb
17
+ lib/hoe/signing.rb
18
+ lib/hoe/test.rb
7
19
  template/.autotest.erb
8
20
  template/History.txt.erb
9
21
  template/Manifest.txt.erb
data/README.txt CHANGED
@@ -6,58 +6,45 @@
6
6
 
7
7
  == DESCRIPTION:
8
8
 
9
- Hoe is a simple rake/rubygems helper for project Rakefiles. It
10
- generates all the usual tasks for projects including rdoc generation,
11
- testing, packaging, and deployment.
12
-
13
- Tasks Provided:
14
-
15
- * announce - Create news email file and post to rubyforge.
16
- * audit - Run ZenTest against the package.
17
- * check_extra_deps - Install missing dependencies.
18
- * check_manifest - Verify the manifest.
19
- * clean - Clean up all the extras.
20
- * config_hoe - Create a fresh ~/.hoerc file.
21
- * debug_gem - Show information about the gem.
22
- * default - Run the default task(s).
23
- * deps:email - Print a contact list for gems dependent on this gem
24
- * deps:fetch - Fetch all the dependent gems of this gem into tarballs
25
- * deps:list - List all the dependent gems of this gem
26
- * docs - Build the docs HTML Files
27
- * email - Generate email announcement file.
28
- * flay - Analyze for code duplication.
29
- * flog - Analyze code complexity.
30
- * gem - Build the gem file hoe-1.9.0.gem
31
- * generate_key - Generate a key for signing your gems.
32
- * install_gem - Install the package as a gem.
33
- * multi - Run the test suite using multiruby.
34
- * package - Build all the packages
35
- * post_blog - Post announcement to blog.
36
- * post_news - Post announcement to rubyforge.
37
- * publish_docs - Publish RDoc to RubyForge.
38
- * rcov - Analyze code coverage with tests
39
- * release - Package and upload the release to rubyforge.
40
- * ridocs - Generate ri locally for testing.
41
- * tasks - Generate a list of tasks for doco.
42
- * test - Run the test suite.
43
- * test_deps - Show which test files fail when run alone.
9
+ Hoe is a rake/rubygems helper for project Rakefiles. It helps generate
10
+ rubygems and includes a dynamic plug-in system allowing for easy
11
+ extensibility. Hoe ships with plug-ins for all your usual project
12
+ tasks including rdoc generation, testing, packaging, and deployment.
13
+
14
+ Plug-ins Provided:
15
+
16
+ * Hoe::Clean
17
+ * Hoe::Debug
18
+ * Hoe::Deps
19
+ * Hoe::Flay
20
+ * Hoe::Flog
21
+ * Hoe::Inline
22
+ * Hoe::Package
23
+ * Hoe::Publish
24
+ * Hoe::RCov
25
+ * Hoe::Signing
26
+ * Hoe::Test
44
27
 
45
28
  See class rdoc for help. Hint: ri Hoe
46
29
 
47
30
  == FEATURES/PROBLEMS:
48
31
 
32
+ * Includes a dynamic plug-in system allowing for easy extensibility.
33
+ * Auto-intuits changes, description, summary, and version.
34
+ * Uses a manifest for safe and secure deployment.
49
35
  * Provides 'sow' for quick project directory creation.
50
- * Make making and maintaining Rakefiles fun and easy.
36
+ * Sow uses a simple ERB templating system allowing you to capture your
37
+ project patterns
51
38
 
52
39
  == SYNOPSIS:
53
40
 
54
41
  % sow [group] project
55
42
 
56
- or
43
+ or:
57
44
 
58
45
  require 'hoe'
59
46
 
60
- Hoe.new(projectname, version) do |p|
47
+ Hoe.spec projectname do
61
48
  # ... project specific data ...
62
49
  end
63
50
 
data/Rakefile CHANGED
@@ -1,31 +1,24 @@
1
1
  # -*- ruby -*-
2
2
 
3
+ $: << 'lib'
4
+
3
5
  require './lib/hoe.rb'
4
6
 
7
+ # TODO:
8
+ # Hoe.plugin :perforce
9
+ # Hoe.plugin :minitest
10
+
5
11
  Hoe.add_include_dirs("../../minitest/dev/lib")
6
12
 
7
- Hoe.new("hoe", Hoe::VERSION) do |hoe|
8
- hoe.rubyforge_name = "seattlerb"
13
+ Hoe.spec "hoe" do
14
+ developer "Ryan Davis", "ryand-ruby@zenspider.com"
9
15
 
10
- hoe.developer("Ryan Davis", "ryand-ruby@zenspider.com")
16
+ self.rubyforge_name = "seattlerb"
17
+ self.testlib = :minitest
11
18
 
12
- hoe.testlib = :minitest
13
- hoe.blog_categories << "Seattle.rb" << "Ruby"
14
- end
19
+ blog_categories << "Seattle.rb" << "Ruby"
15
20
 
16
- desc "Generate a list of tasks for doco. RDOC=1 for commented output"
17
- task :tasks do
18
- tasks = `rake -T`.scan(/rake (\w+)\s+# (.*)/)
19
- tasks.reject! { |t,d| t =~ /^(clobber|tasks|re(package|docs))/ }
20
- max = tasks.map { |x,y| x.size }.max
21
-
22
- tasks.each do |t,d|
23
- if ENV['RDOC'] then
24
- puts "# %-#{max+2}s %s" % [t + "::", d]
25
- else
26
- puts "* %-#{max}s - %s" % [t, d]
27
- end
28
- end
21
+ pluggable!
29
22
  end
30
23
 
31
24
  # vim: syntax=Ruby
data/bin/sow CHANGED
@@ -67,11 +67,9 @@ if $d || $t then
67
67
  FileUtils.mv temp_dir, "#{project}/#{$d ? 'dev' : 'trunk'}", :verbose => true
68
68
  end
69
69
 
70
- WINDOZE = /mswin|mingw/ =~ RUBY_PLATFORM
71
-
72
70
  puts
73
71
  puts "... done, now go fix all occurrences of '#{XIF}':"
74
- if WINDOZE then
72
+ if Hoe::WINDOZE then
75
73
  puts `findstr /N /S /C:#{XIF} #{project}\\*`
76
74
  else
77
75
  puts `find #{project} -type f | xargs grep -n #{XIF}`.gsub(/\A|\n/, "\n ")
data/lib/hoe.rb CHANGED
@@ -19,134 +19,57 @@ rescue Gem::LoadError
19
19
  end
20
20
 
21
21
  ##
22
- # hoe - a tool to help rake
23
- #
24
- # Hoe is a simple rake/rubygems helper for project Rakefiles. It
25
- # generates all the usual tasks for projects including rdoc generation,
26
- # testing, packaging, and deployment.
22
+ # Hoe is a simple rake/rubygems helper for project Rakefiles. It helps
23
+ # generate rubygems and includes a dynamic plug-in system allowing for
24
+ # easy extensibility. Hoe ships with plug-ins for all your usual
25
+ # project tasks including rdoc generation, testing, packaging, and
26
+ # deployment.
27
27
  #
28
28
  # == Using Hoe
29
29
  #
30
30
  # === Basics
31
31
  #
32
- # Use this as a minimal starting point:
33
- #
34
- # require 'hoe'
35
- # require './lib/project.rb'
36
- #
37
- # Hoe.new("project_name", Project::VERSION) do |p|
38
- # p.rubyforge_name = "rf_project"
39
- # p.developer("Joe Blow", "joe@example.com")
40
- # # add other details here
41
- # end
32
+ # Sow generates a new project from scratch. Sow uses a simple ERB
33
+ # templating system allowing you to capture patterns common to your
34
+ # projects. Run `sow` and then see ~/.hoe_template for more info:
42
35
  #
43
- # # add other tasks here
36
+ # % sow project_name
37
+ # ...
38
+ # % cd project_name
44
39
  #
45
- # === Tasks Provided:
46
- #
47
- # announce:: Create news email file and post to rubyforge.
48
- # audit:: Run ZenTest against the package.
49
- # check_extra_deps:: Install missing dependencies.
50
- # check_manifest:: Verify the manifest.
51
- # clean:: Clean up all the extras.
52
- # config_hoe:: Create a fresh ~/.hoerc file.
53
- # debug_gem:: Show information about the gem.
54
- # default:: Run the default task(s).
55
- # deps:email:: Print a contact list for gems dependent on this gem
56
- # deps:fetch:: Fetch all the dependent gems of this gem into tarballs
57
- # deps:list:: List all the dependent gems of this gem
58
- # docs:: Build the docs HTML Files
59
- # email:: Generate email announcement file.
60
- # flay:: Analyze for code duplication.
61
- # flog:: Analyze code complexity.
62
- # gem:: Build the gem file hoe-1.9.0.gem
63
- # generate_key:: Generate a key for signing your gems.
64
- # install_gem:: Install the package as a gem.
65
- # multi:: Run the test suite using multiruby.
66
- # package:: Build all the packages
67
- # post_blog:: Post announcement to blog.
68
- # post_news:: Post announcement to rubyforge.
69
- # publish_docs:: Publish RDoc to RubyForge.
70
- # rcov:: Analyze code coverage with tests
71
- # release:: Package and upload the release to rubyforge.
72
- # ridocs:: Generate ri locally for testing.
73
- # tasks:: Generate a list of tasks for doco.
74
- # test:: Run the test suite.
75
- # test_deps:: Show which test files fail when run alone.
40
+ # and have at it.
76
41
  #
77
42
  # === Extra Configuration Options:
78
43
  #
79
- # Run +config_hoe+ to generate a new ~/.hoerc file. The file is a
80
- # YAML formatted config file with the following settings:
81
- #
82
- # exclude:: A regular expression of files to exclude from
83
- # +check_manifest+.
84
- # publish_on_announce:: Run +publish_docs+ when you run +release+.
85
- # signing_key_file:: Signs your gems with this private key.
86
- # signing_cert_file:: Signs your gem with this certificate.
87
- # blogs:: An array of hashes of blog settings.
88
- #
89
- # Run +config_hoe+ and see ~/.hoerc for examples.
90
- #
91
- # === Signing Gems:
92
- #
93
- # Run the 'generate_key' task. This will:
94
- #
95
- # 1. Configure your ~/.hoerc.
96
- # 2. Generate a signing key and certificate.
97
- # 3. Install the private key and public certificate files into ~/.gem.
98
- # 4. Upload the certificate to RubyForge.
99
- #
100
- # Hoe will now generate signed gems when the package task is run. If you have
101
- # multiple machines you build gems on, be sure to install your key and
102
- # certificate on each machine.
103
- #
104
- # Keep your private key secret! Keep your private key safe!
105
- #
106
- # To make sure your gems are signed run:
44
+ # Hoe maintains a config file for cross-project values. The file is
45
+ # located at <tt>~/.hoerc</tt>. The file is a YAML formatted config file with
46
+ # the following settings (extended by plugins):
107
47
  #
108
- # rake package; tar tf pkg/yourproject-1.2.3.gem
48
+ # exclude:: A regular expression of files to exclude from +check_manifest+.
109
49
  #
110
- # If your gem is signed you will see:
50
+ # Run <tt>`rake config_hoe`</tt> and see ~/.hoerc for examples.
111
51
  #
112
- # data.tar.gz
113
- # data.tar.gz.sig
114
- # metadata.gz
115
- # metadata.gz.sig
52
+ # == Extending Hoe
116
53
  #
117
- # === Platform awareness
54
+ # Hoe can be extended via its plugin system. Hoe searches out all
55
+ # installed files matching <tt>'hoe/*.rb'</tt> and loads them. Those files are
56
+ # expected to define a module matching the file name. The module must
57
+ # define a define task method and can optionally define an initialize
58
+ # method. Both methods must be named to match the file. eg
118
59
  #
119
- # Hoe allows bundling of pre-compiled extensions in the +package+ task.
120
- #
121
- # To create a package for your current platform:
122
- #
123
- # rake package INLINE=1
124
- #
125
- # This will force Hoe analize your +Inline+ already compiled
126
- # extensions and include them in your gem.
127
- #
128
- # If somehow you need to force a specific platform:
129
- #
130
- # rake package INLINE=1 FORCE_PLATFORM=mswin32
131
- #
132
- # This will set the +Gem::Specification+ platform to the one indicated in
133
- # +FORCE_PLATFORM+ (instead of default Gem::Platform::CURRENT)
60
+ # module Hoe::Blah
61
+ # def initialize_blah # optional
62
+ # # ...
63
+ # end
134
64
  #
65
+ # def define_blah_tasks
66
+ # # ...
67
+ # end
68
+ # end
135
69
 
136
70
  class Hoe
137
- VERSION = '1.12.2'
138
- GEMURL = URI.parse 'http://gems.rubyforge.org' # for namespace :deps below
139
-
140
- ruby_prefix = Config::CONFIG['prefix']
141
- sitelibdir = Config::CONFIG['sitelibdir']
142
-
143
- ##
144
- # Configuration for the supported test frameworks for test task.
145
-
146
- SUPPORTED_TEST_FRAMEWORKS = {
147
- :testunit => "test/unit",
148
- :minitest => "minitest/autorun",
149
- }
71
+ # duh
72
+ VERSION = '2.0.0'
150
73
 
151
74
  ##
152
75
  # Used to add extra flags to RUBY_FLAGS.
@@ -162,62 +85,36 @@ class Hoe
162
85
  RUBY_FLAGS = ENV['RUBY_FLAGS'] || default_ruby_flags
163
86
 
164
87
  ##
165
- # Used to add flags to test_unit (e.g., -n test_borked).
166
- #
167
- # eg FILTER="-n test_blah"
168
-
169
- FILTER = ENV['FILTER'] || ENV['TESTOPTS']
88
+ # Default configuration values for .hoerc. Plugins should populate
89
+ # this on load.
170
90
 
171
- # :stopdoc:
91
+ DEFAULT_CONFIG = {
92
+ "exclude" => /tmp$|CVS|\.svn|\.log$/,
93
+ }
172
94
 
173
- DLEXT = Config::CONFIG['DLEXT']
95
+ ##
96
+ # True if you're a masochist developer. Used for building commands.
174
97
 
175
98
  WINDOZE = /mswin|mingw/ =~ RUBY_PLATFORM unless defined? WINDOZE
176
99
 
177
- DIFF = if WINDOZE
178
- 'diff.exe'
179
- else
180
- if system("gdiff", __FILE__, __FILE__)
181
- 'gdiff' # solaris and kin suck
182
- else
183
- 'diff'
184
- end
185
- end unless defined? DIFF
186
-
187
- # :startdoc:
188
-
189
100
  ##
190
101
  # *MANDATORY*: The author(s) of the package. (can be array)
191
102
 
192
103
  attr_accessor :author
193
104
 
194
- ##
195
- # Populated automatically from the manifest. List of executables.
196
-
197
- attr_accessor :bin_files # :nodoc:
198
-
199
- ##
200
- # *Optional*: An array of the project's blog categories. Defaults to project name.
201
-
202
- attr_accessor :blog_categories
203
-
204
105
  ##
205
106
  # Optional: A description of the release's latest changes. Auto-populates.
206
107
 
207
108
  attr_accessor :changes
208
109
 
209
- ##
210
- # Optional: An array of file patterns to delete on clean.
211
-
212
- attr_accessor :clean_globs
213
-
214
110
  ##
215
111
  # Optional: A description of the project. Auto-populates.
216
112
 
217
113
  attr_accessor :description
218
114
 
219
115
  ##
220
- # Optional: What sections from the readme to use for auto-description. Defaults to %w(description).
116
+ # Optional: What sections from the readme to use for
117
+ # auto-description. Defaults to %w(description).
221
118
 
222
119
  attr_accessor :description_sections
223
120
 
@@ -243,46 +140,16 @@ class Hoe
243
140
 
244
141
  attr_accessor :extra_rdoc_files
245
142
 
246
- ##
247
- # Optional: flay threshold to determine threshold failure. [default: 1200-100]
248
-
249
- attr_accessor :flay_threshold
250
-
251
- ##
252
- # Optional: flog threshold to determine threshold failure. [default: 1500-200]
253
-
254
- attr_accessor :flog_threshold
255
-
256
143
  ##
257
144
  # Optional: The filename for the project history. [default: History.txt]
258
145
 
259
146
  attr_accessor :history_file
260
147
 
261
- ##
262
- # Populated automatically from the manifest. List of library files.
263
-
264
- attr_accessor :lib_files # :nodoc:
265
-
266
- ##
267
- # Optional: Array of incompatible versions for multiruby filtering. Used as a regex.
268
-
269
- attr_accessor :multiruby_skip
270
-
271
148
  ##
272
149
  # *MANDATORY*: The name of the release.
273
150
 
274
151
  attr_accessor :name
275
152
 
276
- ##
277
- # Optional: Should package create a tarball? [default: true]
278
-
279
- attr_accessor :need_tar
280
-
281
- ##
282
- # Optional: Should package create a zipfile? [default: false]
283
-
284
- attr_accessor :need_zip
285
-
286
153
  ##
287
154
  # Optional: A post-install message to be displayed when gem is installed.
288
155
 
@@ -293,26 +160,6 @@ class Hoe
293
160
 
294
161
  attr_accessor :readme_file
295
162
 
296
- ##
297
- # Optional: Name of RDoc destination directory on Rubyforge. [default: +name+]
298
-
299
- attr_accessor :remote_rdoc_dir
300
-
301
- ##
302
- # Optional: RSpec dirs. [default: %w(spec lib)]
303
-
304
- attr_accessor :rspec_dirs
305
-
306
- ##
307
- # Optional: RSpec options. [default: []]
308
-
309
- attr_accessor :rspec_options
310
-
311
- ##
312
- # Optional: Flags for RDoc rsync. [default: "-av --delete"]
313
-
314
- attr_accessor :rsync_args
315
-
316
163
  ##
317
164
  # Optional: The name of the rubyforge project. [default: name.downcase]
318
165
 
@@ -338,21 +185,11 @@ class Hoe
338
185
 
339
186
  attr_accessor :summary_sentences
340
187
 
341
- ##
342
- # Populated automatically from the manifest. List of tests.
343
-
344
- attr_accessor :test_files # :nodoc:
345
-
346
188
  ##
347
189
  # Optional: An array of test file patterns [default: test/**/test_*.rb]
348
190
 
349
191
  attr_accessor :test_globs
350
192
 
351
- ##
352
- # Optional: What test library to require [default: :testunit]
353
-
354
- attr_accessor :testlib
355
-
356
193
  ##
357
194
  # Optional: The url(s) of the project. (can be array). Auto-populates.
358
195
 
@@ -364,16 +201,41 @@ class Hoe
364
201
  attr_accessor :version
365
202
 
366
203
  ##
367
- # Add extra dirs to both $: and RUBY_FLAGS (for test runs)
204
+ # Add extra dirs to both $: and RUBY_FLAGS (for test runs and rakefile deps)
368
205
 
369
206
  def self.add_include_dirs(*dirs)
370
207
  dirs = dirs.flatten
371
208
  $:.unshift(*dirs)
372
209
  s = File::PATH_SEPARATOR
373
- Hoe::RUBY_FLAGS.sub!(/-I/, "-I#{dirs.join(s)}#{s}")
210
+ RUBY_FLAGS.sub!(/-I/, "-I#{dirs.join(s)}#{s}")
211
+ end
212
+
213
+ ##
214
+ # Find and load all plugin files.
215
+ #
216
+ # It is called at the end of hoe.rb
217
+
218
+ def self.load_plugins
219
+ loaded = {}
220
+
221
+ Gem.find_files("hoe/*.rb").each do |plugin|
222
+ name = File.basename plugin
223
+ next if loaded[name]
224
+ begin
225
+ load plugin
226
+ loaded[name] = true
227
+ rescue LoadError => e
228
+ warn "error loading #{plugin.inspect}: #{e.message}. skipping..."
229
+ end
230
+ end
374
231
  end
375
232
 
376
- def self.normalize_names project
233
+ ##
234
+ # Normalize a project name into the project, file, and klass cases (?!?).
235
+ #
236
+ # no, I have no idea how to describe this. Does the thing with the stuff.
237
+
238
+ def self.normalize_names project # :nodoc:
377
239
  project = project.tr('-', '_').gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, '')
378
240
  klass = project.gsub(/(?:^|_)([a-z])/) { $1.upcase }
379
241
  file_name = project
@@ -381,98 +243,50 @@ class Hoe
381
243
  return project, file_name, klass
382
244
  end
383
245
 
384
- def normalize_deps deps
385
- Array(deps).map { |o| String === o ? [o] : o }
386
- end
246
+ ##
247
+ # Activate a plugin.
387
248
 
388
- def missing name
389
- warn "** #{name} is missing or in the wrong format for auto-intuiting."
390
- warn " run `sow blah` and look at its text files"
249
+ def self.plugin name
250
+ self.plugins << name
391
251
  end
392
252
 
393
- def timebomb n, m, finis = '2010-04-01', start = '2009-03-14'
394
- finis = Time.parse finis
395
- start = Time.parse start
396
- rest = (finis - Time.now)
397
- full = (finis - start)
253
+ ##
254
+ # Return the list of activated plugins.
398
255
 
399
- ((n - m) * rest / full).to_i + m
256
+ def self.plugins
257
+ @@plugins ||= []
400
258
  end
401
259
 
402
- def initialize(name, version) # :nodoc:
403
- self.name = name
404
- self.version = version
405
-
406
- # Defaults
407
- self.author = []
408
- self.blog_categories = [name]
409
- self.clean_globs = %w(diff diff.txt email.txt ri deps .source_index
410
- *.gem **/*~ **/.*~ **/*.rbc coverage*)
411
- self.description_sections = %w(description)
412
- self.email = []
413
- self.extra_deps = []
414
- self.extra_dev_deps = []
415
- self.extra_rdoc_files = []
416
- self.flay_threshold = timebomb 1200, 100 # 80% of average :(
417
- self.flog_threshold = timebomb 1500, 1000 # 80% of average :(
418
- self.history_file = "History.txt"
419
- self.multiruby_skip = []
420
- self.need_tar = true
421
- self.need_zip = false
422
- self.post_install_message = nil
423
- self.readme_file = "README.txt"
424
- self.remote_rdoc_dir = name
425
- self.rspec_dirs = %w(spec lib)
426
- self.rspec_options = []
427
- self.rsync_args = '-av --delete'
428
- self.rubyforge_name = name.downcase
429
- self.spec_extras = {}
430
- self.summary_sentences = 1
431
- self.test_globs = ['test/**/test_*.rb']
432
- self.testlib = :testunit
433
-
434
- yield self if block_given?
260
+ ##
261
+ # Create a new hoe-specification executing the supplied block
435
262
 
436
- # Intuit values:
263
+ def self.spec name, &block
264
+ spec = self.new name
265
+ spec.activate_plugins
266
+ spec.instance_eval(&block)
267
+ spec.post_initialize
268
+ spec # TODO: remove?
269
+ end
437
270
 
438
- readme = File.read(readme_file).split(/^(=+ .*)$/)[1..-1] rescue ''
439
- unless readme.empty? then
440
- sections = readme.map { |s|
441
- s =~ /^=/ ? s.strip.downcase.chomp(':').split.last : s.strip
442
- }
443
- sections = Hash[*sections]
444
- desc = sections.values_at(*description_sections).join("\n\n")
445
- summ = desc.split(/\.\s+/).first(summary_sentences).join(". ")
271
+ ##
272
+ # Activate plugin modules and add them to the current instance.
446
273
 
447
- self.description ||= desc
448
- self.summary ||= summ
449
- self.url ||= readme[1].gsub(/^\* /, '').split(/\n/).grep(/\S+/)
450
- else
451
- missing readme_file
274
+ def activate_plugins
275
+ self.class.constants.reject { |n| n =~ /^[A-Z_]+$/ }.each do |name|
276
+ self.extend Hoe.const_get(name)
452
277
  end
453
278
 
454
- self.changes ||= begin
455
- h = File.read(history_file)
456
- h.split(/^(===.*)/)[1..2].join.strip
457
- rescue
458
- missing history_file
459
- ''
460
- end
461
-
462
- %w(email author).each do |field|
463
- value = self.send(field)
464
- if value.nil? or value.empty? then
465
- if Time.now < Time.local(2008, 4, 1) then
466
- warn "Hoe #{field} value not set - Fix by 2008-04-01!"
467
- self.send "#{field}=", "doofus"
468
- else
469
- abort "Hoe #{field} value not set. aborting"
470
- end
471
- end
279
+ self.class.plugins.each do |plugin|
280
+ send "initialize_#{plugin}" rescue nil
472
281
  end
282
+ end
283
+
284
+ ##
285
+ # Add standard and user defined dependencies to the spec.
473
286
 
287
+ def add_dependencies
474
288
  hoe_deps = {
475
- 'rake' => ">= #{RAKEVERSION}",
289
+ 'rake' => ">= #{RAKEVERSION}",
476
290
  'rubyforge' => ">= #{::RubyForge::VERSION}",
477
291
  }
478
292
 
@@ -486,143 +300,37 @@ class Hoe
486
300
  else
487
301
  extra_dev_deps << ['hoe', ">= #{VERSION}"] unless hoe_deps.has_key? name
488
302
  end
489
-
490
- define_tasks
491
303
  end
492
304
 
493
- def developer name, email
494
- self.author << name
495
- self.email << email
496
- end
497
-
498
- def with_config # :nodoc:
499
- rc = File.expand_path("~/.hoerc")
500
- exists = File.exist? rc
501
- config = exists ? YAML.load_file(rc) : {}
502
- yield(config, rc)
503
- end
504
-
505
- def define_tasks # :nodoc:
506
- default_tasks = []
507
-
508
- if File.directory? "test" then
509
- desc 'Run the test suite. Use FILTER or TESTOPTS to add flags/args.'
510
- task :test do
511
- ruby make_test_cmd
512
- end
513
-
514
- desc 'Run the test suite using multiruby.'
515
- task :multi do
516
- ruby make_test_cmd(:multi)
517
- end
518
-
519
- desc 'Show which test files fail when run alone.'
520
- task :test_deps do
521
- tests = Dir["test/**/test_*.rb"] + Dir["test/**/*_test.rb"]
522
-
523
- paths = ['bin', 'lib', 'test'].join(File::PATH_SEPARATOR)
524
- null_dev = WINDOZE ? '> NUL 2>&1' : '&> /dev/null'
525
-
526
- tests.each do |test|
527
- if not system "ruby -I#{paths} #{test} #{null_dev}" then
528
- puts "Dependency Issues: #{test}"
529
- end
530
- end
531
- end
532
-
533
- default_tasks << :test
534
- end
535
-
536
- if File.directory? "spec" then
537
- begin
538
- require 'spec/rake/spectask'
539
-
540
- desc "Run all specifications"
541
- Spec::Rake::SpecTask.new(:spec) do |t|
542
- t.libs = self.rspec_dirs
543
- t.spec_opts = self.rspec_options
544
- end
545
- rescue LoadError
546
- # do nothing
547
- end
548
- default_tasks << :spec
549
- end
550
-
551
- desc 'Run the default task(s).'
552
- task :default => default_tasks
553
-
554
- begin # take a whack at defining rcov tasks
555
- require 'rcov/rcovtask'
556
-
557
- Rcov::RcovTask.new do |t|
558
- pattern = ENV['PATTERN'] || 'test/test_*.rb'
559
-
560
- t.test_files = FileList[pattern]
561
- t.verbose = true
562
- t.rcov_opts << "--no-color"
563
- t.rcov_opts << "--save coverage.info"
564
- t.rcov_opts << "-x ^/"
565
- end
566
-
567
- # this is for my emacs rcov overlay stuff on emacswiki.
568
- task :rcov_overlay do
569
- path = ENV["FILE"]
570
- rcov, eol = Marshal.load(File.read("coverage.info")).last[path], 1
571
- puts rcov[:lines].zip(rcov[:coverage]).map { |line, coverage|
572
- bol, eol = eol, eol + line.length
573
- [bol, eol, "#ffcccc"] unless coverage
574
- }.compact.inspect
575
- end
576
- rescue LoadError
577
- # skip
578
- end
579
-
580
- begin
581
- require 'flay'
582
- require 'flay_task'
583
- FlayTask.new :flay, self.flay_threshold
584
- rescue LoadError
585
- # skip
586
- end
587
-
588
- begin
589
- require 'flog'
590
- require 'flog_task'
591
- FlogTask.new :flog, self.flog_threshold
592
- rescue LoadError
593
- # skip
594
- end
595
-
596
- ############################################################
597
- # Packaging and Installing
598
-
599
- signing_key = nil
600
- cert_chain = []
305
+ ##
306
+ # Define the Gem::Specification.
601
307
 
602
- with_config do |config, path|
603
- break unless config['signing_key_file'] and config['signing_cert_file']
604
- key_file = File.expand_path config['signing_key_file'].to_s
605
- signing_key = key_file if File.exist? key_file
308
+ def define_spec
309
+ self.spec = Gem::Specification.new do |s|
310
+ dirs = Dir['{lib,ext}']
606
311
 
607
- cert_file = File.expand_path config['signing_cert_file'].to_s
608
- cert_chain << cert_file if File.exist? cert_file
609
- end
312
+ s.name = name
313
+ s.version = version if version
314
+ s.summary = summary
315
+ s.email = email
316
+ s.homepage = Array(url).first
317
+ s.rubyforge_project = rubyforge_name
318
+ s.description = description
319
+ s.files = File.read("Manifest.txt").split(/\r?\n\r?/)
320
+ s.executables = s.files.grep(/^bin/) { |f| File.basename(f) }
321
+ s.bindir = "bin"
322
+ s.require_paths = dirs unless dirs.empty?
323
+ s.rdoc_options = ['--main', readme_file]
324
+ s.has_rdoc = true
325
+ s.post_install_message = post_install_message
326
+ s.test_files = Dir[*self.test_globs]
610
327
 
611
- self.spec = Gem::Specification.new do |s|
612
- s.name = name
613
- s.version = version
614
- s.summary = summary
615
328
  case author
616
329
  when Array
617
330
  s.authors = author
618
331
  else
619
- s.author = author
332
+ s.author = author
620
333
  end
621
- s.email = email
622
- s.homepage = Array(url).first
623
- s.rubyforge_project = rubyforge_name
624
-
625
- s.description = description
626
334
 
627
335
  extra_deps.each do |dep|
628
336
  s.add_dependency(*dep)
@@ -632,67 +340,9 @@ class Hoe
632
340
  s.add_development_dependency(*dep)
633
341
  end
634
342
 
635
- s.files = File.read("Manifest.txt").delete("\r").split(/\n/)
636
- s.executables = s.files.grep(/^bin/) { |f| File.basename(f) }
637
-
638
- s.bindir = "bin"
639
- dirs = Dir['{lib,ext}']
640
- s.require_paths = dirs unless dirs.empty?
641
-
642
- s.rdoc_options = ['--main', readme_file]
643
-
644
343
  s.extra_rdoc_files += s.files.grep(/txt$/)
645
344
  s.extra_rdoc_files.reject! { |f| f =~ %r%^(test|spec|vendor|template|data|tmp)/% }
646
345
  s.extra_rdoc_files += @extra_rdoc_files
647
- s.has_rdoc = true
648
-
649
- s.post_install_message = post_install_message
650
-
651
- if test ?f, "test/test_all.rb" then
652
- s.test_file = "test/test_all.rb"
653
- else
654
- s.test_files = Dir[*self.test_globs]
655
- end
656
-
657
- if signing_key and cert_chain then
658
- s.signing_key = signing_key
659
- s.cert_chain = cert_chain
660
- end
661
-
662
- ############################################################
663
- # Allow automatic inclusion of compiled extensions
664
- if ENV['INLINE'] then
665
- s.platform = ENV['FORCE_PLATFORM'] || Gem::Platform::CURRENT
666
-
667
- # Try collecting Inline extensions for +name+
668
- if defined?(Inline) then
669
- directory 'lib/inline'
670
-
671
- Inline.registered_inline_classes.each do |cls|
672
- name = cls.name # TODO: what about X::Y::Z?
673
- # name of the extension is CamelCase
674
- alternate_name = if name =~ /[A-Z]/ then
675
- name.gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, '')
676
- elsif name =~ /_/ then
677
- name.capitalize.gsub(/_([a-z])/) { $1.upcase }
678
- end
679
-
680
- extensions = Dir.chdir(Inline::directory) {
681
- Dir["Inline_{#{name},#{alternate_name}}_*.#{DLEXT}"]
682
- }
683
-
684
- extensions.each do |ext|
685
- # add the inlined extension to the spec files
686
- s.files += ["lib/inline/#{ext}"]
687
-
688
- # include the file in the tasks
689
- file "lib/inline/#{ext}" => ["lib/inline"] do
690
- cp File.join(Inline::directory, ext), "lib/inline"
691
- end
692
- end
693
- end
694
- end
695
- end
696
346
 
697
347
  # Do any extra stuff the user wants
698
348
  spec_extras.each do |msg, val|
@@ -705,448 +355,116 @@ class Hoe
705
355
  end
706
356
  end
707
357
 
708
- desc 'Show information about the gem.'
709
- task :debug_gem do
710
- puts spec.to_ruby
711
- end
712
-
713
- self.lib_files = spec.files.grep(/^(lib|ext)/)
714
- self.bin_files = spec.files.grep(/^bin/)
715
- self.test_files = spec.files.grep(/^test/)
716
-
717
- Rake::GemPackageTask.new spec do |pkg|
718
- pkg.need_tar = @need_tar
719
- pkg.need_zip = @need_zip
720
- end
721
-
722
- desc 'Install the package as a gem.'
723
- task :install_gem => [:clean, :package, :check_extra_deps] do
724
- install_gem Dir['pkg/*.gem'].first
725
- end
726
-
727
- desc 'Package and upload the release to rubyforge.'
728
- task :release => [:clean, :package] do |t|
729
- v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
730
- abort "Versions don't match #{v} vs #{version}" if v != version
731
- pkg = "pkg/#{name}-#{version}"
732
-
733
- if $DEBUG then
734
- puts "release_id = rf.add_release #{rubyforge_name.inspect}, #{name.inspect}, #{version.inspect}, \"#{pkg}.tgz\""
735
- puts "rf.add_file #{rubyforge_name.inspect}, #{name.inspect}, release_id, \"#{pkg}.gem\""
736
- end
737
-
738
- rf = RubyForge.new.configure
739
- puts "Logging in"
740
- rf.login
741
-
742
- c = rf.userconfig
743
- c["release_notes"] = description if description
744
- c["release_changes"] = changes if changes
745
- c["preformatted"] = true
746
-
747
- files = [(@need_tar ? "#{pkg}.tgz" : nil),
748
- (@need_zip ? "#{pkg}.zip" : nil),
749
- "#{pkg}.gem"].compact
750
-
751
- puts "Releasing #{name} v. #{version}"
752
- rf.add_release rubyforge_name, name, version, *files
753
- end
754
-
755
- ############################################################
756
- # Doco
757
-
758
- Rake::RDocTask.new(:docs) do |rd|
759
- rd.main = readme_file
760
- rd.options << '-d' if (`which dot` =~ /\/dot/) unless
761
- ENV['NODOT'] || WINDOZE
762
- rd.rdoc_dir = 'doc'
763
-
764
- rd.rdoc_files += spec.require_paths
765
- rd.rdoc_files += spec.extra_rdoc_files
766
-
767
- title = "#{name}-#{version} Documentation"
768
- title = "#{rubyforge_name}'s " + title if rubyforge_name != name
769
-
770
- rd.options << "-t" << title
771
- end
772
-
773
- desc 'Generate ri locally for testing.'
774
- task :ridocs => :clean do
775
- sh %q{ rdoc --ri -o ri . }
776
- end
777
-
778
- desc 'Publish RDoc to RubyForge.'
779
- task :publish_docs => [:clean, :docs] do
780
- config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
781
- host = "#{config["username"]}@rubyforge.org"
782
-
783
- remote_dir = "/var/www/gforge-projects/#{rubyforge_name}/#{remote_rdoc_dir}"
784
- local_dir = 'doc'
785
-
786
- sh %{rsync #{rsync_args} #{local_dir}/ #{host}:#{remote_dir}}
787
- end
788
-
789
- # no doco for this one
790
- task :publish_on_announce do
791
- with_config do |config, _|
792
- Rake::Task['publish_docs'].invoke if config["publish_on_announce"]
793
- end
794
- end
795
-
796
- ############################################################
797
- # Dependencies:
798
-
799
- namespace :deps do
800
- require 'zlib' # HACK for rubygems 1.3.0
801
- require 'rubygems/remote_fetcher'
802
-
803
- @@index = nil
804
-
805
- def self.get_source_index
806
- return @@index if @@index
807
-
808
- dump = unless File.exist? '.source_index' then
809
- url = GEMURL + "Marshal.#{Gem.marshal_version}.Z"
810
- dump = Gem::RemoteFetcher.fetcher.fetch_path url
811
- dump = Gem.inflate dump
812
- open '.source_index', 'wb' do |io| io.write dump end
813
- dump
814
- else
815
- open '.source_index', 'rb' do |io| io.read end
816
- end
817
-
818
- @@index = Marshal.load dump
819
- end
820
-
821
- def self.get_latest_gems
822
- @@cache ||= get_source_index.latest_specs
823
- end
824
-
825
- def self.get_gems_by_name
826
- @@by_name ||= Hash[*get_latest_gems.map { |gem|
827
- [gem.name, gem, gem.full_name, gem]
828
- }.flatten]
829
- end
830
-
831
- def self.dependent_upon name
832
- get_latest_gems.find_all { |gem|
833
- gem.dependencies.any? { |dep| dep.name == name }
834
- }
835
- end
836
-
837
-
838
- desc "List all the dependent gems of this gem"
839
- task :list do
840
- gems = self.get_gems_by_name
841
- gem = gems[self.name]
842
-
843
- abort "Couldn't find gem: #{self.name}" unless gem
844
-
845
- deps = self.dependent_upon self.name
846
- max = deps.map { |s| s.full_name.size }.max
847
-
848
- puts " dependents:"
849
- unless deps.empty? then
850
- deps.sort_by { |spec| spec.full_name }.each do |spec|
851
- vers = spec.dependencies.find {|s| s.name == name }.requirement_list
852
- puts " %-*s - %s" % [max, spec.full_name, vers.join(", ")]
853
- end
854
- else
855
- puts " none"
856
- end
857
- end
858
-
859
- desc "Print a contact list for gems dependent on this gem"
860
- task :email do
861
- gems = self.get_gems_by_name
862
- gem = gems[self.name]
863
-
864
- abort "Couldn't find gem: #{self.name}" unless gem
865
-
866
- deps = self.dependent_upon self.name
867
-
868
- email = deps.map { |s| s.email }.flatten.sort.uniq
869
- email = email.map { |s| s.split(/,\s*/) }.flatten.sort.uniq
870
-
871
- email.map! { |s| # don't you people realize how easy this is?
872
- s.gsub(/ at | _at_ |\s*(atmark|@nospam@|-at?-|@at?@|<at?>|\[at?\]|\(at?\))\s*/i, '@').gsub(/\s*(dot|\[d(ot)?\]|\.dot\.)\s*/i, '.').gsub(/\s+com$/, '.com')
873
- }
874
-
875
- bad, good = email.partition { |e| e !~ /^[\w.+-]+\@[\w.+-]+$/ }
876
-
877
- warn "Rejecting #{bad.size} email. I couldn't unmunge them." unless
878
- bad.empty?
879
-
880
- puts good.join(", ")
881
- end
882
-
883
- desc "Fetch all the dependent gems of this gem into tarballs"
884
- task :fetch do
885
- gems = self.get_gems_by_name
886
- gem = gems[self.name]
887
- deps = self.dependent_upon self.name
888
-
889
- mkdir "deps" unless File.directory? "deps"
890
- Dir.chdir "deps" do
891
- begin
892
- deps.sort_by { |spec| spec.full_name }.each do |spec|
893
- full_name = spec.full_name
894
- tgz_name = "#{full_name}.tgz"
895
- gem_name = "#{full_name}.gem"
896
-
897
- next if File.exist? tgz_name
898
- FileUtils.rm_rf [full_name, gem_name]
899
-
900
- begin
901
- warn "downloading #{full_name}"
902
- Gem::RemoteFetcher.fetcher.download(spec, GEMURL, Dir.pwd)
903
- FileUtils.mv "cache/#{gem_name}", '.'
904
- rescue Gem::RemoteFetcher::FetchError
905
- warn " failed"
906
- next
907
- end
908
-
909
- warn "converting #{gem_name} to tarball"
910
-
911
- system "gem unpack #{gem_name} 2> /dev/null"
912
- system "gem spec -l #{gem_name} > #{full_name}/gemspec.rb"
913
- system "tar zmcf #{tgz_name} #{full_name}"
914
- FileUtils.rm_rf [full_name, gem_name, "cache"]
915
- end
916
- ensure
917
- FileUtils.rm_rf "cache"
918
- end
919
- end
920
- end
921
- end
922
-
923
- ############################################################
924
- # Misc/Maintenance:
925
-
926
- desc 'Run ZenTest against the package.'
927
- task :audit do
928
- libs = %w(lib test ext).join(File::PATH_SEPARATOR)
929
- sh "zentest -I=#{libs} #{spec.files.grep(/^(lib|test)/).join(' ')}"
930
- end
931
-
932
- task :clobber_rcov # in case rcov didn't load
358
+ unless self.version then
359
+ version = nil
933
360
 
934
- desc 'Clean up all the extras.'
935
- task :clean => [ :clobber_docs, :clobber_package, :clobber_rcov ] do
936
- clean_globs.each do |pattern|
937
- files = Dir[pattern]
938
- rm_rf files, :verbose => true unless files.empty?
361
+ spec.files.each do |file|
362
+ next unless File.exist? file
363
+ version = File.read(file)[/VERSION = ([\"\'])([\d\.]+)\1/, 2]
364
+ break if version
939
365
  end
940
- end
941
366
 
942
- desc 'Install missing dependencies.'
943
- task :check_extra_deps do
944
- # extra_deps = [["rubyforge", ">= 1.0.0"], ["rake", ">= 0.8.1"]]
945
- extra_deps.each do |dep|
946
- begin
947
- gem(*dep)
948
- rescue Gem::LoadError
949
- install_gem(*dep)
950
- end
951
- end
367
+ spec.version = self.version = version
952
368
  end
953
369
 
954
- desc 'Create a fresh ~/.hoerc file.'
955
- task :config_hoe do
956
- with_config do |config, path|
957
- default_config = {
958
- "exclude" => /tmp$|CVS|\.svn|\.log$/,
959
- "publish_on_announce" => false,
960
- "signing_key_file" => "~/.gem/gem-private_key.pem",
961
- "signing_cert_file" => "~/.gem/gem-public_cert.pem",
962
- "blogs" => [
963
- {
964
- "user" => "user",
965
- "password" => "password",
966
- "url" => "url",
967
- "blog_id" => "blog_id",
968
- "extra_headers" => {
969
- "mt_convert_breaks" => "markdown"
970
- },
971
- }
972
- ],
973
- }
974
- File.open(path, "w") do |f|
975
- YAML.dump(default_config.merge(config), f)
976
- end
977
-
978
- editor = ENV['EDITOR'] || 'vi'
979
- system "#{editor} #{path}" if ENV['SHOW_EDITOR'] != 'no'
980
- end
981
- end
370
+ raise "Need version" unless self.version
371
+ end
982
372
 
983
- desc 'Generate email announcement file.'
984
- task :email do
985
- require 'rubyforge'
986
- subject, title, body, urls = announcement
987
-
988
- File.open("email.txt", "w") do |mail|
989
- mail.puts "Subject: [ANN] #{subject}"
990
- mail.puts
991
- mail.puts title
992
- mail.puts
993
- mail.puts urls
994
- mail.puts
995
- mail.puts body
996
- mail.puts
997
- mail.puts urls
998
- end
999
- puts "Created email.txt"
1000
- end
373
+ ##
374
+ # Convenience method to set add to both the author and email fields.
1001
375
 
1002
- desc 'Post announcement to blog.'
1003
- task :post_blog do
1004
- require 'xmlrpc/client'
376
+ def developer name, email
377
+ self.author << name
378
+ self.email << email
379
+ end
1005
380
 
1006
- with_config do |config, path|
1007
- break unless config['blogs']
381
+ ##
382
+ # Create a newly initialized hoe spec. If a block is given, yield on
383
+ # it and finish post_initialize steps. This is deprecated behavior
384
+ # and should be switched from Hoe.new to Hoe.spec.
1008
385
 
1009
- subject, title, body, urls = announcement
1010
- body += "\n\n#{urls}"
386
+ def initialize name, version = nil # :nodoc:
387
+ self.name = name
388
+ self.version = version
1011
389
 
1012
- config['blogs'].each do |site|
1013
- server = XMLRPC::Client.new2(site['url'])
1014
- content = site['extra_headers'].merge(:title => title,
1015
- :description => body,
1016
- :categories => blog_categories)
390
+ self.author = []
391
+ self.changes = nil
392
+ self.description = nil
393
+ self.description_sections = %w(description)
394
+ self.email = []
395
+ self.extra_deps = []
396
+ self.extra_dev_deps = []
397
+ self.extra_rdoc_files = []
398
+ self.history_file = "History.txt"
399
+ self.post_install_message = nil
400
+ self.readme_file = "README.txt"
401
+ self.rubyforge_name = name.downcase
402
+ self.spec = nil
403
+ self.spec_extras = {}
404
+ self.summary = nil
405
+ self.summary_sentences = 1
406
+ self.test_globs = ['test/**/test_*.rb']
407
+ self.url = nil
1017
408
 
1018
- result = server.call('metaWeblog.newPost',
1019
- site['blog_id'],
1020
- site['user'],
1021
- site['password'],
1022
- content,
1023
- true)
1024
- end
1025
- end
409
+ if block_given? then
410
+ warn "Hoe.new {...} deprecated. Switch to Hoe.spec."
411
+ self.activate_plugins
412
+ yield self
413
+ post_initialize
1026
414
  end
415
+ end
1027
416
 
1028
- desc 'Post announcement to rubyforge.'
1029
- task :post_news do
1030
- require 'rubyforge'
1031
- subject, title, body, urls = announcement
417
+ ##
418
+ # Intuit values from the readme and history files.
1032
419
 
1033
- rf = RubyForge.new.configure
1034
- rf.login
1035
- rf.post_news(rubyforge_name, subject, "#{title}\n\n#{body}")
1036
- puts "Posted to rubyforge"
1037
- end
420
+ def intuit_values
421
+ readme = File.read(readme_file).split(/^(=+ .*)$/)[1..-1] rescue ''
422
+ unless readme.empty? then
423
+ sections = readme.map { |s|
424
+ s =~ /^=/ ? s.strip.downcase.chomp(':').split.last : s.strip
425
+ }
426
+ sections = Hash[*sections]
427
+ desc = sections.values_at(*description_sections).join("\n\n")
428
+ summ = desc.split(/\.\s+/).first(summary_sentences).join(". ")
1038
429
 
1039
- desc 'Create news email file and post to rubyforge.'
1040
- task :announce => [:email, :post_news, :post_blog, :publish_on_announce ]
1041
-
1042
- desc 'Verify the manifest.'
1043
- task :check_manifest => :clean do
1044
- f = "Manifest.tmp"
1045
- require 'find'
1046
- files = []
1047
- with_config do |config, _|
1048
- exclusions = config["exclude"]
1049
- abort "exclude entry missing from .hoerc. Aborting." if exclusions.nil?
1050
- Find.find '.' do |path|
1051
- next unless File.file? path
1052
- next if path =~ exclusions
1053
- files << path[2..-1]
1054
- end
1055
- files = files.sort.join "\n"
1056
- File.open f, 'w' do |fp| fp.puts files end
1057
- system "#{DIFF} -du Manifest.txt #{f}"
1058
- rm f
1059
- end
430
+ self.description ||= desc
431
+ self.summary ||= summ
432
+ self.url ||= readme[1].gsub(/^\* /, '').split(/\n/).grep(/\S+/)
433
+ else
434
+ missing readme_file
1060
435
  end
1061
436
 
1062
- desc 'Generate a key for signing your gems.'
1063
- task :generate_key do
1064
- email = Array(spec.email)
1065
- abort "No email in your gemspec" if email.nil? or email.empty?
1066
-
1067
- key_file = with_config { |config, _| config['signing_key_file'] }
1068
- cert_file = with_config { |config, _| config['signing_cert_file'] }
1069
-
1070
- if key_file.nil? or cert_file.nil? then
1071
- ENV['SHOW_EDITOR'] ||= 'no'
1072
- Rake::Task['config_hoe'].invoke
1073
-
1074
- key_file = with_config { |config, _| config['signing_key_file'] }
1075
- cert_file = with_config { |config, _| config['signing_cert_file'] }
1076
- end
1077
-
1078
- key_file = File.expand_path key_file
1079
- cert_file = File.expand_path cert_file
1080
-
1081
- unless File.exist? key_file or File.exist? cert_file then
1082
- warn "NOTICE: using #{email.first} for certificate" if email.size > 1
1083
-
1084
- sh "gem cert --build #{email.first}"
1085
- mv "gem-private_key.pem", key_file, :verbose => true
1086
- mv "gem-public_cert.pem", cert_file, :verbose => true
1087
-
1088
- puts "Installed key and certificate."
1089
-
1090
- rf = RubyForge.new.configure
1091
- rf.login
1092
-
1093
- cert_package = "#{rubyforge_name}-certificates"
1094
-
1095
- begin
1096
- rf.lookup 'package', cert_package
1097
- rescue
1098
- rf.create_package rubyforge_name, cert_package
1099
- end
437
+ self.changes ||= begin
438
+ h = File.read(history_file)
439
+ h.split(/^(===.*)/)[1..2].join.strip
440
+ rescue
441
+ missing history_file
442
+ ''
443
+ end
444
+ end
1100
445
 
1101
- begin
1102
- rf.lookup('release', cert_package)['certificates']
1103
- rf.add_file rubyforge_name, cert_package, 'certificates', cert_file
1104
- rescue
1105
- rf.create_package rubyforge_name, cert_package
1106
- rf.add_release rubyforge_name, cert_package, 'certificates', cert_file
1107
- end
446
+ ##
447
+ # Load activated plugins by calling their define tasks method.
1108
448
 
1109
- puts "Uploaded certificate to release \"certificates\" in package #{cert_package}"
1110
- else
1111
- puts "Keys already exist: #{key_file} and #{cert_file}"
1112
- end
449
+ def load_plugin_tasks
450
+ self.class.plugins.each do |plugin|
451
+ send "define_#{plugin}_tasks"
1113
452
  end
1114
- end # end define
1115
-
1116
- def install_gem name, version = nil
1117
- gem_cmd = Gem.default_exec_format % 'gem'
1118
- sudo = 'sudo ' unless WINDOZE
1119
- local = '--local' unless version
1120
- version = "--version '#{version}'" if version
1121
- sh "#{sudo}#{gem_cmd} install #{local} #{name} #{version}"
1122
453
  end
1123
454
 
1124
- def make_test_cmd multi = false # :nodoc:
1125
- framework = SUPPORTED_TEST_FRAMEWORKS[testlib]
1126
- raise "unsupported test framework #{testlib}" unless framework
1127
-
1128
- tests = ["rubygems", framework] +
1129
- test_globs.map { |g| Dir.glob(g) }.flatten
1130
- tests.map! {|f| %(require "#{f}")}
1131
-
1132
- cmd = "#{RUBY_FLAGS} -e '#{tests.join("; ")}' #{FILTER}"
1133
-
1134
- if multi then
1135
- ENV['EXCLUDED_VERSIONS'] = multiruby_skip.join ":"
1136
- cmd = "-S multiruby #{cmd}"
1137
- end
455
+ ##
456
+ # Bitch about a file that is missing data or unparsable for intuiting values.
1138
457
 
1139
- cmd
458
+ def missing name
459
+ warn "** #{name} is missing or in the wrong format for auto-intuiting."
460
+ warn " run `sow blah` and look at its text files"
1140
461
  end
1141
462
 
1142
- def announcement # :nodoc:
1143
- changes = self.changes.rdoc_to_markdown
1144
- subject = "#{name} #{version} Released"
1145
- title = "#{name} version #{version} has been released!"
1146
- body = "#{description}\n\nChanges:\n\n#{changes}".rdoc_to_markdown
1147
- urls = Array(url).map { |s| "* <#{s.strip.rdoc_to_markdown}>" }.join("\n")
463
+ ##
464
+ # Normalize the dependencies.
1148
465
 
1149
- return subject, title, body, urls
466
+ def normalize_deps deps
467
+ Array(deps).map { |o| String === o ? [o] : o }
1150
468
  end
1151
469
 
1152
470
  ##
@@ -1155,75 +473,60 @@ class Hoe
1155
473
  # changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
1156
474
  # summary, *description = p.paragraphs_of('README.txt', 3, 3..8)
1157
475
 
1158
- def paragraphs_of(path, *paragraphs)
476
+ def paragraphs_of path, *paragraphs
1159
477
  File.read(path).delete("\r").split(/\n\n+/).values_at(*paragraphs)
1160
478
  end
1161
- end
1162
479
 
1163
- module Rake
1164
- module TaskManager
1165
- ##
1166
- # This gives us access to the tasks already defined in rake.
1167
- def all_tasks
1168
- @tasks
1169
- end
480
+ ##
481
+ # Tell the world you're a pluggable package (ie you require rubygems 1.3.1+)
482
+
483
+ def pluggable!
484
+ abort "update rubygems to >= 1.3.1" unless Gem.respond_to? :find_files
485
+ spec_extras[:required_rubygems_version] = '>= 1.3.1'
1170
486
  end
1171
487
 
1172
488
  ##
1173
- # Simple shortcut for Rake.application.all_tasks
1174
- def self.all_tasks
1175
- Rake.application.all_tasks
489
+ # Finalize configuration
490
+
491
+ def post_initialize
492
+ intuit_values
493
+ validate_fields
494
+ add_dependencies
495
+ define_spec
496
+ load_plugin_tasks
1176
497
  end
1177
498
 
1178
499
  ##
1179
- # Hooks into rake and allows us to clear out a task by name or
1180
- # regexp. Use this if you want to completely override a task instead
1181
- # of extend it.
1182
- def self.clear_tasks(*tasks)
1183
- tasks.flatten.each do |name|
1184
- case name
1185
- when Regexp then
1186
- all_tasks.delete_if { |k,_| k =~ name }
1187
- else
1188
- all_tasks.delete(name)
1189
- end
1190
- end
500
+ # Provide a linear degrading value from n to m over start to finis dates.
501
+
502
+ def timebomb n, m, finis = '2010-04-01', start = '2009-03-14'
503
+ finis = Time.parse finis
504
+ start = Time.parse start
505
+ rest = (finis - Time.now)
506
+ full = (finis - start)
507
+
508
+ ((n - m) * rest / full).to_i + m
1191
509
  end
1192
510
 
1193
511
  ##
1194
- # Removes the last action added to a task. Use this when two
1195
- # libraries define the same task and you only want one of the
1196
- # actions.
1197
- #
1198
- # require 'hoe'
1199
- # require 'tasks/rails'
1200
- # Rake.undo("test") # rolls out rails' test task
1201
- def self.undo(*names)
1202
- names.each do |name|
1203
- all_tasks[name].actions.delete_at(-1)
512
+ # Verify that mandatory fields are set.
513
+
514
+ def validate_fields
515
+ %w(email author).each do |field|
516
+ value = self.send(field)
517
+ abort "Hoe #{field} value not set. aborting" if value.nil? or value.empty?
1204
518
  end
1205
519
  end
1206
- end
1207
-
1208
- # :enddoc:
1209
520
 
1210
- class ::Rake::SshDirPublisher # :nodoc:
1211
- attr_reader :host, :remote_dir, :local_dir
1212
- end
521
+ ##
522
+ # Load or create a default config and yield it
1213
523
 
1214
- class String
1215
- def rdoc_to_markdown
1216
- self.gsub(/^mailto:/, '').gsub(/^(=+)/) { "#" * $1.size }
524
+ def with_config # :nodoc:
525
+ rc = File.expand_path("~/.hoerc")
526
+ exists = File.exist? rc
527
+ config = exists ? YAML.load_file(rc) : {}
528
+ yield(config, rc)
1217
529
  end
1218
- end
1219
530
 
1220
- if $0 == __FILE__ then
1221
- out = `rake -T | egrep -v "redocs|repackage|clobber|trunk"`
1222
- if ARGV.empty? then
1223
- # # default:: Run the default tasks.
1224
- puts out.gsub(/(\s*)\#/, '::\1').gsub(/^rake /, '# ')
1225
- else
1226
- # * default - Run the default tasks.
1227
- puts out.gsub(/\#/, '-').gsub(/^rake /, '* ')
1228
- end
531
+ Hoe.load_plugins
1229
532
  end