rscm-accurev 0.0 → 0.0.1

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.
Files changed (49) hide show
  1. data/Rakefile +7 -76
  2. data/TODO +3 -17
  3. data/lib/rscm/accurev.rb +1 -13
  4. data/lib/rscm/scm/accurev/#command.rb# +95 -0
  5. data/lib/rscm/scm/accurev/api.rb +77 -258
  6. data/lib/rscm/scm/accurev/command.rb +40 -97
  7. data/lib/rscm/scm/accurev/filterio.rb +4 -6
  8. data/lib/rscm/scm/accurev/xml.rb +11 -199
  9. data/test/t_command.rb +11 -59
  10. data/test/t_load.rb +0 -1
  11. data/test/t_scrubio.rb +6 -1
  12. data/{apitest.rb → test.rb} +0 -1
  13. data/{test/eg/update-newwksp.xml → testing.log} +138 -0
  14. metadata +15 -57
  15. data/STATUS +0 -63
  16. data/bumprelease.sh +0 -13
  17. data/lib/rscm/scm/accurev/api.rb.mine +0 -382
  18. data/lib/rscm/scm/accurev/api.rb.r263 +0 -364
  19. data/lib/rscm/scm/accurev/api.rb.r265 +0 -393
  20. data/lib/rscm/scm/accurev/exception.rb +0 -38
  21. data/lib/test/unit/ui/xml/testrunner.rb +0 -165
  22. data/lib/test/unit/ui/xml/xmltestrunner.xslt +0 -79
  23. data/test/coverage/analyzer.rb +0 -127
  24. data/test/coverage/c_loader.rb +0 -34
  25. data/test/coverage/cover.rb +0 -91
  26. data/test/coverage/coverage_loader.rb +0 -21
  27. data/test/coverage/coveragetask.rb +0 -38
  28. data/test/coverage/index_tmpl.html +0 -42
  29. data/test/coverage/template.html +0 -36
  30. data/test/eg/ac-files.xml +0 -172
  31. data/test/eg/ac-pop.txt +0 -195
  32. data/test/eg/files-various-states.xml +0 -188
  33. data/test/eg/hist-oneweek-all.xml +0 -1483
  34. data/test/eg/hist-oneweek-external.xml +0 -246
  35. data/test/eg/hist-oneweek-promotes.xml +0 -1092
  36. data/test/eg/info.txt +0 -14
  37. data/test/eg/stat-a-various.xml +0 -1789
  38. data/test/eg/stat-m.xml +0 -13
  39. data/test/eg/stat-overlap.xml +0 -13
  40. data/test/eg/stat-x.xml +0 -20
  41. data/test/eg/update-i-mods-and-updates-and-overlap.xml +0 -73
  42. data/test/eg/update-i-nochanges.xml +0 -8
  43. data/test/eg/update-i-stale.xml +0 -0
  44. data/test/eg/update-i-updates.xml +0 -125
  45. data/test/eg/update-nochanges.xml +0 -7
  46. data/test/eg/update-stale.xml +0 -12
  47. data/test/eg/update-updates.xml +0 -147
  48. data/test/t_api.rb +0 -163
  49. data/test/t_xmlmapper.rb +0 -75
@@ -1,42 +1,27 @@
1
1
  # -*- ruby -*-
2
- #
3
- # = api.rb
4
- #
5
- # API for interacting with accurev workspaces.
6
- #
7
- # Includes:
8
- #
9
- # * API
10
- #
11
- require 'stringio'
2
+ require 'rubygems'
12
3
  require 'rscm/base'
13
4
  require 'rscm/path_converter'
14
5
  require 'rexml/document'
15
6
  require 'rscm/scm/accurev/xml'
16
7
  require 'rscm/scm/accurev/filterio'
17
8
  require 'rscm/scm/accurev/command'
18
- require 'rscm/scm/accurev/exception'
19
9
 
20
- # need to define module within module before you can use module X::Y
21
- module RSCM; module Accurev; end; end
10
+ module RSCM
11
+ module Accurev; end
12
+ end
22
13
 
23
14
  module RSCM::Accurev
24
15
 
16
+ class AccurevException < Exception ; end
17
+
18
+ # Indicates a failure of the update command due to unkept local modifications
19
+ class StaleWorkspaceError < AccurevException; end
20
+
21
+ # RSCM implementation for Accurev (http://www.accurev.com/).
25
22
  #
26
- # RSCM implementation for Accurev (http://www.accurev.com).
27
- #
28
- # Requires an accurev cli executable on the path (see also
29
- # RSCM::Accurev::Command), and the correct environment
30
- # configuration for ac server/principal/password.
31
- #
32
- # ---
33
- #
34
- # === Example
35
- #
36
- # api = RSCM::Accurev::API.new( "./ws/proj-1", "proj", "proj-1" )
37
- # api.checkout() each do |file|
38
- # puts "Updated #{file}..."
39
- # end
23
+ # Requires an accurev cli executable on the path, and the correct
24
+ # environment for ac server/principal/password.
40
25
  #
41
26
  class API < RSCM::Base
42
27
  register self
@@ -47,32 +32,36 @@ module RSCM::Accurev
47
32
  ann :description => "Backing Stream (autodetected)"
48
33
  attr_accessor :backing_stream
49
34
 
50
- # If workspace stream is nil (the default), checkout/update will be
51
- # done using `accurev pop`. This is faster and more appropriate for
52
- # read-only use; however a workspace is required for commits.
53
35
  ann :description => "Workspace Stream"
54
36
  attr_accessor :workspace_stream
55
37
 
56
- # [defined in Base]
57
- # ann :description => "Filesystem Path to Workspace"
58
- # attr_accessor :checkout_dir
59
-
60
- ann :description => "Overwrite Mode: if true, co overwrites existing"
61
- attr_accessor :overwrite
62
-
63
- def initialize(checkout_dir=nil, backing_stream=nil, workspace_stream=nil)
64
- @depot = nil # will be pulled from files cmd output
65
- @workspace_stream = workspace_stream
66
- @backing_stream = backing_stream
38
+ # defined in Base
39
+ # ann :description => "Filesystem Path to Workspace"
40
+ # attr_accessor :checkout_dir
41
+
42
+ STATUSES = {
43
+ '(backed)' => :backed,
44
+ '(external)' => :external,
45
+ '(modified)' => :modified,
46
+ '(kept)' => :kept,
47
+ '(defunct)' => :defunct,
48
+ '(missing)' => :missing,
49
+ '(stranded)' => :stranded,
50
+ '(overlap)' => :overlap
51
+ }
52
+
53
+ def initialize( checkout_dir=nil, depot=nil, workspace_stream=nil )
54
+ @depot = depot
67
55
  @checkout_dir = checkout_dir
68
- @overwrite = false
56
+ @workspace_stream = workspace_stream
57
+ @backing_stream = nil # will be pulled from files cmd output
69
58
  end
70
59
 
71
60
  def name()
72
61
  return "Accurev"
73
62
  end
74
63
 
75
- # Accurev operations are atomic: returns true.
64
+ # Accurev operations are atomic:
76
65
  def transactional?
77
66
  return true
78
67
  end
@@ -87,9 +76,6 @@ module RSCM::Accurev
87
76
  end
88
77
 
89
78
  # "Returns a Revisions object for the period specified ... (inclusive)."
90
- #
91
- # list txns (promotes to bs) from hist within the period
92
- #
93
79
  def revisions( from_identifier, to_identifier=Time.infinity )
94
80
  raise "XXX implement me"
95
81
  end
@@ -111,58 +97,20 @@ module RSCM::Accurev
111
97
 
112
98
  # --- ac specific
113
99
 
114
- # remember: ac_files is non-recursive
115
100
  def ac_files( relative_path )
116
- cmd = Command.instance
117
- ret = []
118
- with_working_dir( co_filepath ) do
119
- acresponse = cmd.accurev( "files", relative_path )
120
- if acresponse['element'].nil?
121
- return []
122
- end
123
- acresponse['element'].each do |fd|
124
- yield fd if block_given?
125
- ret << fd
126
- end
101
+ out = self.accurev( "files", relative_path )
102
+ # validate
103
+ raise AccurevException.new("Failed to get response") if out.nil?
104
+ if ( out.root.name!="AcResponse" )
105
+ raise AccurevException.new("Invalid response")
127
106
  end
128
- return ret
129
- end
130
-
131
- def ac_stat( flag="-a" )
132
- cmd = Command.instance
133
- ret = []
134
- with_working_dir( co_filepath ) do
135
- acresponse = cmd.accurev( "stat", flag )
136
- return [] if acresponse['element'].nil?
137
- acresponse['element'].each do |fd|
138
- yield fd if block_given?
139
- ret << fd
140
- end
141
- end
142
- return ret
143
- end
144
-
145
- # yeilds the TransactionData objects for the given time period
146
- # (promotes only)
147
- def ac_hist( from, to=Time.infinite )
148
- cmd = Command.instance
149
- lower = from.to_accurev
150
- upper = "now"
151
- unless to == Time.infinite
152
- upper = to.to_accurev
153
- end
154
- with_working_dir( self.co_filepath ) do
155
- acresponse = cmd.accurev( "hist",
156
- "-t", "'#{upper}-#{lower}'",
157
- "-k", "promote"
158
- )
159
- ret = []
160
- acresponse['transaction'].each do |txn|
161
- ret << txn
162
- yield txn if block_given?
163
- end
164
- return ret
107
+ files = []
108
+ out.elements.each( "/AcResponse/element" ) do |e|
109
+ f = FileStatus.new( e )
110
+ yield f if block_given?
111
+ files << f
165
112
  end
113
+ return files
166
114
  end
167
115
 
168
116
  def ac_keep( files=[], message="" )
@@ -192,32 +140,9 @@ module RSCM::Accurev
192
140
  raise "XXX implement me"
193
141
  end
194
142
 
195
- #
196
- # Performs an "accurev info" command in the workspace.
197
- # Returns a map of
198
- #
199
143
  # ac info: shows eg, backing stream
200
- # but doesn't support -fx!
201
- #
202
- def ac_info()
203
- co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
204
- unless File.exists?( co )
205
- raise AccurevException.new( "Checkout dir #{co} does not exist" )
206
- end
207
- info = {}
208
- with_working_dir( co ) do
209
- cmd = Command.instance
210
- io = StringIO.new( cmd.accurev_nofx( "info" ) )
211
- io.each_line do |line|
212
- next unless line =~ /\S/
213
- if line =~ /^(.*?):\s+(.*)$/
214
- info[$1] = $2
215
- end
216
- end
217
- end
218
- return info
219
- end
220
-
144
+ # but doesn't support -fx!
145
+
221
146
  # ac mkws
222
147
  # -b orbitz-host-gt3-0-impl
223
148
  # -w orbitz-host-gt3-0-impl-test2_gfast
@@ -231,7 +156,7 @@ module RSCM::Accurev
231
156
  # (eg, no in-process diffing ala cvs diff)
232
157
  # lists modified lines in xml
233
158
 
234
- #
159
+ # checkout():
235
160
  # "Checks out or updates[!] contents from a central SCM
236
161
  # to +checkout_dir+ - a local working copy."
237
162
  #
@@ -239,156 +164,60 @@ module RSCM::Accurev
239
164
  # obtain files up to a particular time or label."
240
165
  #
241
166
  # For accurev, this:
242
- # * checks to see if +@checkout_dir+ exists and appears checked out.
243
- # If it's already checked out, this calls +update()+. If
244
- # +@checkout_dir+ exists and +to_identifier+ is given, an
245
- # exception is raised.
167
+ # * checks to see if @checkout_dir exists and appears checked out.
168
+ # If it's already checked out, this calls update().
246
169
  # * otherwise, this creates a new workspace stream and populates it
247
- # at +@checkout_dir+.
248
- #
249
- # This both returns and yields a list of updated files.
250
- # Only updated files are returned, not directories.
170
+ # at @checkout_dir.
251
171
  #
252
- # Current, ac_update returns both files and directories, including
253
- # deleted files.
172
+ # Unknown: support for +to_identifier+ (esp for update)?
254
173
  #
174
+ # This method yields files in the workspace and doesn't need to be
175
+ # overridden.
176
+ # The checkout_silent() method does the actual work.
177
+ #
178
+ # Only yields files, not directories
255
179
  def checkout( to_identifier=Time.infinite )
256
- co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
257
- if @backing_stream.nil?
258
- self.attempt_init_from_info()
259
- end
260
- if @workspace_stream.nil?
261
- self.checkout_pop()
262
- else
263
- unless File.exists?( co )
264
- # create new workspace
265
- self.checkout_workspace()
180
+ co = PathConverter.nativepath_to_filepath( @checkout_dir )
181
+ unless File.exists?( co )
182
+ puts "> creating new workspace..."
183
+ if @backing_stream.nil?
184
+ raise "Backing stream must be set"
266
185
  end
267
- # update workspace
268
- self.update( to_identifier )
269
- end
270
- end
271
-
272
- def checkout_pop()
273
- co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
274
- raise "A backing stream is required" if @backing_stream.nil?
275
- raise "A working stream may not be given" unless @working_stream.nil?
276
- # for `accurev pop`: remove and re-pop the checkout copy
277
- if File.exists?( co )
278
- unless @overwrite
279
- raise "Checkout dir #{co} already exists (@overwrite=#@overwrite)"
186
+ if @workspace_stream.nil?
187
+ raise "Workspace stream must be set"
280
188
  end
281
- rm_rf( co )
282
- end
283
- mkdir(co)
284
- with_working_dir( co ) do
285
- cmd = Command.instance
286
- pop_out = cmd.accurev_nofx("pop",
287
- "-R",
288
- "-v", @backing_stream,
289
- "-L", ".", ".")
290
- elems = []
291
- popio = StringIO.new( pop_out )
292
- popio.each_line do |line|
293
- if line =~ /^Populating element \/.\/(.*)$/
294
- loc = $1
295
- elems << loc
296
- yield loc if block_given?
297
- end
189
+ mkws_out = self.accurev_nofx( "mkws",
190
+ "-b", @backing_stream,
191
+ "-w", @workspace_stream,
192
+ "-l", co )
193
+ # sucks:
194
+ if ( mkws_out =~ /already exists/ )
195
+ raise AccurevException.new( mkws_out )
298
196
  end
299
- return elems
300
- end
301
- end
302
-
303
- def checkout_workspace()
304
- co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
305
- raise "A backing stream is required" if @backing_stream.nil?
306
- raise "A workspace is required" if @working_stream.nil?
307
- if File.exist?( co ) and !@overwrite
308
- raise "Checkout dir #{co} already exists (@overwrite=#@overwrite)"
309
- end
310
- cmd = Command.instance
311
- mkws_out = cmd.accurev_nofx( "mkws",
312
- "-b", @backing_stream,
313
- "-w", @workspace_stream,
314
- "-l", co )
315
- # kinda sucks:
316
- if ( mkws_out =~ /already exists/ )
317
- raise AccurevException.new( "Failed to checkout", mkws_out )
318
197
  end
198
+ puts "> Updating workspace.."
199
+ self.update( to_identifier )
319
200
  end
320
201
 
321
202
  def update( to_identifier=Time.infinite )
322
- co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
203
+ co = PathConverter.nativepath_to_filepath( @checkout_dir )
323
204
  unless File.exists?( co )
324
205
  raise AccurevException.new( "Workspace does not exist!" )
325
206
  end
326
207
  updated = []
327
208
  with_working_dir( co ) do
328
- cmd = Command.instance
329
- acresponse = cmd.accurev( "update" )
330
- if acresponse.error
331
- if acresponse.error =~ /workspace have been modified/
332
- raise StaleWorkspaceException.new( "Workspace stale",
333
- acresponse.error )
334
- else
335
- # some other update problem
336
- raise AccurevException.new( "Error on update", acresponse.error )
337
- end
338
- end
339
- if acresponse['element']
340
- acresponse['element'].each do |up|
341
- # "ac update" on a new workspace yields element locations
342
- # with leading "/"s, which should be removed to get a proper
343
- # relative path:
344
- loc = up.location.sub( /^\//, "" )
345
- yield loc if block_given?
346
- updated << loc
347
- end
209
+ accurev_elements( UpdateData, "update" ) do |up|
210
+ yield up.location
211
+ updated << up.location
348
212
  end
349
213
  end
350
214
  return updated
351
215
  end
352
216
 
353
- # --- internals
354
217
 
355
- # status flag mappings for "stat", "file" commands
356
- STATUSES = {
357
- '(backed)' => :backed,
358
- '(external)' => :external,
359
- '(modified)' => :modified,
360
- '(kept)' => :kept,
361
- '(defunct)' => :defunct,
362
- '(missing)' => :missing,
363
- '(stranded)' => :stranded,
364
- '(overlap)' => :overlap
365
- }
366
-
367
- # private
368
-
369
- # psuedo-accessor (cached)
370
- def co_filepath
371
- if @co_filepath.nil?
372
- @co_filepath = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
373
- end
374
- return @co_filepath
375
- end
218
+ # --- internals
376
219
 
377
- #
378
- # Runs an `ac info` command in +@checkout_dir+, and tries to
379
- # set +@backing_stream+ and +@workspace_stream+ from the output.
380
- #
381
- def attempt_init_from_info()
382
- if File.exists?( self.co_filepath )
383
- info = self.ac_info
384
- if info.has_key?( "Basis" )
385
- @backing_stream = info["Basis"]
386
- end
387
- if info.has_key?( "ws/ref" )
388
- @workspace_stream = info["ws/ref"]
389
- end
390
- end
391
- end
220
+ private
392
221
 
393
222
  # Takes a status flags line (eg, "(modified)(kept)")
394
223
  # and returns a list of status flags.
@@ -399,13 +228,3 @@ module RSCM::Accurev
399
228
  end
400
229
 
401
230
  end
402
-
403
- class Time
404
- def to_accurev
405
- self.strftime( "%Y/%m/%d %H:%M:%S" )
406
- end
407
- end
408
-
409
- #
410
- # Copyright (c) 2005 Gregory D. Fast <gdf@speakeasy.net>
411
- #
@@ -1,49 +1,35 @@
1
1
  # -*- ruby -*-
2
2
 
3
+ require 'singleton'
4
+
3
5
  module RSCM
4
6
  module Accurev
5
7
 
6
- #
7
- # Executes accurev commands and deals with the output.
8
- # This class is a thread local singleton: each thread
9
- # calling +Command.instance+ gets a different instance.
10
- #
11
8
  class Command
9
+ include Singleton
12
10
 
13
- attr_accessor :debug, :debug_to, :accurev_bin
14
-
15
- # If you need to swap out the mapper class
16
- attr_accessor :xmlmapper
11
+ attr_accessor :debug, :debug_to, :accurev, :working_dir
17
12
 
18
- def initialize()
19
- @xmlmapper = XMLMapper
13
+ def initialize( working_dir="." )
20
14
  @debug = false
21
15
  @debug_to = STDOUT
22
- @accurev_bin = "accurev"
16
+ @accurev = "accurev"
17
+ @working_dir = working_dir
23
18
  end
24
19
 
25
- #
26
- # Returns a command line string for executing the given
27
- # accurev subcomment +cmd+ with arguments +opts+.
28
- #
29
20
  def accurev_cmdline( cmd, *opts )
30
- return "#{@accurev_bin} #{cmd} #{opts.join(' ')}";
21
+ return "#{@accurev} #{cmd} #{opts.join(' ')}";
31
22
  end
32
-
33
- #
34
- # Executes the given accurev subcommand +cmd+ with the
35
- # given arguments +opts+. The command will be executed with
36
- # standard (non-xml) output format. This method returns
37
- # the stdout from the command execution.
38
- #
39
- # (Not all accurev subcommands (eg, `accurev info`) support
40
- # `-fx` for xml output.)
41
- #
23
+
24
+ # Execute the given accurev subcommand, and return its
25
+ # output as a plain uninterpreted string.
26
+ # Not all accurev subcommands (eg, `accurev info`) support
27
+ # `-fx` for xml output.
42
28
  def accurev_nofx( cmd, *opts )
43
- ## # nativepath_to_filepath is actually generic to native
44
- ## dir = PathConverter.nativepath_to_filepath( @working_dir )
45
- ## dir = File.expand_path( dir )
46
- ## with_working_dir( dir ) do
29
+ # nativepath_to_filepath is actually generic to native
30
+ dir = PathConverter.nativepath_to_filepath( @working_dir )
31
+ dir = File.expand_path( dir )
32
+ with_working_dir( dir ) do
47
33
  cmdline = self.accurev_cmdline( cmd, opts )
48
34
  if @debug
49
35
  @debug_to.puts("ac> #{cmdline}")
@@ -51,26 +37,20 @@ module RSCM
51
37
  Better.popen( cmdline ) do |stdout|
52
38
  return stdout.read()
53
39
  end
54
- ## end
40
+ end
55
41
  end
56
-
57
- #
58
- # Executes the given accurev subcommand +cmd+ with the
59
- # given arguments +opts+ in XML mode. The output of the command
60
- # will be converted to an REXML document and returned.
61
- # The command's options list will have `-fx` appended,
62
- # to specify xml output format.
63
- #
42
+
43
+ # Execute the given accurev subcommand, and return its
44
+ # output as an REXML document. The options list to the command
45
+ # will automatically have `-fx` prepended, to specify xml output.
64
46
  # Certain quirks in <AcResponse>-type documents will be
65
- # corrected (see Accurev::AcXMLScrubIO). Note that not all
66
- # accurev subcommands support the "-fx" option.
67
- #
68
- def accurev_xml( cmd, *opts )
47
+ # corrected (see Accurev::AcXMLScrubIO).
48
+ def accurev( cmd, *opts )
49
+ # nativepath_to_filepath is actually generic to native
50
+ dir = PathConverter.nativepath_to_filepath( @working_dir )
51
+ dir = File.expand_path( dir )
69
52
  opts << "-fx"
70
- ## # nativepath_to_filepath is actually generic to native
71
- ## dir = PathConverter.nativepath_to_filepath( @working_dir )
72
- ## dir = File.expand_path( dir )
73
- ## with_working_dir( dir ) do
53
+ with_working_dir( dir ) do
74
54
  cmdline = self.accurev_cmdline( cmd, opts )
75
55
  if @debug
76
56
  @debug_to.puts("ac> #{cmdline}")
@@ -78,8 +58,7 @@ module RSCM
78
58
  Better.popen( cmdline ) do |stdout|
79
59
  output = stdout.read()
80
60
  if @debug
81
- @debug_to.puts( "raw>" )
82
- @debug_to.puts( output )
61
+ @debug_to.puts( "raw>\n#{output}" )
83
62
  end
84
63
  begin
85
64
  return REXML::Document.new( AcXMLScrubIO.new( output ) )
@@ -87,64 +66,28 @@ module RSCM
87
66
  raise "Unexpected output from #{cmdline}: #{e}"
88
67
  end
89
68
  end
90
- ## end
69
+ end
91
70
  end
92
71
 
93
- #
94
- # Execute the given accurev subcommand using +accurev_xml+,
95
- # and return an object tree mirroring the structure of the
96
- # XML output.
97
- #
98
- # This uses +XMLMapper+ to build the object tree.
99
- #
100
- def accurev( cmd, *opts )
101
- doc = self.accurev_xml( cmd, opts )
72
+ # Execute the given accurev subcommand using +accurev+,
73
+ # and return the <element> REXML elements from the
74
+ # resulting document.
75
+ # For ac commands which emit the common <elements> format.
76
+ def accurev_elements( mapclass, cmd, *opts )
77
+ doc = self.accurev( cmd, opts )
102
78
  if @debug
103
- @debug_to.puts( "doc>" )
104
79
  @debug_to.puts( doc )
105
80
  end
106
81
  if doc.elements.size==0
107
82
  raise "Unexpected output from #{cmd}: #{doc}"
108
83
  end
109
- mapper = @xmlmapper.new()
110
- return mapper.map( doc.root )
111
- end
112
-
113
- # static methods
114
-
115
- # Retrieve this thread's +Command+ instance.
116
- #
117
- # eg:
118
- # cmd = Command.instance
119
- # eg:
120
- # Command.instance do |cmd|
121
- # cmd.workspace_dir = "/var/tmp"
122
- # end
123
- #
124
- def Command.instance()
125
- if Thread.current[ :RSCM_ACCUREV_COMMAND ].nil?
126
- Thread.current[ :RSCM_ACCUREV_COMMAND ] = Command.new
84
+ doc.elements.each( "/AcResponse/element" ) do |e|
85
+ o = mapclass.new( e )
86
+ yield o
127
87
  end
128
- yield Thread.current[ :RSCM_ACCUREV_COMMAND ] if block_given?
129
- return Thread.current[ :RSCM_ACCUREV_COMMAND ]
130
- end
131
-
132
- # Discard the current thread's Command object.
133
- # The next call to +Command.instance+ in this thread will
134
- # return a new instance configured with the defaults.
135
- def Command.discard()
136
- Thread.current[ :RSCM_ACCUREV_COMMAND ] = nil
137
- end
138
-
139
- private
140
-
141
- # new() is marked private, use Command.instance().
142
- def new( *args )
143
- super(args)
144
88
  end
145
89
 
146
- end # class Command
147
-
90
+ end
148
91
  end
149
92
  end
150
93
 
@@ -3,19 +3,17 @@ require 'stringio'
3
3
  module RSCM
4
4
  module Accurev
5
5
 
6
- #
7
6
  # IO stream which cleans irregularities out of accurev xml output.
8
7
  #
9
8
  # In particular:
10
9
  #
11
- # * Unlike other commands, the +-fx+ output from _accurev update_
12
- # has a root element of +<acResponse>+, not +<AcResponse>+.
10
+ # * the -fx output from `accurev update` has a root element of
11
+ # <acResponse>, not <AcResponse> like the other commands
13
12
  #
14
- # * _accurev update_ emits broken XML when there are no files
15
- # to update.
13
+ # * `accurev update` emits broken XML when there are no files
14
+ # needing updates.
16
15
  #
17
16
  class AcXMLScrubIO < StringIO
18
-
19
17
  # @param: sourceio - io or string source to wrap
20
18
  def initialize( sourceio )
21
19
  if sourceio.respond_to?( :read )