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