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.
- data.tar.gz.sig +0 -0
- data/ChangeLog +134 -506
- data/LICENSE +1 -1
- data/README.md +95 -0
- data/Rakefile +145 -95
- data/Rakefile.local +31 -39
- data/ext/dictionary.c +103 -37
- data/ext/extconf.rb +79 -32
- data/ext/linkage.c +245 -210
- data/ext/linkparser.c +3 -2
- data/ext/linkparser.h +21 -17
- data/ext/parseoptions.c +65 -65
- data/ext/sentence.c +75 -64
- data/lib/linkparser.rb +16 -26
- data/lib/linkparser/linkage.rb +68 -50
- data/lib/linkparser/mixins.rb +38 -0
- data/lib/linkparser/sentence.rb +15 -40
- data/rake/dependencies.rb +1 -1
- data/rake/documentation.rb +123 -0
- data/rake/helpers.rb +400 -310
- data/rake/hg.rb +318 -0
- data/rake/manual.rb +84 -79
- data/rake/packaging.rb +33 -37
- data/rake/publishing.rb +166 -146
- data/rake/style.rb +1 -1
- data/rake/svn.rb +577 -549
- data/rake/testing.rb +55 -106
- data/spec/bugfixes_spec.rb +12 -6
- data/spec/linkparser/dictionary_spec.rb +45 -29
- data/spec/linkparser/linkage_spec.rb +90 -94
- data/spec/linkparser/mixins_spec.rb +67 -0
- data/spec/linkparser/parseoptions_spec.rb +19 -22
- data/spec/linkparser/sentence_spec.rb +19 -17
- data/spec/linkparser_spec.rb +11 -5
- metadata +64 -147
- metadata.gz.sig +0 -0
- data/README +0 -61
- data/rake/rdoc.rb +0 -40
- data/rake/win32.rb +0 -186
data/rake/style.rb
CHANGED
data/rake/svn.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Subversion Rake Tasks
|
3
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
###
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
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
|
-
|
205
|
-
|
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
|
209
|
-
def
|
210
|
-
|
211
|
-
|
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
|
-
###
|
218
|
-
|
219
|
-
|
220
|
-
|
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
|
-
|
223
|
-
end
|
118
|
+
return url.sub( root + '/', '' )
|
119
|
+
end
|
224
120
|
|
225
121
|
|
226
|
-
###
|
227
|
-
|
228
|
-
|
229
|
-
|
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
|
-
|
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
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
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
|
-
|
245
|
-
end
|
139
|
+
return kwmap
|
140
|
+
end
|
246
141
|
|
247
142
|
|
248
|
-
###
|
249
|
-
def
|
250
|
-
|
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
|
-
|
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
|
-
|
263
|
-
|
264
|
-
|
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
|
-
|
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
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
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
|
-
|
334
|
-
|
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
|
-
|
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
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
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
|
-
###
|
356
|
-
def
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
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
|
-
|
370
|
-
###
|
251
|
+
return diff
|
252
|
+
end
|
371
253
|
|
372
|
-
desc "Subversion tasks"
|
373
|
-
namespace :svn do
|
374
254
|
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
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
|
-
|
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
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
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
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
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
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
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
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
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
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
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
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
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
|
-
|
500
|
-
|
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
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
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
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
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
|
-
|
471
|
+
task :sw => :switch
|
521
472
|
|
522
473
|
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
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
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
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
|
-
|
552
|
-
|
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
|
-
|
556
|
-
|
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
|
-
|
560
|
-
|
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
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
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
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
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
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
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
|
-
|
666
|
+
|
667
|
+
end # unless defined?( SVN_DOTDIR )
|
640
668
|
|