pluginfactory 1.0.3 → 1.0.4
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/ChangeLog +26 -0
- data/README +1 -1
- data/Rakefile +82 -22
- data/lib/pluginfactory.rb +77 -39
- data/rake/191_compat.rb +26 -0
- data/rake/dependencies.rb +25 -11
- data/rake/helpers.rb +65 -40
- data/rake/manual.rb +464 -64
- data/rake/publishing.rb +30 -16
- data/rake/rdoc.rb +36 -21
- data/rake/svn.rb +166 -25
- data/rake/testing.rb +46 -35
- data/rake/win32.rb +94 -0
- data/spec/lib/helpers.rb +247 -0
- data/spec/pluginfactory_spec.rb +43 -69
- metadata +138 -9
data/rake/publishing.rb
CHANGED
@@ -100,15 +100,17 @@ begin
|
|
100
100
|
|
101
101
|
|
102
102
|
namespace :release do
|
103
|
-
task :default => [ 'svn:release', :
|
103
|
+
task :default => [ 'svn:release', :upload, :publish, :announce ]
|
104
104
|
|
105
105
|
desc "Re-publish the release with the current version number"
|
106
|
-
task :rerelease => [ :publish, :announce
|
106
|
+
task :rerelease => [ :upload, :publish, :announce ]
|
107
107
|
|
108
|
+
desc "Re-run the publication tasks, but send notifications to debugging address"
|
108
109
|
task :test do
|
110
|
+
trace "Will publish privately"
|
109
111
|
$publish_privately = true
|
112
|
+
Rake::Task['release:rerelease'].invoke
|
110
113
|
end
|
111
|
-
task :test => [ :rerelease ]
|
112
114
|
|
113
115
|
|
114
116
|
desc "Generate the release notes"
|
@@ -127,24 +129,34 @@ begin
|
|
127
129
|
|
128
130
|
edit task.name
|
129
131
|
end
|
130
|
-
|
132
|
+
CLOBBER.include( RELEASE_NOTES_FILE )
|
131
133
|
|
132
134
|
|
133
|
-
|
134
|
-
|
135
|
+
desc "Upload project documentation and packages to #{PROJECT_HOST}"
|
136
|
+
task :upload => [ :upload_docs, :upload_packages ]
|
137
|
+
task :project => :upload # the old name
|
138
|
+
|
139
|
+
desc "Publish the project docs to #{PROJECT_HOST}"
|
140
|
+
task :upload_docs => [ :rdoc ] do
|
141
|
+
when_writing( "Publishing docs to #{PROJECT_SCPDOCURL}" ) do
|
142
|
+
log "Uploading API documentation to %s:%s" % [ PROJECT_HOST, PROJECT_DOCDIR ]
|
135
143
|
run 'ssh', PROJECT_HOST, "rm -rf #{PROJECT_DOCDIR}"
|
136
|
-
run 'scp', '-qCr',
|
144
|
+
run 'scp', '-qCr', RDOCDIR, PROJECT_SCPDOCURL
|
137
145
|
end
|
146
|
+
end
|
147
|
+
|
148
|
+
desc "Publish the project packages to #{PROJECT_HOST}"
|
149
|
+
task :upload_packages => [ :package ] do
|
138
150
|
when_writing( "Uploading packages") do
|
139
151
|
pkgs = Pathname.glob( PKGDIR + "#{PKG_FILE_NAME}.{gem,tar.gz,tar.bz2,zip}" )
|
140
|
-
log "Uploading %d packages to #{
|
152
|
+
log "Uploading %d packages to #{PROJECT_SCPPUBURL}" % [ pkgs.length ]
|
141
153
|
pkgs.each do |pkgfile|
|
142
|
-
run 'scp', '-qC', pkgfile,
|
154
|
+
run 'scp', '-qC', pkgfile, PROJECT_SCPPUBURL
|
143
155
|
end
|
144
156
|
end
|
145
157
|
end
|
146
158
|
|
147
|
-
|
159
|
+
|
148
160
|
file RELEASE_ANNOUNCE_FILE => [RELEASE_NOTES_FILE] do |task|
|
149
161
|
relnotes = File.read( RELEASE_NOTES_FILE )
|
150
162
|
announce_body = %{
|
@@ -180,7 +192,7 @@ begin
|
|
180
192
|
|
181
193
|
edit task.name
|
182
194
|
end
|
183
|
-
|
195
|
+
CLOBBER.include( RELEASE_ANNOUNCE_FILE )
|
184
196
|
|
185
197
|
|
186
198
|
desc 'Send out a release announcement'
|
@@ -188,12 +200,11 @@ begin
|
|
188
200
|
email = TMail::Mail.new
|
189
201
|
if $publish_privately
|
190
202
|
trace "Sending private announce mail"
|
191
|
-
email.to
|
203
|
+
email.to = 'rubymage@gmail.com'
|
192
204
|
else
|
193
205
|
trace "Sending public announce mail"
|
194
|
-
email.to
|
195
|
-
|
196
|
-
# email.bcc = 'rubymage@gmail.com'
|
206
|
+
email.to = 'Ruby-Talk List <ruby-talk@ruby-lang.org>'
|
207
|
+
email.bcc = 'rubymage@gmail.com'
|
197
208
|
end
|
198
209
|
email.from = GEMSPEC.email
|
199
210
|
email.subject = "[ANN] #{PKG_NAME} #{PKG_VERSION}"
|
@@ -229,7 +240,7 @@ begin
|
|
229
240
|
|
230
241
|
|
231
242
|
desc 'Publish the new release to RubyForge'
|
232
|
-
task :publish => [:
|
243
|
+
task :publish => [:clean, :package, :notes] do |task|
|
233
244
|
project = GEMSPEC.rubyforge_project
|
234
245
|
|
235
246
|
rf = RubyForge.new
|
@@ -299,5 +310,8 @@ rescue LoadError => err
|
|
299
310
|
task "release:notes" => :no_release_tasks
|
300
311
|
end
|
301
312
|
|
313
|
+
desc "Package up a release, publish it, and send out notifications"
|
302
314
|
task :release => 'release:default'
|
315
|
+
task :rerelease => 'release:rerelease'
|
316
|
+
task :testrelease => 'release:test'
|
303
317
|
|
data/rake/rdoc.rb
CHANGED
@@ -1,30 +1,45 @@
|
|
1
1
|
#
|
2
|
-
# RDoc Rake tasks
|
3
|
-
# $Id: rdoc.rb
|
2
|
+
# RDoc Rake tasks
|
3
|
+
# $Id: rdoc.rb 86 2009-02-23 06:38:40Z deveiant $
|
4
4
|
#
|
5
5
|
|
6
|
-
require '
|
7
|
-
|
6
|
+
require 'rdoc/rdoc'
|
7
|
+
require 'rake/clean'
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
|
10
|
+
if RDoc::RDoc::GENERATORS.key?( 'darkfish' )
|
11
11
|
$have_darkfish = true
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
gem 'darkfish-rdoc'
|
16
|
-
retry
|
17
|
-
end
|
18
|
-
|
19
|
-
log "No DarkFish: %s: %s" % [ err.class.name, err.message ]
|
20
|
-
trace "Backtrace:\n %s" % [ err.backtrace.join("\n ") ]
|
12
|
+
else
|
13
|
+
trace "No darkfish generator."
|
14
|
+
$have_darkfish = false
|
21
15
|
end
|
22
16
|
|
23
|
-
Rake::RDocTask.new do |rdoc|
|
24
|
-
rdoc.rdoc_dir = 'docs/html'
|
25
|
-
rdoc.title = "#{PKG_NAME} - #{PKG_SUMMARY}"
|
26
|
-
rdoc.options += RDOC_OPTIONS + [ '-f', 'darkfish' ] if $have_darkfish
|
27
17
|
|
28
|
-
|
29
|
-
|
18
|
+
# Append docs/lib to the load path if it exists for a locally-installed Darkfish
|
19
|
+
DOCSLIB = DOCSDIR + 'lib'
|
20
|
+
$LOAD_PATH.unshift( DOCSLIB.to_s ) if DOCSLIB.exist?
|
21
|
+
|
22
|
+
# Make relative string paths of all the stuff we need to generate docs for
|
23
|
+
DOCFILES = LIB_FILES + EXT_FILES + GEMSPEC.extra_rdoc_files
|
24
|
+
|
25
|
+
|
26
|
+
directory RDOCDIR.to_s
|
27
|
+
CLOBBER.include( RDOCDIR )
|
28
|
+
|
29
|
+
desc "Build API documentation in #{RDOCDIR}"
|
30
|
+
task :rdoc => [ Rake.application.rakefile, *DOCFILES ] do
|
31
|
+
args = RDOC_OPTIONS
|
32
|
+
args += [ '-o', RDOCDIR.to_s ]
|
33
|
+
args += [ '-f', 'darkfish' ] if $have_darkfish
|
34
|
+
args += DOCFILES.collect {|pn| pn.to_s }
|
35
|
+
|
36
|
+
trace "Building docs with arguments: %s" % [ args.join(' ') ]
|
37
|
+
RDoc::RDoc.new.document( args ) rescue nil
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "Rebuild API documentation in #{RDOCDIR}"
|
41
|
+
task :rerdoc do
|
42
|
+
rm_r( RDOCDIR ) if RDOCDIR.exist?
|
43
|
+
Rake::Task[ :rdoc ].invoke
|
30
44
|
end
|
45
|
+
|
data/rake/svn.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
#
|
2
2
|
# Subversion Rake Tasks
|
3
|
-
# $Id: svn.rb
|
3
|
+
# $Id: svn.rb 86 2009-02-23 06:38:40Z deveiant $
|
4
4
|
#
|
5
5
|
# Authors:
|
6
6
|
# * Michael Granger <ged@FaerieMUD.org>
|
7
7
|
#
|
8
8
|
|
9
|
-
|
10
9
|
require 'pp'
|
11
10
|
require 'yaml'
|
12
11
|
require 'date'
|
12
|
+
require 'time'
|
13
13
|
|
14
14
|
# Strftime format for tags/releases
|
15
15
|
TAG_TIMESTAMP_FORMAT = '%Y%m%d-%H%M%S'
|
@@ -19,8 +19,15 @@ RELEASE_VERSION_PATTERN = /\d+\.\d+\.\d+/
|
|
19
19
|
|
20
20
|
DEFAULT_EDITOR = 'vi'
|
21
21
|
DEFAULT_KEYWORDS = %w[Date Rev Author URL Id]
|
22
|
-
KEYWORDED_FILEDIRS = %w[applets bin etc lib misc]
|
23
|
-
KEYWORDED_FILEPATTERN =
|
22
|
+
KEYWORDED_FILEDIRS = %w[applets spec bin etc ext experiments examples lib misc docs]
|
23
|
+
KEYWORDED_FILEPATTERN = /
|
24
|
+
^(?:
|
25
|
+
(?:meta)?rakefile.* # Rakefiles
|
26
|
+
|
|
27
|
+
.*\.(?:rb|c|h|js|html|css|template|erb|page) # Source file extensions
|
28
|
+
|
|
29
|
+
readme|install|todo
|
30
|
+
)$/ix
|
24
31
|
|
25
32
|
COMMIT_MSG_FILE = 'commit-msg.txt'
|
26
33
|
|
@@ -50,6 +57,9 @@ def get_svn_info( dir='.' )
|
|
50
57
|
return {} unless File.directory?( File.join(dir, '.svn') )
|
51
58
|
info = IO.read( '|-' ) or exec 'svn', 'info', dir
|
52
59
|
return YAML.load( info ) # 'svn info' outputs valid YAML! Yay!
|
60
|
+
rescue NotImplementedError
|
61
|
+
trace "No fork(), proceeding without svn info..."
|
62
|
+
return {}
|
53
63
|
end
|
54
64
|
|
55
65
|
|
@@ -64,7 +74,7 @@ def get_svn_filelist( dir='.' )
|
|
64
74
|
# the additional complexity to make it handle that case. If we do need that, there's
|
65
75
|
# always the --xml output for 'svn st'...
|
66
76
|
return list.split( $/ ).
|
67
|
-
reject {|line| line =~
|
77
|
+
reject {|line| line =~ /^(\?|(\s*|--- .*)$)/ }.
|
68
78
|
collect {|fn| Pathname(fn[/\S+$/]) }
|
69
79
|
end
|
70
80
|
|
@@ -93,7 +103,10 @@ end
|
|
93
103
|
|
94
104
|
|
95
105
|
### Return the keywords for the specified array of +files+ as a Hash keyed by filename.
|
96
|
-
def get_svn_keyword_map( files )
|
106
|
+
def get_svn_keyword_map( *files )
|
107
|
+
files.flatten!
|
108
|
+
files.push( '.' ) if files.empty?
|
109
|
+
|
97
110
|
cmd = ['svn', 'pg', 'svn:keywords', *files]
|
98
111
|
|
99
112
|
# trace "Executing: svn pg svn:keywords " + files.join(' ')
|
@@ -160,6 +173,23 @@ def get_svn_diff( *targets )
|
|
160
173
|
end
|
161
174
|
|
162
175
|
|
176
|
+
### Get a subversion status as an Array of tuples of the form:
|
177
|
+
### [ <status>, <path> ]
|
178
|
+
def get_svn_status( *targets )
|
179
|
+
targets << BASEDIR if targets.empty?
|
180
|
+
trace "Getting svn status for targets: %p" % [targets]
|
181
|
+
status = IO.read( '|-' ) or exec 'svn', 'st', '--ignore-externals', *(targets.flatten)
|
182
|
+
entries = status.split( /\n/ ).
|
183
|
+
select {|line| line !~ /^(\s*|--- .*)$/ }.
|
184
|
+
collect do |line|
|
185
|
+
flag, path = line.strip.split( /\s+/, 2 )
|
186
|
+
[ flag, Pathname.new(path) ]
|
187
|
+
end
|
188
|
+
|
189
|
+
return entries
|
190
|
+
end
|
191
|
+
|
192
|
+
|
163
193
|
### Return the URL of the latest timestamp in the tags directory.
|
164
194
|
def get_latest_release_tag
|
165
195
|
rooturl = get_svn_repo_root()
|
@@ -280,15 +310,49 @@ end
|
|
280
310
|
|
281
311
|
|
282
312
|
### Returns a human-scannable file list by joining and truncating the list if it's too long.
|
283
|
-
def humanize_file_list( list )
|
284
|
-
listtext = list[0..5].join( "\n#{
|
313
|
+
def humanize_file_list( list, indent=FILE_INDENT )
|
314
|
+
listtext = list[0..5].join( "\n#{indent}" )
|
285
315
|
if list.length > 5
|
286
316
|
listtext << " (and %d other/s)" % [ list.length - 5 ]
|
287
317
|
end
|
288
318
|
|
289
319
|
return listtext
|
290
320
|
end
|
291
|
-
|
321
|
+
|
322
|
+
|
323
|
+
### Add the list of +pathnames+ to the svn:ignore list.
|
324
|
+
def svn_ignore_files( *pathnames )
|
325
|
+
pathnames.flatten!
|
326
|
+
|
327
|
+
map = pathnames.inject({}) do |map,path|
|
328
|
+
map[ path.dirname ] ||= []
|
329
|
+
map[ path.dirname ] << path.basename
|
330
|
+
map
|
331
|
+
end
|
332
|
+
|
333
|
+
trace "Ignoring %d files in %d directories." % [ pathnames.length, map.length ]
|
334
|
+
|
335
|
+
map.each do |dir, files|
|
336
|
+
trace " %s: %p" % [ dir, files ]
|
337
|
+
io = open( '|-' ) or exec 'svn', 'pg', 'svn:ignore', dir
|
338
|
+
ignorelist = io.read.strip
|
339
|
+
ignorelist << "\n" << files.join("\n")
|
340
|
+
system 'svn', 'ps', 'svn:ignore', ignorelist, dir
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
|
345
|
+
### Delete the files in the given +filelist+ after confirming with the user.
|
346
|
+
def delete_extra_files( filelist )
|
347
|
+
description = humanize_file_list( filelist, ' ' )
|
348
|
+
log "Files to delete:\n ", description
|
349
|
+
ask_for_confirmation( "Really delete them?", false ) do
|
350
|
+
filelist.each do |f|
|
351
|
+
rm_rf( f, :verbose => true )
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
292
356
|
|
293
357
|
|
294
358
|
###
|
@@ -315,27 +379,60 @@ namespace :svn do
|
|
315
379
|
end
|
316
380
|
|
317
381
|
|
382
|
+
desc "Copy the HEAD revision of the current #{SVN_TRUNK_DIR}/ to #{SVN_BRANCHES_DIR} with a " +
|
383
|
+
"user-specified name."
|
384
|
+
task :branch, [:name] do |task, args|
|
385
|
+
unless args.name
|
386
|
+
args.name = prompt( "Branch name" ) or abort
|
387
|
+
end
|
388
|
+
|
389
|
+
svninfo = get_svn_info()
|
390
|
+
svntrunk = Pathname.new( svninfo['Repository Root'] ) + SVN_TRUNK_DIR
|
391
|
+
svnbranchdir = Pathname.new( svninfo['Repository Root'] ) + SVN_BRANCHES_DIR
|
392
|
+
svnbranch = svnbranchdir + args.name
|
393
|
+
|
394
|
+
desc = "Making a new branch: #{svnbranch}"
|
395
|
+
ask_for_confirmation( desc ) do
|
396
|
+
msg = prompt_with_default( "Commit log: ", "Making a '#{args.name}' branch" )
|
397
|
+
run 'svn', 'cp', '-m', msg, svntrunk, svnbranch
|
398
|
+
ask_for_confirmation( "Switch to the new branch?", false ) do
|
399
|
+
run 'svn', 'sw', svnbranch
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
|
405
|
+
desc "Switch to the trunk if the working copy isn't there already."
|
406
|
+
task :trunk do
|
407
|
+
svninfo = get_svn_info()
|
408
|
+
svntrunk = Pathname.new( svninfo['Repository Root'] ) + SVN_TRUNK_DIR
|
409
|
+
|
410
|
+
if svninfo['URL'] != svntrunk.to_s
|
411
|
+
log "Switching to #{svntrunk}"
|
412
|
+
run 'svn', 'sw', svntrunk
|
413
|
+
else
|
414
|
+
log "You are already on trunk (#{svntrunk})"
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
|
318
419
|
desc "Copy the most recent tag to #{SVN_RELEASES_DIR}/#{PKG_VERSION}"
|
319
420
|
task :release do
|
320
421
|
last_tag = get_latest_svn_timestamp_tag()
|
321
422
|
svninfo = get_svn_info()
|
322
|
-
svnroot = svninfo['Repository Root']
|
323
|
-
svntrunk = svnroot +
|
324
|
-
svnrel = svnroot +
|
423
|
+
svnroot = Pathname.new( svninfo['Repository Root'] )
|
424
|
+
svntrunk = svnroot + SVN_TRUNK_DIR
|
425
|
+
svnrel = svnroot + SVN_RELEASES_DIR
|
325
426
|
release = PKG_VERSION
|
326
|
-
svnrelease = svnrel +
|
427
|
+
svnrelease = svnrel + release
|
327
428
|
|
328
|
-
|
329
|
-
unless topdirs.include?( SVN_RELEASES_DIR )
|
330
|
-
trace "Top directories (%p) does not include %p" %
|
331
|
-
[ topdirs, SVN_RELEASES_DIR ]
|
429
|
+
unless svn_ls( svnrel.dirname ).include?( svnrel.basename.to_s + '/' )
|
332
430
|
log "Releases path #{svnrel} does not exist."
|
333
431
|
ask_for_confirmation( "To continue I'll need to create it." ) do
|
334
432
|
run 'svn', 'mkdir', svnrel, '-m', 'Creating releases/ directory'
|
335
433
|
end
|
336
434
|
else
|
337
|
-
trace "Found release dir #{
|
338
|
-
[ topdirs ]
|
435
|
+
trace "Found release dir #{svnrel}"
|
339
436
|
end
|
340
437
|
|
341
438
|
releases = svn_ls( svnrel ).collect {|name| name.sub(%r{/$}, '') }
|
@@ -391,10 +488,48 @@ namespace :svn do
|
|
391
488
|
end
|
392
489
|
|
393
490
|
|
491
|
+
desc "Add/ignore any files that are unknown in the working copy"
|
492
|
+
task :newfiles do
|
493
|
+
log "Checking for new files..."
|
494
|
+
entries = get_svn_status()
|
495
|
+
|
496
|
+
unless entries.empty?
|
497
|
+
files_to_add = []
|
498
|
+
files_to_ignore = []
|
499
|
+
files_to_delete = []
|
500
|
+
|
501
|
+
entries.find_all {|entry| entry[0] == '?'}.each do |entry|
|
502
|
+
action = prompt_with_default( " #{entry[1]}: (a)dd, (i)gnore, (s)kip (d)elete", 's' )
|
503
|
+
case action
|
504
|
+
when 'a'
|
505
|
+
files_to_add << entry[1]
|
506
|
+
when 'i'
|
507
|
+
files_to_ignore << entry[1]
|
508
|
+
when 'd'
|
509
|
+
files_to_delete << entry[1]
|
510
|
+
end
|
511
|
+
end
|
512
|
+
|
513
|
+
unless files_to_add.empty?
|
514
|
+
run 'svn', 'add', *files_to_add
|
515
|
+
end
|
516
|
+
|
517
|
+
unless files_to_ignore.empty?
|
518
|
+
svn_ignore_files( *files_to_ignore )
|
519
|
+
end
|
520
|
+
|
521
|
+
unless files_to_delete.empty?
|
522
|
+
delete_extra_files( files_to_delete )
|
523
|
+
end
|
524
|
+
end
|
525
|
+
end
|
526
|
+
task :add => :newfiles
|
527
|
+
|
528
|
+
|
394
529
|
desc "Check in all the changes in your current working copy"
|
395
|
-
task :checkin => ['svn:update', 'test', 'svn:fix_keywords', COMMIT_MSG_FILE] do
|
530
|
+
task :checkin => ['svn:update', 'svn:newfiles', 'test', 'svn:fix_keywords', COMMIT_MSG_FILE] do
|
396
531
|
targets = get_target_args()
|
397
|
-
$
|
532
|
+
$stderr.puts '---', File.read( COMMIT_MSG_FILE ), '---'
|
398
533
|
ask_for_confirmation( "Continue with checkin?" ) do
|
399
534
|
run 'svn', 'ci', '-F', COMMIT_MSG_FILE, targets
|
400
535
|
rm_f COMMIT_MSG_FILE
|
@@ -427,7 +562,7 @@ namespace :svn do
|
|
427
562
|
end
|
428
563
|
|
429
564
|
unless files_needing_fixups.empty?
|
430
|
-
$
|
565
|
+
$stderr.puts "Files needing keyword fixes: ",
|
431
566
|
files_needing_fixups.collect {|f|
|
432
567
|
" %s: %s" % [f, kwmap[f] ? kwmap[f].join(' ') : "(no keywords)"]
|
433
568
|
}
|
@@ -442,13 +577,19 @@ namespace :svn do
|
|
442
577
|
|
443
578
|
task :debug_helpers do
|
444
579
|
methods = [
|
445
|
-
:
|
580
|
+
:get_last_changed_rev,
|
581
|
+
:get_latest_release_tag,
|
582
|
+
:get_latest_svn_timestamp_tag,
|
583
|
+
:get_svn_diff,
|
584
|
+
:get_svn_filelist,
|
446
585
|
:get_svn_info,
|
586
|
+
:get_svn_keyword_map,
|
587
|
+
:get_svn_path,
|
447
588
|
:get_svn_repo_root,
|
589
|
+
:get_svn_rev,
|
590
|
+
:get_svn_status,
|
448
591
|
:get_svn_url,
|
449
|
-
:get_svn_path,
|
450
592
|
:svn_ls,
|
451
|
-
:get_latest_svn_timestamp_tag,
|
452
593
|
]
|
453
594
|
maxlen = methods.collect {|sym| sym.to_s.length }.max
|
454
595
|
|