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 +0 -0
- data/History.txt +19 -0
- data/Manifest.txt +12 -0
- data/README.txt +25 -38
- data/Rakefile +12 -19
- data/bin/sow +1 -3
- data/lib/hoe.rb +243 -940
- data/lib/hoe/clean.rb +36 -0
- data/lib/hoe/debug.rb +68 -0
- data/lib/hoe/deps.rb +169 -0
- data/lib/hoe/flay.rb +35 -0
- data/lib/hoe/flog.rb +35 -0
- data/lib/hoe/inline.rb +58 -0
- data/lib/hoe/package.rb +83 -0
- data/lib/hoe/publish.rb +182 -0
- data/lib/hoe/rake.rb +44 -0
- data/lib/hoe/rcov.rb +44 -0
- data/lib/hoe/signing.rb +119 -0
- data/lib/hoe/test.rb +140 -0
- data/template/Rakefile.erb +3 -4
- data/test/test_hoe.rb +7 -9
- metadata +33 -38
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/History.txt
CHANGED
@@ -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:
|
data/Manifest.txt
CHANGED
@@ -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
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
*
|
17
|
-
*
|
18
|
-
*
|
19
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
26
|
-
*
|
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
|
-
*
|
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.
|
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.
|
8
|
-
|
13
|
+
Hoe.spec "hoe" do
|
14
|
+
developer "Ryan Davis", "ryand-ruby@zenspider.com"
|
9
15
|
|
10
|
-
|
16
|
+
self.rubyforge_name = "seattlerb"
|
17
|
+
self.testlib = :minitest
|
11
18
|
|
12
|
-
|
13
|
-
hoe.blog_categories << "Seattle.rb" << "Ruby"
|
14
|
-
end
|
19
|
+
blog_categories << "Seattle.rb" << "Ruby"
|
15
20
|
|
16
|
-
|
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
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
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
|
-
#
|
33
|
-
#
|
34
|
-
#
|
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
|
-
#
|
36
|
+
# % sow project_name
|
37
|
+
# ...
|
38
|
+
# % cd project_name
|
44
39
|
#
|
45
|
-
#
|
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
|
-
#
|
80
|
-
# YAML formatted config file with
|
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
|
-
#
|
48
|
+
# exclude:: A regular expression of files to exclude from +check_manifest+.
|
109
49
|
#
|
110
|
-
#
|
50
|
+
# Run <tt>`rake config_hoe`</tt> and see ~/.hoerc for examples.
|
111
51
|
#
|
112
|
-
#
|
113
|
-
# data.tar.gz.sig
|
114
|
-
# metadata.gz
|
115
|
-
# metadata.gz.sig
|
52
|
+
# == Extending Hoe
|
116
53
|
#
|
117
|
-
#
|
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
|
120
|
-
#
|
121
|
-
#
|
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
|
-
|
138
|
-
|
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
|
-
#
|
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
|
-
|
91
|
+
DEFAULT_CONFIG = {
|
92
|
+
"exclude" => /tmp$|CVS|\.svn|\.log$/,
|
93
|
+
}
|
172
94
|
|
173
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
385
|
-
|
386
|
-
end
|
246
|
+
##
|
247
|
+
# Activate a plugin.
|
387
248
|
|
388
|
-
def
|
389
|
-
|
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
|
-
|
394
|
-
|
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
|
-
|
256
|
+
def self.plugins
|
257
|
+
@@plugins ||= []
|
400
258
|
end
|
401
259
|
|
402
|
-
|
403
|
-
|
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
|
-
|
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
|
-
|
439
|
-
|
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
|
-
|
448
|
-
|
449
|
-
self.
|
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.
|
455
|
-
|
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'
|
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
|
-
|
494
|
-
|
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
|
-
|
603
|
-
|
604
|
-
|
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
|
-
|
608
|
-
|
609
|
-
|
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
|
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
|
-
|
709
|
-
|
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
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
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
|
-
|
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
|
-
|
955
|
-
|
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
|
-
|
984
|
-
|
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
|
-
|
1003
|
-
|
1004
|
-
|
376
|
+
def developer name, email
|
377
|
+
self.author << name
|
378
|
+
self.email << email
|
379
|
+
end
|
1005
380
|
|
1006
|
-
|
1007
|
-
|
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
|
-
|
1010
|
-
|
386
|
+
def initialize name, version = nil # :nodoc:
|
387
|
+
self.name = name
|
388
|
+
self.version = version
|
1011
389
|
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
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
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
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
|
-
|
1029
|
-
|
1030
|
-
require 'rubyforge'
|
1031
|
-
subject, title, body, urls = announcement
|
417
|
+
##
|
418
|
+
# Intuit values from the readme and history files.
|
1032
419
|
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
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
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
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
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
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
|
-
|
1102
|
-
|
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
|
-
|
1110
|
-
|
1111
|
-
|
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
|
-
|
1125
|
-
|
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
|
-
|
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
|
-
|
1143
|
-
|
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
|
-
|
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
|
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
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
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
|
-
#
|
1174
|
-
|
1175
|
-
|
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
|
-
#
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
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
|
-
#
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
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
|
-
|
1211
|
-
|
1212
|
-
end
|
521
|
+
##
|
522
|
+
# Load or create a default config and yield it
|
1213
523
|
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
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
|
-
|
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
|