pluginfactory 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|