pg 0.9.0.pre156-x86-mswin32

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.
@@ -0,0 +1,668 @@
1
+ #
2
+ # Subversion Rake Tasks
3
+
4
+ #
5
+ # Authors:
6
+ # * Michael Granger <ged@FaerieMUD.org>
7
+ #
8
+
9
+ require 'pp'
10
+ require 'yaml'
11
+ require 'date'
12
+ require 'time'
13
+ require 'abbrev'
14
+
15
+ unless defined?( SVN_DOTDIR )
16
+
17
+ # Subversion constants -- directory names for releases and tags
18
+ SVN_TRUNK_DIR = 'trunk'
19
+ SVN_RELEASES_DIR = 'releases'
20
+ SVN_BRANCHES_DIR = 'branches'
21
+ SVN_TAGS_DIR = 'tags'
22
+
23
+ SVN_DOTDIR = BASEDIR + '.svn'
24
+ SVN_ENTRIES = SVN_DOTDIR + 'entries'
25
+
26
+ # Ignore .svn directories in the various FileLists used by the main Rakefile
27
+ [
28
+ BIN_FILES,
29
+ LIB_FILES,
30
+ EXT_FILES,
31
+ DATA_FILES,
32
+ SPEC_FILES,
33
+ TEST_FILES,
34
+ EXTRA_PKGFILES,
35
+ ].each {|filelist| filelist.exclude(/\.svn/) }
36
+
37
+ # Strftime format for tags/releases
38
+ TAG_TIMESTAMP_FORMAT = '%Y%m%d-%H%M%S'
39
+ TAG_TIMESTAMP_PATTERN = /\d{4}\d{2}\d{2}-\d{6}/
40
+
41
+ RELEASE_VERSION_PATTERN = /\d+\.\d+\.\d+/
42
+
43
+ DEFAULT_KEYWORDS = %w[Date Rev Author URL Id]
44
+ KEYWORDED_FILEDIRS = %w[applets spec bin etc ext experiments examples lib misc docs]
45
+ KEYWORDED_FILEPATTERN = /
46
+ ^(?:
47
+ (?:meta)?rakefile.* # Rakefiles
48
+ |
49
+ .*\.(?:rb|c|h|js|html|css|template|erb|page) # Source file extensions
50
+ |
51
+ readme|install|todo
52
+ )$/ix
53
+
54
+
55
+
56
+ ###
57
+ ### Subversion-specific Helpers
58
+ ###
59
+ module SubversionHelpers
60
+
61
+ ###############
62
+ module_function
63
+ ###############
64
+
65
+ ### Return a new tag for the given time
66
+ def make_new_tag( time=Time.now )
67
+ return time.strftime( TAG_TIMESTAMP_FORMAT )
68
+ end
69
+
70
+
71
+ ### Get the subversion information for the current working directory as
72
+ ### a hash.
73
+ def get_svn_info( dir='.' )
74
+ return {} unless File.directory?( File.join(dir, '.svn') )
75
+ info = IO.read( '|-' ) or exec 'svn', 'info', dir.to_s
76
+ return YAML.load( info ) # 'svn info' outputs valid YAML! Yay!
77
+ rescue NotImplementedError
78
+ trace "No fork(), proceeding without svn info..."
79
+ return {}
80
+ end
81
+
82
+
83
+ ### Get a list of the objects registered with subversion under the specified directory and
84
+ ### return them as an Array of Pathame objects.
85
+ def get_svn_filelist( dir='.' )
86
+ list = IO.read( '|-' ) or exec 'svn', 'st', '-v', '--ignore-externals', dir
87
+
88
+ # Split into lines, filter out the unknowns, and grab the filenames as Pathnames
89
+ # :FIXME: This will break if we ever put in a file with spaces in its name. This
90
+ # will likely be the least of our worries if we do so, however, so it's not worth
91
+ # the additional complexity to make it handle that case. If we do need that, there's
92
+ # always the --xml output for 'svn st'...
93
+ return list.split( $/ ).
94
+ reject {|line| line =~ /^(\?|(\s*|--- .*)$)/ }.
95
+ collect {|fn| Pathname(fn[/\S+$/]) }
96
+ end
97
+
98
+ ### Return the URL to the repository root for the specified +dir+.
99
+ def get_svn_repo_root( dir='.' )
100
+ info = get_svn_info( dir )
101
+ return info['Repository Root']
102
+ end
103
+
104
+
105
+ ### Return the Subversion URL to the given +dir+.
106
+ def get_svn_url( dir='.' )
107
+ info = get_svn_info( dir )
108
+ return info['URL']
109
+ end
110
+
111
+
112
+ ### Return the path of the specified +dir+ under the svn root of the
113
+ ### checkout.
114
+ def get_svn_path( dir='.' )
115
+ root = get_svn_repo_root( dir )
116
+ url = get_svn_url( dir )
117
+
118
+ return url.sub( root + '/', '' )
119
+ end
120
+
121
+
122
+ ### Return the keywords for the specified array of +files+ as a Hash keyed by filename.
123
+ def get_svn_keyword_map( *files )
124
+ files.flatten!
125
+ files.push( '.' ) if files.empty?
126
+
127
+ cmd = ['svn', 'pg', 'svn:keywords', *files]
128
+
129
+ # trace "Executing: svn pg svn:keywords " + files.join(' ')
130
+ output = IO.read( '|-' ) or exec( 'svn', 'pg', 'svn:keywords', *files )
131
+
132
+ kwmap = {}
133
+ output.split( "\n" ).each do |line|
134
+ next if line !~ /\s+-\s+/
135
+ path, keywords = line.split( /\s+-\s+/, 2 )
136
+ kwmap[ path ] = keywords.split
137
+ end
138
+
139
+ return kwmap
140
+ end
141
+
142
+
143
+ ### Return the latest revision number of the specified +dir+ as an Integer.
144
+ def get_svn_rev( dir='.' )
145
+ info = get_svn_info( dir )
146
+ return info['Revision']
147
+ end
148
+ alias get_vcs_rev get_svn_rev
149
+
150
+
151
+ ### Return the latest revision number of the specified +dir+ as an Integer.
152
+ def get_last_changed_rev( dir='.' )
153
+ info = get_svn_info( dir )
154
+ return info['Last Changed Rev']
155
+ end
156
+
157
+
158
+ ### Return a list of the entries at the specified Subversion url. If
159
+ ### no +url+ is specified, it will default to the list in the URL
160
+ ### corresponding to the current working directory.
161
+ def svn_ls( url=nil )
162
+ url ||= get_svn_url()
163
+ list = IO.read( '|-' ) or exec 'svn', 'ls', url
164
+
165
+ trace 'svn ls of %s: %p' % [url, list] if $trace
166
+
167
+ return [] if list.nil? || list.empty?
168
+ return list.split( $INPUT_RECORD_SEPARATOR )
169
+ end
170
+
171
+
172
+ ### Return the URL of the latest timestamp in the tags directory.
173
+ def get_latest_svn_timestamp_tag
174
+ rooturl = get_svn_repo_root()
175
+ tagsurl = rooturl + "/#{SVN_TAGS_DIR}"
176
+
177
+ tags = svn_ls( tagsurl ).grep( TAG_TIMESTAMP_PATTERN ).sort
178
+ return nil if tags.nil? || tags.empty?
179
+ return tagsurl + '/' + tags.last
180
+ end
181
+
182
+
183
+ ### Get a subversion diff of the specified targets and return it. If no targets are
184
+ ### specified, the current directory will be diffed instead.
185
+ def get_svn_diff( *targets )
186
+ targets << BASEDIR if targets.empty?
187
+ trace "Getting svn diff for targets: %p" % [targets]
188
+ log = IO.read( '|-' ) or exec 'svn', 'diff', *(targets.flatten)
189
+
190
+ return log
191
+ end
192
+
193
+
194
+ ### Generate a commit log and invoke the user's editor on it.
195
+ def edit_commit_log
196
+ diff = make_commit_log()
197
+
198
+ File.open( COMMIT_MSG_FILE, File::WRONLY|File::TRUNC|File::CREAT ) do |fh|
199
+ fh.print( diff )
200
+ end
201
+
202
+ edit( COMMIT_MSG_FILE )
203
+ end
204
+
205
+
206
+ ### Get a subversion status as an Array of tuples of the form:
207
+ ### [ <status>, <path> ]
208
+ def get_svn_status( *targets )
209
+ targets << BASEDIR if targets.empty?
210
+ trace "Getting svn status for targets: %p" % [targets]
211
+ status = IO.read( '|-' ) or exec 'svn', 'st', '--ignore-externals', *(targets.flatten)
212
+ entries = status.split( /\n/ ).
213
+ select {|line| line !~ /^(\s*|--- .*)$/ }.
214
+ collect do |line|
215
+ flag, path = line.strip.split( /\s+/, 2 )
216
+ [ flag, Pathname.new(path) ]
217
+ end
218
+
219
+ return entries
220
+ end
221
+
222
+
223
+ ### Return the URL of the latest timestamp in the tags directory.
224
+ def get_latest_release_tag
225
+ rooturl = get_svn_repo_root()
226
+ releaseurl = rooturl + "/#{SVN_RELEASES_DIR}"
227
+
228
+ tags = svn_ls( releaseurl ).grep( RELEASE_VERSION_PATTERN ).sort_by do |tag|
229
+ tag[RELEASE_VERSION_PATTERN].split('.').collect {|i| Integer(i) }
230
+ end
231
+ return nil if tags.empty?
232
+
233
+ return releaseurl + '/' + tags.last
234
+ end
235
+
236
+
237
+ ### Return the names of all existing branches.
238
+ def get_branch_names
239
+ rooturl = get_svn_repo_root()
240
+ branchesurl = rooturl + "/#{SVN_BRANCHES_DIR}"
241
+
242
+ return svn_ls( branchesurl )
243
+ end
244
+
245
+
246
+ ### Extract a diff from the specified subversion working +dir+ and return it.
247
+ def make_svn_commit_log( dir='.' )
248
+ diff = IO.read( '|-' ) or exec 'svn', 'diff'
249
+ fail "No differences." if diff.empty?
250
+
251
+ return diff
252
+ end
253
+
254
+
255
+ ### Extract the svn log from the specified subversion working +dir+,
256
+ ### starting from rev +start+ and ending with rev +finish+, and return it.
257
+ def make_svn_log( dir='.', start='PREV', finish='HEAD' )
258
+ trace "svn log -r#{start}:#{finish} #{dir}"
259
+ log = IO.read( '|-' ) or exec 'svn', 'log', "-r#{start}:#{finish}", dir
260
+ fail "No log between #{start} and #{finish}." if log.empty?
261
+
262
+ return log
263
+ end
264
+
265
+
266
+ ### Extract the verbose XML svn log from the specified subversion working +dir+,
267
+ ### starting from rev +start+ and ending with rev +finish+, and return it.
268
+ def make_xml_svn_log( dir='.', start='PREV', finish='HEAD' )
269
+ trace "svn log --xml --verbose -r#{start}:#{finish} #{dir}"
270
+ log = IO.read( '|-' ) or exec 'svn', 'log', '--verbose', '--xml', "-r#{start}:#{finish}", dir
271
+ fail "No log between #{start} and #{finish}." if log.empty?
272
+
273
+ return log
274
+ end
275
+
276
+
277
+ ### Create a changelog from the subversion log of the specified +dir+ and return it.
278
+ def make_svn_changelog( dir='.' )
279
+ require 'xml/libxml'
280
+
281
+ changelog = ''
282
+ path_prefix = '/' + get_svn_path( dir ) + '/'
283
+
284
+ xmllog = make_xml_svn_log( dir, 0 )
285
+
286
+ parser = XML::Parser.string( xmllog )
287
+ root = parser.parse.root
288
+ root.find( '//log/logentry' ).to_a.reverse.each do |entry|
289
+ trace "Making a changelog entry for r%s" % [ entry['revision'] ]
290
+
291
+ added = []
292
+ deleted = []
293
+ changed = []
294
+
295
+ entry.find( 'paths/path').each do |path|
296
+ pathname = path.content
297
+ pathname.sub!( path_prefix , '' ) if pathname.count('/') > 1
298
+
299
+ case path['action']
300
+ when 'A', 'R'
301
+ if path['copyfrom-path']
302
+ verb = path['action'] == 'A' ? 'renamed' : 'copied'
303
+ added << "%s\n#{FILE_INDENT}-> #{verb} from %s@r%s" % [
304
+ pathname,
305
+ path['copyfrom-path'],
306
+ path['copyfrom-rev'],
307
+ ]
308
+ else
309
+ added << "%s (new)" % [ pathname ]
310
+ end
311
+
312
+ when 'M'
313
+ changed << pathname
314
+
315
+ when 'D'
316
+ deleted << pathname
317
+
318
+ else
319
+ log "Unknown action %p in rev %d" % [ path['action'], entry['revision'] ]
320
+ end
321
+
322
+ end
323
+
324
+ date = Time.parse( entry.find_first('date').content )
325
+
326
+ # cvs2svn doesn't set 'author'
327
+ author = 'unknown'
328
+ if entry.find_first( 'author' )
329
+ author = entry.find_first( 'author' ).content
330
+ end
331
+
332
+ msg = entry.find_first( 'msg' ).content
333
+ rev = entry['revision']
334
+
335
+ changelog << "-- #{date.rfc2822} by #{author} (r#{rev}) -----\n"
336
+ changelog << " Added: " << humanize_file_list(added) << "\n" unless added.empty?
337
+ changelog << " Changed: " << humanize_file_list(changed) << "\n" unless changed.empty?
338
+ changelog << " Deleted: " << humanize_file_list(deleted) << "\n" unless deleted.empty?
339
+ changelog << "\n"
340
+
341
+ indent = msg[/^(\s*)/] + LOG_INDENT
342
+
343
+ changelog << indent << msg.strip.gsub(/\n\s*/m, "\n#{indent}")
344
+ changelog << "\n\n\n"
345
+ end
346
+
347
+ return changelog
348
+ end
349
+
350
+
351
+ ### Returns a human-scannable file list by joining and truncating the list if it's too long.
352
+ def humanize_file_list( list, indent=FILE_INDENT )
353
+ listtext = list[0..5].join( "\n#{indent}" )
354
+ if list.length > 5
355
+ listtext << " (and %d other/s)" % [ list.length - 5 ]
356
+ end
357
+
358
+ return listtext
359
+ end
360
+
361
+
362
+ ### Add the list of +pathnames+ to the svn:ignore list.
363
+ def svn_ignore_files( *pathnames )
364
+ pathnames.flatten!
365
+
366
+ map = pathnames.inject({}) do |map,path|
367
+ map[ path.dirname ] ||= []
368
+ map[ path.dirname ] << path.basename
369
+ map
370
+ end
371
+
372
+ trace "Ignoring %d files in %d directories." % [ pathnames.length, map.length ]
373
+
374
+ map.each do |dir, files|
375
+ trace " %s: %p" % [ dir, files ]
376
+ io = open( '|-' ) or exec 'svn', 'pg', 'svn:ignore', dir
377
+ ignorelist = io.read.strip
378
+ ignorelist << "\n" << files.join("\n")
379
+ system 'svn', 'ps', 'svn:ignore', ignorelist, dir
380
+ end
381
+ end
382
+
383
+
384
+ ### Delete the files in the given +filelist+ after confirming with the user.
385
+ def delete_extra_files( filelist )
386
+ description = humanize_file_list( filelist, ' ' )
387
+ log "Files to delete:\n ", description
388
+ ask_for_confirmation( "Really delete them?", false ) do
389
+ filelist.each do |f|
390
+ rm_rf( f, :verbose => true )
391
+ end
392
+ end
393
+ end
394
+
395
+ end # module SubversionHelpers
396
+
397
+
398
+ ###
399
+ ### Tasks
400
+ ###
401
+
402
+ desc "Subversion tasks"
403
+ namespace :svn do
404
+ include SubversionHelpers
405
+
406
+ desc "Copy the HEAD revision of the current #{SVN_TRUNK_DIR}/ to #{SVN_TAGS_DIR}/ with a " +
407
+ "current timestamp."
408
+ task :tag do
409
+ svninfo = get_svn_info()
410
+ tag = make_new_tag()
411
+ svntrunk = svninfo['Repository Root'] + "/#{SVN_TRUNK_DIR}"
412
+ svntagdir = svninfo['Repository Root'] + "/#{SVN_TAGS_DIR}"
413
+ svntag = svntagdir + '/' + tag
414
+
415
+ desc = "Tagging trunk as #{svntag}"
416
+ ask_for_confirmation( desc ) do
417
+ msg = prompt_with_default( "Commit log: ", "Tagging for code push" )
418
+ run 'svn', 'cp', '-m', msg, svntrunk, svntag
419
+ end
420
+ end
421
+
422
+
423
+ desc "Copy the HEAD revision of the current #{SVN_TRUNK_DIR}/ to #{SVN_BRANCHES_DIR} with a " +
424
+ "user-specified name."
425
+ task :branch, [:name] do |task, args|
426
+ branchname = args.name
427
+ unless branchname
428
+ branchname = prompt( "Branch name" ) or abort
429
+ end
430
+
431
+ svninfo = get_svn_info()
432
+ svntrunk = Pathname.new( svninfo['Repository Root'] ) + SVN_TRUNK_DIR
433
+ svnbranchdir = Pathname.new( svninfo['Repository Root'] ) + SVN_BRANCHES_DIR
434
+ svnbranch = svnbranchdir + branchname
435
+
436
+ desc = "Making a new branch: #{svnbranch}"
437
+ ask_for_confirmation( desc ) do
438
+ msg = prompt_with_default( "Commit log: ", "Making a '#{args.name}' branch" )
439
+ run 'svn', 'cp', '-m', msg, svntrunk, svnbranch
440
+ ask_for_confirmation( "Switch to the new branch?", false ) do
441
+ run 'svn', 'sw', svnbranch
442
+ end
443
+ end
444
+ end
445
+
446
+
447
+ desc "Switch the working copy to the named branch"
448
+ task :switch, [:name] do |task, args|
449
+ branches = get_branch_names().collect {|name| name.chomp('/') }
450
+
451
+ unless args.name
452
+ log "Branches are:\n" + branches.collect {|br| " #{br}" }.join( "\n" )
453
+
454
+ begin
455
+ oldproc = Readline.completion_proc
456
+ abbrev = branches.abbrev
457
+ Readline.completion_proc = lambda{|string| abbrev[string] }
458
+
459
+ name = prompt( "Branch to switch to" ) or abort
460
+ args.with_defaults( :name => name )
461
+ ensure
462
+ Readline.completion_proc = oldproc unless oldproc.nil?
463
+ end
464
+ end
465
+
466
+ svninfo = get_svn_info()
467
+ abort "Branch '#{args.name}' does not exist" unless branches.include?( args.name )
468
+ branchuri = Pathname.new( svninfo['Repository Root'] ) + SVN_BRANCHES_DIR + args.name
469
+ run 'svn', 'sw', branchuri
470
+ end
471
+ task :sw => :switch
472
+
473
+
474
+ desc "Switch to the trunk if the working copy isn't there already."
475
+ task :trunk do
476
+ svninfo = get_svn_info()
477
+ svntrunk = Pathname.new( svninfo['Repository Root'] ) + SVN_TRUNK_DIR
478
+
479
+ if svninfo['URL'] != svntrunk.to_s
480
+ log "Switching to #{svntrunk}"
481
+ run 'svn', 'sw', svntrunk
482
+ else
483
+ log "You are already on trunk (#{svntrunk})"
484
+ end
485
+ end
486
+
487
+
488
+ desc "Copy the most recent tag to #{SVN_RELEASES_DIR}/#{PKG_VERSION}"
489
+ task :prep_release do
490
+ last_tag = get_latest_svn_timestamp_tag()
491
+ svninfo = get_svn_info()
492
+ svnroot = Pathname.new( svninfo['Repository Root'] )
493
+ svntrunk = svnroot + SVN_TRUNK_DIR
494
+ svnrel = svnroot + SVN_RELEASES_DIR
495
+ release = PKG_VERSION
496
+ svnrelease = svnrel + release
497
+
498
+ unless svn_ls( svnrel.dirname ).include?( svnrel.basename.to_s + '/' )
499
+ log "Releases path #{svnrel} does not exist."
500
+ ask_for_confirmation( "To continue I'll need to create it." ) do
501
+ run 'svn', 'mkdir', svnrel, '-m', 'Creating releases/ directory'
502
+ end
503
+ else
504
+ trace "Found release dir #{svnrel}"
505
+ end
506
+
507
+ releases = svn_ls( svnrel ).collect {|name| name.sub(%r{/$}, '') }
508
+ trace "Releases: %p" % [releases]
509
+ if releases.include?( release )
510
+ error "Version #{release} already has a branch (#{svnrelease}). Did you mean " +
511
+ "to increment the version in #{VERSION_FILE}?"
512
+ fail
513
+ else
514
+ trace "No #{release} version currently exists"
515
+ end
516
+
517
+ desc = "Tagging trunk as #{svnrelease}..."
518
+ ask_for_confirmation( desc ) do
519
+ msg = prompt_with_default( "Commit log: ", "Branching for release" )
520
+ run 'svn', 'cp', '-m', msg, svntrunk, svnrelease
521
+ end
522
+ end
523
+
524
+ ### Task for debugging the #get_target_args helper
525
+ task :show_targets do
526
+ $stdout.puts "Targets from ARGV (%p): %p" % [ARGV, get_target_args()]
527
+ end
528
+
529
+
530
+ desc "Update from Subversion"
531
+ task :update do
532
+ run 'svn', 'up', '--ignore-externals'
533
+ end
534
+
535
+
536
+ desc "Add/ignore any files that are unknown in the working copy"
537
+ task :newfiles do
538
+ log "Checking for new files..."
539
+ entries = get_svn_status()
540
+
541
+ unless entries.empty?
542
+ files_to_add = []
543
+ files_to_ignore = []
544
+ files_to_delete = []
545
+
546
+ entries.find_all {|entry| entry[0] == '?'}.each do |entry|
547
+ action = prompt_with_default( " #{entry[1]}: (a)dd, (i)gnore, (s)kip (d)elete", 's' )
548
+ case action
549
+ when 'a'
550
+ files_to_add << entry[1]
551
+ when 'i'
552
+ files_to_ignore << entry[1]
553
+ when 'd'
554
+ files_to_delete << entry[1]
555
+ end
556
+ end
557
+
558
+ unless files_to_add.empty?
559
+ run 'svn', 'add', *files_to_add
560
+ end
561
+
562
+ unless files_to_ignore.empty?
563
+ svn_ignore_files( *files_to_ignore )
564
+ end
565
+
566
+ unless files_to_delete.empty?
567
+ delete_extra_files( files_to_delete )
568
+ end
569
+ end
570
+ end
571
+ task :add => :newfiles
572
+
573
+
574
+ desc "Check in all the changes in your current working copy"
575
+ task :checkin => ['svn:update', 'svn:newfiles', 'test', 'svn:fix_keywords', COMMIT_MSG_FILE] do
576
+ targets = get_target_args()
577
+ $stderr.puts '---', File.read( COMMIT_MSG_FILE ), '---'
578
+ ask_for_confirmation( "Continue with checkin?" ) do
579
+ run 'svn', 'ci', '-F', COMMIT_MSG_FILE, targets
580
+ rm_f COMMIT_MSG_FILE
581
+ end
582
+ end
583
+ task :commit => :checkin
584
+ task :ci => :checkin
585
+
586
+
587
+ task :clean do
588
+ rm_f COMMIT_MSG_FILE
589
+ end
590
+
591
+
592
+ desc "Check and fix any missing keywords for any files in the project which need them"
593
+ task :fix_keywords do
594
+ log "Checking subversion keywords..."
595
+ paths = get_svn_filelist( BASEDIR ).
596
+ select {|path| path.file? && path.to_s =~ KEYWORDED_FILEPATTERN }
597
+
598
+ trace "Looking at %d paths for keywords:\n %p" % [paths.length, paths]
599
+ kwmap = get_svn_keyword_map( paths )
600
+
601
+ buf = ''
602
+ PP.pp( kwmap, buf, 132 )
603
+ trace "keyword map is: %s" % [buf]
604
+
605
+ files_needing_fixups = paths.find_all do |path|
606
+ (kwmap[path.to_s] & DEFAULT_KEYWORDS) != DEFAULT_KEYWORDS
607
+ end
608
+
609
+ unless files_needing_fixups.empty?
610
+ $stderr.puts "Files needing keyword fixes: ",
611
+ files_needing_fixups.collect {|f|
612
+ " %s: %s" % [f, kwmap[f] ? kwmap[f].join(' ') : "(no keywords)"]
613
+ }
614
+ ask_for_confirmation( "Will add default keywords to these files." ) do
615
+ run 'svn', 'ps', 'svn:keywords', DEFAULT_KEYWORDS.join(' '), *files_needing_fixups
616
+ end
617
+ else
618
+ log "Keywords are all up to date."
619
+ end
620
+ end
621
+
622
+
623
+ task :debug_helpers do
624
+ methods = [
625
+ :get_last_changed_rev,
626
+ :get_latest_release_tag,
627
+ :get_latest_svn_timestamp_tag,
628
+ :get_svn_diff,
629
+ :get_svn_filelist,
630
+ :get_svn_info,
631
+ :get_svn_keyword_map,
632
+ :get_svn_path,
633
+ :get_svn_repo_root,
634
+ :get_svn_rev,
635
+ :get_svn_status,
636
+ :get_svn_url,
637
+ :svn_ls,
638
+ ]
639
+ maxlen = methods.collect {|sym| sym.to_s.length }.max
640
+
641
+ methods.each do |meth|
642
+ res = send( meth )
643
+ puts "%*s => %p" % [ maxlen, colorize(meth.to_s, :cyan), res ]
644
+ end
645
+ end
646
+
647
+ end
648
+
649
+ if SVN_DOTDIR.exist?
650
+ trace "Defining subversion VCS tasks"
651
+
652
+ desc "Check in all the changes in your current working copy"
653
+ task :ci => 'svn:ci'
654
+ desc "Check in all the changes in your current working copy"
655
+ task :checkin => 'svn:ci'
656
+
657
+ desc "Tag a release"
658
+ task :prep_release => 'svn:prep_release'
659
+
660
+ file COMMIT_MSG_FILE do
661
+ edit_commit_log()
662
+ end
663
+ else
664
+ trace "Not defining subversion tasks: no #{SVN_DOTDIR}"
665
+ end
666
+
667
+ end # unless defined?( SVN_DOTDIR )
668
+