linkparser 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/rake/style.rb ADDED
@@ -0,0 +1,62 @@
1
+ #
2
+ # Style Fixup Rake Tasks
3
+ # $Id: style.rb 10 2008-07-18 15:52:48Z deveiant $
4
+ #
5
+ # Authors:
6
+ # * Michael Granger <ged@FaerieMUD.org>
7
+ #
8
+
9
+
10
+ ### Coding style checks and fixes
11
+ namespace :style do
12
+
13
+ BLANK_LINE = /^\s*$/
14
+ GOOD_INDENT = /^(\t\s*)?\S/
15
+
16
+ # A list of the files that have legitimate leading whitespace, etc.
17
+ PROBLEM_FILES = [ SPECDIR + 'config_spec.rb' ]
18
+
19
+ desc "Check source files for inconsistent indent and fix them"
20
+ task :fix_indent do
21
+ files = LIB_FILES + SPEC_FILES
22
+
23
+ badfiles = Hash.new {|h,k| h[k] = [] }
24
+
25
+ trace "Checking files for indentation"
26
+ files.each do |file|
27
+ if PROBLEM_FILES.include?( file )
28
+ trace " skipping problem file #{file}..."
29
+ next
30
+ end
31
+
32
+ trace " #{file}"
33
+ linecount = 0
34
+ file.each_line do |line|
35
+ linecount += 1
36
+
37
+ # Skip blank lines
38
+ next if line =~ BLANK_LINE
39
+
40
+ # If there's a line with incorrect indent, note it and skip to the
41
+ # next file
42
+ if line !~ GOOD_INDENT
43
+ trace " Bad line %d: %p" % [ linecount, line ]
44
+ badfiles[file] << [ linecount, line ]
45
+ end
46
+ end
47
+ end
48
+
49
+ if badfiles.empty?
50
+ log "No indentation problems found."
51
+ else
52
+ log "Found incorrect indent in #{badfiles.length} files:\n "
53
+ badfiles.each do |file, badlines|
54
+ log " #{file}:\n" +
55
+ " " + badlines.collect {|badline| "%5d: %p" % badline }.join( "\n " )
56
+ end
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+
data/rake/svn.rb ADDED
@@ -0,0 +1,602 @@
1
+ #
2
+ # Subversion Rake Tasks
3
+ # $Id: svn.rb 77 2008-12-18 16:35:24Z deveiant $
4
+ #
5
+ # Authors:
6
+ # * Michael Granger <ged@FaerieMUD.org>
7
+ #
8
+
9
+ require 'rubygems'
10
+ gem 'rake', '>= 0.8.3'
11
+
12
+ require 'pp'
13
+ require 'yaml'
14
+ require 'date'
15
+ require 'time'
16
+
17
+ # Strftime format for tags/releases
18
+ TAG_TIMESTAMP_FORMAT = '%Y%m%d-%H%M%S'
19
+ TAG_TIMESTAMP_PATTERN = /\d{4}\d{2}\d{2}-\d{6}/
20
+
21
+ RELEASE_VERSION_PATTERN = /\d+\.\d+\.\d+/
22
+
23
+ DEFAULT_EDITOR = 'vi'
24
+ DEFAULT_KEYWORDS = %w[Date Rev Author URL Id]
25
+ KEYWORDED_FILEDIRS = %w[applets spec bin etc ext experiments examples lib misc docs]
26
+ KEYWORDED_FILEPATTERN = /
27
+ ^(?:
28
+ (?:meta)?rakefile.* # Rakefiles
29
+ |
30
+ .*\.(?:rb|c|h|js|html|css|template|erb) # Source file extensions
31
+ |
32
+ readme|install|todo
33
+ )$/ix
34
+
35
+ COMMIT_MSG_FILE = 'commit-msg.txt'
36
+
37
+ SVN_TRUNK_DIR = 'trunk' unless defined?( SVN_TRUNK_DIR )
38
+ SVN_RELEASES_DIR = 'branches' unless defined?( SVN_RELEASES_DIR )
39
+ SVN_BRANCHES_DIR = 'branches' unless defined?( SVN_BRANCHES_DIR )
40
+ SVN_TAGS_DIR = 'tags' unless defined?( SVN_TAGS_DIR )
41
+
42
+ FILE_INDENT = " " * 12
43
+ LOG_INDENT = " " * 3
44
+
45
+
46
+
47
+ ###
48
+ ### Subversion-specific Helpers
49
+ ###
50
+
51
+ ### Return a new tag for the given time
52
+ def make_new_tag( time=Time.now )
53
+ return time.strftime( TAG_TIMESTAMP_FORMAT )
54
+ end
55
+
56
+
57
+ ### Get the subversion information for the current working directory as
58
+ ### a hash.
59
+ def get_svn_info( dir='.' )
60
+ return {} unless File.directory?( File.join(dir, '.svn') )
61
+ info = IO.read( '|-' ) or exec 'svn', 'info', dir
62
+ return YAML.load( info ) # 'svn info' outputs valid YAML! Yay!
63
+ end
64
+
65
+
66
+ ### Get a list of the objects registered with subversion under the specified directory and
67
+ ### return them as an Array of Pathame objects.
68
+ def get_svn_filelist( dir='.' )
69
+ list = IO.read( '|-' ) or exec 'svn', 'st', '-v', '--ignore-externals', dir
70
+
71
+ # Split into lines, filter out the unknowns, and grab the filenames as Pathnames
72
+ # :FIXME: This will break if we ever put in a file with spaces in its name. This
73
+ # will likely be the least of our worries if we do so, however, so it's not worth
74
+ # the additional complexity to make it handle that case. If we do need that, there's
75
+ # always the --xml output for 'svn st'...
76
+ return list.split( $/ ).
77
+ reject {|line| line =~ /^(\?|(\s*|--- .*)$)/ }.
78
+ collect {|fn| Pathname(fn[/\S+$/]) }
79
+ end
80
+
81
+ ### Return the URL to the repository root for the specified +dir+.
82
+ def get_svn_repo_root( dir='.' )
83
+ info = get_svn_info( dir )
84
+ return info['Repository Root']
85
+ end
86
+
87
+
88
+ ### Return the Subversion URL to the given +dir+.
89
+ def get_svn_url( dir='.' )
90
+ info = get_svn_info( dir )
91
+ return info['URL']
92
+ end
93
+
94
+
95
+ ### Return the path of the specified +dir+ under the svn root of the
96
+ ### checkout.
97
+ def get_svn_path( dir='.' )
98
+ root = get_svn_repo_root( dir )
99
+ url = get_svn_url( dir )
100
+
101
+ return url.sub( root + '/', '' )
102
+ end
103
+
104
+
105
+ ### Return the keywords for the specified array of +files+ as a Hash keyed by filename.
106
+ def get_svn_keyword_map( *files )
107
+ files.flatten!
108
+ files.push( '.' ) if files.empty?
109
+
110
+ cmd = ['svn', 'pg', 'svn:keywords', *files]
111
+
112
+ # trace "Executing: svn pg svn:keywords " + files.join(' ')
113
+ output = IO.read( '|-' ) or exec( 'svn', 'pg', 'svn:keywords', *files )
114
+
115
+ kwmap = {}
116
+ output.split( "\n" ).each do |line|
117
+ next if line !~ /\s+-\s+/
118
+ path, keywords = line.split( /\s+-\s+/, 2 )
119
+ kwmap[ path ] = keywords.split
120
+ end
121
+
122
+ return kwmap
123
+ end
124
+
125
+
126
+ ### Return the latest revision number of the specified +dir+ as an Integer.
127
+ def get_svn_rev( dir='.' )
128
+ info = get_svn_info( dir )
129
+ return info['Revision']
130
+ end
131
+
132
+
133
+ ### Return the latest revision number of the specified +dir+ as an Integer.
134
+ def get_last_changed_rev( dir='.' )
135
+ info = get_svn_info( dir )
136
+ return info['Last Changed Rev']
137
+ end
138
+
139
+
140
+ ### Return a list of the entries at the specified Subversion url. If
141
+ ### no +url+ is specified, it will default to the list in the URL
142
+ ### corresponding to the current working directory.
143
+ def svn_ls( url=nil )
144
+ url ||= get_svn_url()
145
+ list = IO.read( '|-' ) or exec 'svn', 'ls', url
146
+
147
+ trace 'svn ls of %s: %p' % [url, list] if $trace
148
+
149
+ return [] if list.nil? || list.empty?
150
+ return list.split( $INPUT_RECORD_SEPARATOR )
151
+ end
152
+
153
+
154
+ ### Return the URL of the latest timestamp in the tags directory.
155
+ def get_latest_svn_timestamp_tag
156
+ rooturl = get_svn_repo_root()
157
+ tagsurl = rooturl + "/#{SVN_TAGS_DIR}"
158
+
159
+ tags = svn_ls( tagsurl ).grep( TAG_TIMESTAMP_PATTERN ).sort
160
+ return nil if tags.nil? || tags.empty?
161
+ return tagsurl + '/' + tags.last
162
+ end
163
+
164
+
165
+ ### Get a subversion diff of the specified targets and return it. If no targets are
166
+ ### specified, the current directory will be diffed instead.
167
+ def get_svn_diff( *targets )
168
+ targets << BASEDIR if targets.empty?
169
+ trace "Getting svn diff for targets: %p" % [targets]
170
+ log = IO.read( '|-' ) or exec 'svn', 'diff', *(targets.flatten)
171
+
172
+ return log
173
+ end
174
+
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
+
193
+ ### Return the URL of the latest timestamp in the tags directory.
194
+ def get_latest_release_tag
195
+ rooturl = get_svn_repo_root()
196
+ releaseurl = rooturl + "/#{SVN_RELEASES_DIR}"
197
+
198
+ tags = svn_ls( releaseurl ).grep( RELEASE_VERSION_PATTERN ).sort_by do |tag|
199
+ tag[RELEASE_VERSION_PATTERN].split('.').collect {|i| Integer(i) }
200
+ end
201
+ return nil if tags.empty?
202
+
203
+ return releaseurl + '/' + tags.last
204
+ end
205
+
206
+
207
+ ### Extract a diff from the specified subversion working +dir+ and return it.
208
+ def make_svn_commit_log( dir='.' )
209
+ diff = IO.read( '|-' ) or exec 'svn', 'diff'
210
+ fail "No differences." if diff.empty?
211
+
212
+ return diff
213
+ end
214
+
215
+
216
+ ### Extract the svn log from the specified subversion working +dir+,
217
+ ### starting from rev +start+ and ending with rev +finish+, and return it.
218
+ def make_svn_log( dir='.', start='PREV', finish='HEAD' )
219
+ trace "svn log -r#{start}:#{finish} #{dir}"
220
+ log = IO.read( '|-' ) or exec 'svn', 'log', "-r#{start}:#{finish}", dir
221
+ fail "No log between #{start} and #{finish}." if log.empty?
222
+
223
+ return log
224
+ end
225
+
226
+
227
+ ### Extract the verbose XML svn log from the specified subversion working +dir+,
228
+ ### starting from rev +start+ and ending with rev +finish+, and return it.
229
+ def make_xml_svn_log( dir='.', start='PREV', finish='HEAD' )
230
+ trace "svn log --xml --verbose -r#{start}:#{finish} #{dir}"
231
+ log = IO.read( '|-' ) or exec 'svn', 'log', '--verbose', '--xml', "-r#{start}:#{finish}", dir
232
+ fail "No log between #{start} and #{finish}." if log.empty?
233
+
234
+ return log
235
+ end
236
+
237
+
238
+ ### Create a changelog from the subversion log of the specified +dir+ and return it.
239
+ def make_svn_changelog( dir='.' )
240
+ require 'xml/libxml'
241
+
242
+ changelog = ''
243
+ path_prefix = '/' + get_svn_path( dir ) + '/'
244
+
245
+ xmllog = make_xml_svn_log( dir, 0 )
246
+
247
+ parser = XML::Parser.string( xmllog )
248
+ root = parser.parse.root
249
+ root.find( '//log/logentry' ).to_a.reverse.each do |entry|
250
+ trace "Making a changelog entry for r%s" % [ entry['revision'] ]
251
+
252
+ added = []
253
+ deleted = []
254
+ changed = []
255
+
256
+ entry.find( 'paths/path').each do |path|
257
+ pathname = path.content
258
+ pathname.sub!( path_prefix , '' ) if pathname.count('/') > 1
259
+
260
+ case path['action']
261
+ when 'A', 'R'
262
+ if path['copyfrom-path']
263
+ verb = path['action'] == 'A' ? 'renamed' : 'copied'
264
+ added << "%s\n#{FILE_INDENT}-> #{verb} from %s@r%s" % [
265
+ pathname,
266
+ path['copyfrom-path'],
267
+ path['copyfrom-rev'],
268
+ ]
269
+ else
270
+ added << "%s (new)" % [ pathname ]
271
+ end
272
+
273
+ when 'M'
274
+ changed << pathname
275
+
276
+ when 'D'
277
+ deleted << pathname
278
+
279
+ else
280
+ log "Unknown action %p in rev %d" % [ path['action'], entry['revision'] ]
281
+ end
282
+
283
+ end
284
+
285
+ date = Time.parse( entry.find_first('date').content )
286
+
287
+ # cvs2svn doesn't set 'author'
288
+ author = 'unknown'
289
+ if entry.find_first( 'author' )
290
+ author = entry.find_first( 'author' ).content
291
+ end
292
+
293
+ msg = entry.find_first( 'msg' ).content
294
+ rev = entry['revision']
295
+
296
+ changelog << "-- #{date.rfc2822} by #{author} (r#{rev}) -----\n"
297
+ changelog << " Added: " << humanize_file_list(added) << "\n" unless added.empty?
298
+ changelog << " Changed: " << humanize_file_list(changed) << "\n" unless changed.empty?
299
+ changelog << " Deleted: " << humanize_file_list(deleted) << "\n" unless deleted.empty?
300
+ changelog << "\n"
301
+
302
+ indent = msg[/^(\s*)/] + LOG_INDENT
303
+
304
+ changelog << indent << msg.strip.gsub(/\n\s*/m, "\n#{indent}")
305
+ changelog << "\n\n\n"
306
+ end
307
+
308
+ return changelog
309
+ end
310
+
311
+
312
+ ### Returns a human-scannable file list by joining and truncating the list if it's too long.
313
+ def humanize_file_list( list, indent=FILE_INDENT )
314
+ listtext = list[0..5].join( "\n#{indent}" )
315
+ if list.length > 5
316
+ listtext << " (and %d other/s)" % [ list.length - 5 ]
317
+ end
318
+
319
+ return listtext
320
+ end
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
+
356
+
357
+
358
+ ###
359
+ ### Tasks
360
+ ###
361
+
362
+ desc "Subversion tasks"
363
+ namespace :svn do
364
+
365
+ desc "Copy the HEAD revision of the current #{SVN_TRUNK_DIR}/ to #{SVN_TAGS_DIR}/ with a " +
366
+ "current timestamp."
367
+ task :tag do
368
+ svninfo = get_svn_info()
369
+ tag = make_new_tag()
370
+ svntrunk = svninfo['Repository Root'] + "/#{SVN_TRUNK_DIR}"
371
+ svntagdir = svninfo['Repository Root'] + "/#{SVN_TAGS_DIR}"
372
+ svntag = svntagdir + '/' + tag
373
+
374
+ desc = "Tagging trunk as #{svntag}"
375
+ ask_for_confirmation( desc ) do
376
+ msg = prompt_with_default( "Commit log: ", "Tagging for code push" )
377
+ run 'svn', 'cp', '-m', msg, svntrunk, svntag
378
+ end
379
+ end
380
+
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
+
419
+ desc "Copy the most recent tag to #{SVN_RELEASES_DIR}/#{PKG_VERSION}"
420
+ task :release do
421
+ last_tag = get_latest_svn_timestamp_tag()
422
+ svninfo = get_svn_info()
423
+ svnroot = Pathname.new( svninfo['Repository Root'] )
424
+ svntrunk = svnroot + SVN_TRUNK_DIR
425
+ svnrel = svnroot + SVN_RELEASES_DIR
426
+ release = PKG_VERSION
427
+ svnrelease = svnrel + release
428
+
429
+ unless svn_ls( svnrel.dirname ).include?( svnrel.basename.to_s + '/' )
430
+ log "Releases path #{svnrel} does not exist."
431
+ ask_for_confirmation( "To continue I'll need to create it." ) do
432
+ run 'svn', 'mkdir', svnrel, '-m', 'Creating releases/ directory'
433
+ end
434
+ else
435
+ trace "Found release dir #{svnrel}"
436
+ end
437
+
438
+ releases = svn_ls( svnrel ).collect {|name| name.sub(%r{/$}, '') }
439
+ trace "Releases: %p" % [releases]
440
+ if releases.include?( release )
441
+ error "Version #{release} already has a branch (#{svnrelease}). Did you mean " +
442
+ "to increment the version in #{VERSION_FILE}?"
443
+ fail
444
+ else
445
+ trace "No #{release} version currently exists"
446
+ end
447
+
448
+ desc = "Tagging trunk as #{svnrelease}..."
449
+ ask_for_confirmation( desc ) do
450
+ msg = prompt_with_default( "Commit log: ", "Branching for release" )
451
+ run 'svn', 'cp', '-m', msg, svntrunk, svnrelease
452
+ end
453
+ end
454
+
455
+ ### Task for debugging the #get_target_args helper
456
+ task :show_targets do
457
+ $stdout.puts "Targets from ARGV (%p): %p" % [ARGV, get_target_args()]
458
+ end
459
+
460
+
461
+ desc "Generate a commit log"
462
+ task :commitlog => [COMMIT_MSG_FILE]
463
+
464
+ desc "Show the (pre-edited) commit log for the current directory"
465
+ task :show_commitlog do
466
+ puts make_svn_commit_log()
467
+ end
468
+
469
+
470
+ file COMMIT_MSG_FILE do
471
+ diff = make_svn_commit_log()
472
+
473
+ File.open( COMMIT_MSG_FILE, File::WRONLY|File::EXCL|File::CREAT ) do |fh|
474
+ fh.print( diff )
475
+ end
476
+
477
+ editor = ENV['EDITOR'] || ENV['VISUAL'] || DEFAULT_EDITOR
478
+ system editor, COMMIT_MSG_FILE
479
+ unless $?.success?
480
+ fail "Editor exited uncleanly."
481
+ end
482
+ end
483
+
484
+
485
+ desc "Update from Subversion"
486
+ task :update do
487
+ run 'svn', 'up', '--ignore-externals'
488
+ end
489
+
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
+
529
+ desc "Check in all the changes in your current working copy"
530
+ task :checkin => ['svn:update', 'svn:newfiles', 'test', 'svn:fix_keywords', COMMIT_MSG_FILE] do
531
+ targets = get_target_args()
532
+ $deferr.puts '---', File.read( COMMIT_MSG_FILE ), '---'
533
+ ask_for_confirmation( "Continue with checkin?" ) do
534
+ run 'svn', 'ci', '-F', COMMIT_MSG_FILE, targets
535
+ rm_f COMMIT_MSG_FILE
536
+ end
537
+ end
538
+ task :commit => :checkin
539
+ task :ci => :checkin
540
+
541
+
542
+ task :clean do
543
+ rm_f COMMIT_MSG_FILE
544
+ end
545
+
546
+
547
+ desc "Check and fix any missing keywords for any files in the project which need them"
548
+ task :fix_keywords do
549
+ log "Checking subversion keywords..."
550
+ paths = get_svn_filelist( BASEDIR ).
551
+ select {|path| path.file? && path.to_s =~ KEYWORDED_FILEPATTERN }
552
+
553
+ trace "Looking at %d paths for keywords:\n %p" % [paths.length, paths]
554
+ kwmap = get_svn_keyword_map( paths )
555
+
556
+ buf = ''
557
+ PP.pp( kwmap, buf, 132 )
558
+ trace "keyword map is: %s" % [buf]
559
+
560
+ files_needing_fixups = paths.find_all do |path|
561
+ (kwmap[path.to_s] & DEFAULT_KEYWORDS) != DEFAULT_KEYWORDS
562
+ end
563
+
564
+ unless files_needing_fixups.empty?
565
+ $deferr.puts "Files needing keyword fixes: ",
566
+ files_needing_fixups.collect {|f|
567
+ " %s: %s" % [f, kwmap[f] ? kwmap[f].join(' ') : "(no keywords)"]
568
+ }
569
+ ask_for_confirmation( "Will add default keywords to these files." ) do
570
+ run 'svn', 'ps', 'svn:keywords', DEFAULT_KEYWORDS.join(' '), *files_needing_fixups
571
+ end
572
+ else
573
+ log "Keywords are all up to date."
574
+ end
575
+ end
576
+
577
+
578
+ task :debug_helpers do
579
+ methods = [
580
+ :get_last_changed_rev,
581
+ :get_latest_release_tag,
582
+ :get_latest_svn_timestamp_tag,
583
+ :get_svn_diff,
584
+ :get_svn_filelist,
585
+ :get_svn_info,
586
+ :get_svn_keyword_map,
587
+ :get_svn_path,
588
+ :get_svn_repo_root,
589
+ :get_svn_rev,
590
+ :get_svn_status,
591
+ :get_svn_url,
592
+ :svn_ls,
593
+ ]
594
+ maxlen = methods.collect {|sym| sym.to_s.length }.max
595
+
596
+ methods.each do |meth|
597
+ res = send( meth )
598
+ puts "%*s => %p" % [ maxlen, colorize(meth.to_s, :cyan), res ]
599
+ end
600
+ end
601
+ end
602
+