rscm-accurev 0.0.3 → 0.0.4
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/Rakefile +43 -6
- data/STATUS +63 -0
- data/TODO +15 -4
- data/lib/rscm/accurev.rb +10 -0
- data/lib/rscm/scm/accurev/api.rb +114 -49
- data/lib/rscm/scm/accurev/command.rb +11 -12
- data/lib/rscm/scm/accurev/filterio.rb +6 -4
- data/lib/rscm/scm/accurev/xml.rb +38 -8
- data/lib/test/unit/ui/xml/testrunner.rb +165 -0
- data/lib/test/unit/ui/xml/xmltestrunner.xslt +79 -0
- data/test/eg/info.txt +14 -0
- data/test/t_api.rb +50 -5
- data/test/t_command.rb +16 -14
- metadata +11 -3
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'rake/rdoctask'
|
|
6
6
|
require 'rake/packagetask'
|
7
7
|
require 'rake/gempackagetask'
|
8
8
|
|
9
|
-
# rakefile borrowed shamelessly from rscm
|
9
|
+
# this rakefile originally borrowed shamelessly from rscm
|
10
10
|
|
11
11
|
PKG_NAME = 'rscm-accurev'
|
12
12
|
PKG_BUILD = ENV['PKG_BUILD'] ? '.'+ENV['PKG_BUILD'] : ''
|
@@ -17,20 +17,52 @@ PKG_SUMMARY = 'RSCM::Accurev - RSCM API for Accurev'
|
|
17
17
|
desc "Default Task"
|
18
18
|
task :default => [ :test, :gem ]
|
19
19
|
|
20
|
-
#
|
21
|
-
|
20
|
+
#task :test => [ :backup_testresults, :xmltest ]
|
21
|
+
|
22
|
+
# define a task(s) to run tests
|
23
|
+
|
24
|
+
test_files = FileList.new( "test/**/t_*.rb" )
|
25
|
+
TEST_OUTPUT = "doc"
|
26
|
+
|
27
|
+
Rake::TestTask.new( :plaintest ) do |t|
|
22
28
|
t.libs << "test"
|
23
|
-
t.test_files =
|
29
|
+
t.test_files = test_files
|
24
30
|
t.verbose = true
|
25
31
|
end
|
26
32
|
|
33
|
+
# requires a patch to rake_test_loader.rb to exclude options
|
34
|
+
# requires a patch to rake/testtask.rb to support ruby_opts
|
35
|
+
# (see doc/patches)
|
36
|
+
Rake::TestTask.new( :xmltest ) do |t|
|
37
|
+
t.libs << "test"
|
38
|
+
t.test_files = test_files
|
39
|
+
t.verbose = true
|
40
|
+
t.ruby_opts << '-rtest/unit/ui/xml/testrunner'
|
41
|
+
ENV['XMLTEST_OUTPUT'] = "#{TEST_OUTPUT}/testresults.xml"
|
42
|
+
t.options = "--runner=xml"
|
43
|
+
end
|
44
|
+
|
45
|
+
# backs up existing testresults.xml files in test target dir
|
46
|
+
task :backup_testresults do
|
47
|
+
old = "#{TEST_OUTPUT}/testresults.xml"
|
48
|
+
if File.exist?( old )
|
49
|
+
stat = File.stat( old )
|
50
|
+
bak = stat.ctime.strftime('testresults-%Y%m%d-%H%M.xml')
|
51
|
+
new = "#{TEST_OUTPUT}/#{bak}"
|
52
|
+
#puts "...Backing up previous test results to #{new}"
|
53
|
+
mv( old, new )
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
27
57
|
# define a task to create rdocs
|
28
58
|
# keep a reference to it so we can reuse it in the gempkg task
|
29
|
-
rd_task = Rake::RDocTask.new do |rdoc|
|
59
|
+
rd_task = Rake::RDocTask.new( :rdoc ) do |rdoc|
|
30
60
|
rdoc.title = PKG_SUMMARY
|
61
|
+
rdoc.template = "doc/jamis.rb" # so nice
|
31
62
|
rdoc.options << '--line-numbers' << '--inline-source'
|
32
|
-
|
63
|
+
rdoc.rdoc_files.include( 'STATUS' )
|
33
64
|
rdoc.rdoc_files.include( 'lib/**/*.rb' )
|
65
|
+
rdoc.rdoc_files.include( 'doc/*.rd' )
|
34
66
|
end
|
35
67
|
|
36
68
|
PKG_FILES = FileList[
|
@@ -64,5 +96,10 @@ else
|
|
64
96
|
end
|
65
97
|
end
|
66
98
|
|
99
|
+
desc "Delete all generated files (includes built packages)"
|
100
|
+
task :realclean => :clean do
|
101
|
+
f = FileList[ 'pkg', 'html', 'doc/test*.xml' ]
|
102
|
+
rm f
|
103
|
+
end
|
67
104
|
|
68
105
|
|
data/STATUS
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
= RSCM::Accurev Status
|
3
|
+
|
4
|
+
------------------------
|
5
|
+
|
6
|
+
== Core RSCM API (RSCM::Accurev::API)
|
7
|
+
|
8
|
+
[checkout()] supported
|
9
|
+
|
10
|
+
- basic checkouts should work
|
11
|
+
|
12
|
+
- time-based checkouts do not work
|
13
|
+
|
14
|
+
[update()] basic updates work
|
15
|
+
|
16
|
+
- time-based updates ("update( yesterday )") not working
|
17
|
+
|
18
|
+
- elements list returned currently includes directories and removed files
|
19
|
+
|
20
|
+
[add()] unsupported, todo(?)
|
21
|
+
|
22
|
+
[edit()] supported (no-op)
|
23
|
+
|
24
|
+
[revisions()] supported
|
25
|
+
|
26
|
+
- time-based limits do not work
|
27
|
+
|
28
|
+
- should be history-based
|
29
|
+
|
30
|
+
-------------------------------------------
|
31
|
+
|
32
|
+
== Accurev-specific API (RSCM::Accurev::API)
|
33
|
+
|
34
|
+
[ac_update()] unsupported, todo
|
35
|
+
|
36
|
+
[ac_files()] supported
|
37
|
+
|
38
|
+
[ac_info()] supported
|
39
|
+
|
40
|
+
[ac_stat()] unsupported, use ac_files().
|
41
|
+
|
42
|
+
[ac_move()] unsupported, todo
|
43
|
+
|
44
|
+
[ac_pop()] unsupported, todo
|
45
|
+
|
46
|
+
[ac_purge()] unsupported, todo
|
47
|
+
|
48
|
+
[ac_hist()] unsupported, todo
|
49
|
+
|
50
|
+
[ac_keep()] unsupported, todo
|
51
|
+
|
52
|
+
[ac_promote()] unsupported, todo
|
53
|
+
|
54
|
+
-------------------------------------------
|
55
|
+
|
56
|
+
== Other Items
|
57
|
+
|
58
|
+
[code docs] woefully incomplete
|
59
|
+
|
60
|
+
[usage docs] virtually nonexistant
|
61
|
+
|
62
|
+
[test coverage] truly pitiful
|
63
|
+
|
data/TODO
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# todo for rscm/scm/accurev.rb
|
2
2
|
|
3
|
-
|
3
|
+
api - checkout
|
4
4
|
- there is no rscm-api update() (only checkout-to-existing-ws)
|
5
5
|
- `pop`, `update`
|
6
6
|
|
7
7
|
**api - revisions
|
8
8
|
- `hist` (others?)
|
9
9
|
|
10
|
-
|
10
|
+
api - diff
|
11
11
|
- `diff` (yukx)
|
12
12
|
|
13
13
|
api - import_central, create_central
|
@@ -21,10 +21,21 @@ api - triggers?
|
|
21
21
|
**api - identifiers (Time or revision) to ac format
|
22
22
|
- is this even always applicable? does stat/update take limits?
|
23
23
|
|
24
|
-
xml - s/FileStatus/FileData/
|
24
|
+
# xml - s/FileStatus/FileData/
|
25
25
|
|
26
26
|
api - checkout(Time.infinite) just does update
|
27
27
|
checkout(x) only works if ws not exist
|
28
28
|
unless it implies nuke-and-re-checkout (slow)
|
29
29
|
|
30
|
-
api - need ac_update which returns an acresponse
|
30
|
+
api - need ac_update which returns an acresponse
|
31
|
+
|
32
|
+
api - update: elements list should not contain directories
|
33
|
+
|
34
|
+
api - update: elements list should probably not include removed files
|
35
|
+
|
36
|
+
# command - Command.working_dir is bad: should use with_working_dir()
|
37
|
+
|
38
|
+
*** api - checkout() should use `pop` instead of `mkws`, unless
|
39
|
+
user *really* wants it
|
40
|
+
|
41
|
+
|
data/lib/rscm/accurev.rb
CHANGED
@@ -5,3 +5,13 @@ require 'rscm/scm/accurev/command'
|
|
5
5
|
require 'rscm/scm/accurev/xml'
|
6
6
|
require 'rscm/scm/accurev/filterio'
|
7
7
|
|
8
|
+
module RSCM
|
9
|
+
#
|
10
|
+
# == module RSCM::Accurev
|
11
|
+
#
|
12
|
+
# Namespace for accurev api classes and utils.
|
13
|
+
#
|
14
|
+
# See RSCM::Accurev::API.
|
15
|
+
#
|
16
|
+
module Accurev; end
|
17
|
+
end
|
data/lib/rscm/scm/accurev/api.rb
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
+
#
|
3
|
+
# = api.rb
|
4
|
+
#
|
5
|
+
# API for interacting with accurev workspaces.
|
6
|
+
#
|
7
|
+
require 'stringio'
|
2
8
|
require 'rubygems'
|
3
9
|
require 'rscm/base'
|
4
10
|
require 'rscm/path_converter'
|
@@ -7,12 +13,16 @@ require 'rscm/scm/accurev/xml'
|
|
7
13
|
require 'rscm/scm/accurev/filterio'
|
8
14
|
require 'rscm/scm/accurev/command'
|
9
15
|
|
10
|
-
module
|
11
|
-
|
12
|
-
end
|
16
|
+
# need to define module within module before you can use module X::Y
|
17
|
+
module RSCM; module Accurev; end; end
|
13
18
|
|
14
19
|
module RSCM::Accurev
|
15
20
|
|
21
|
+
#
|
22
|
+
# General exception class for errors processing commands.
|
23
|
+
#
|
24
|
+
# @attr error_msg Error message output by accurev.
|
25
|
+
#
|
16
26
|
class AccurevException < Exception
|
17
27
|
attr_reader :error_msg
|
18
28
|
def initialize( msg, error_msg=nil )
|
@@ -21,12 +31,29 @@ module RSCM::Accurev
|
|
21
31
|
end
|
22
32
|
end
|
23
33
|
|
34
|
+
#
|
35
|
+
# Exception thrown when an update is performed
|
36
|
+
# on a workspace with unkept/unanchored modifications.
|
37
|
+
# Accurev requires that all modifications be handled before
|
38
|
+
# an update is performed.
|
39
|
+
#
|
24
40
|
class StaleWorkspaceException < AccurevException; end
|
25
41
|
|
26
|
-
# RSCM implementation for Accurev (http://www.accurev.com/).
|
27
42
|
#
|
28
|
-
#
|
29
|
-
#
|
43
|
+
# RSCM implementation for Accurev (http://www.accurev.com).
|
44
|
+
#
|
45
|
+
# Requires an accurev cli executable on the path (see also
|
46
|
+
# RSCM::Accurev::Command), and the correct environment
|
47
|
+
# configuration for ac server/principal/password.
|
48
|
+
#
|
49
|
+
# ---
|
50
|
+
#
|
51
|
+
# === Example
|
52
|
+
#
|
53
|
+
# api = RSCM::Accurev::API.new( "./ws/proj-1", "proj", "proj-1" )
|
54
|
+
# api.checkout() each do |file|
|
55
|
+
# puts "Updated #{file}..."
|
56
|
+
# end
|
30
57
|
#
|
31
58
|
class API < RSCM::Base
|
32
59
|
register self
|
@@ -40,20 +67,21 @@ module RSCM::Accurev
|
|
40
67
|
ann :description => "Workspace Stream"
|
41
68
|
attr_accessor :workspace_stream
|
42
69
|
|
43
|
-
# defined in Base
|
44
|
-
#
|
45
|
-
#
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
70
|
+
# [defined in Base]
|
71
|
+
# ann :description => "Filesystem Path to Workspace"
|
72
|
+
# attr_accessor :checkout_dir
|
73
|
+
|
74
|
+
# status flag mappings for "stat", "file" commands
|
75
|
+
STATUSES = {
|
76
|
+
'(backed)' => :backed,
|
77
|
+
'(external)' => :external,
|
78
|
+
'(modified)' => :modified,
|
79
|
+
'(kept)' => :kept,
|
80
|
+
'(defunct)' => :defunct,
|
81
|
+
'(missing)' => :missing,
|
82
|
+
'(stranded)' => :stranded,
|
83
|
+
'(overlap)' => :overlap
|
84
|
+
}
|
57
85
|
|
58
86
|
def initialize( checkout_dir=nil, depot=nil, workspace_stream=nil )
|
59
87
|
@depot = depot
|
@@ -66,7 +94,7 @@ module RSCM::Accurev
|
|
66
94
|
return "Accurev"
|
67
95
|
end
|
68
96
|
|
69
|
-
# Accurev operations are atomic:
|
97
|
+
# Accurev operations are atomic: returns true.
|
70
98
|
def transactional?
|
71
99
|
return true
|
72
100
|
end
|
@@ -105,10 +133,12 @@ module RSCM::Accurev
|
|
105
133
|
def ac_files( relative_path )
|
106
134
|
cmd = Command.instance
|
107
135
|
ret = []
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
136
|
+
with_working_dir( @checkout_dir ) do
|
137
|
+
acresponse = cmd.accurev( "files", relative_path )
|
138
|
+
acresponse['element'].each do |fd|
|
139
|
+
yield fd if block_given?
|
140
|
+
ret << fd
|
141
|
+
end
|
112
142
|
end
|
113
143
|
return ret
|
114
144
|
end
|
@@ -140,9 +170,32 @@ module RSCM::Accurev
|
|
140
170
|
raise "XXX implement me"
|
141
171
|
end
|
142
172
|
|
173
|
+
#
|
174
|
+
# Performs an "accurev info" command in the workspace.
|
175
|
+
# Returns a map of
|
176
|
+
#
|
143
177
|
# ac info: shows eg, backing stream
|
144
|
-
# but doesn't support -fx!
|
145
|
-
|
178
|
+
# but doesn't support -fx!
|
179
|
+
#
|
180
|
+
def ac_info()
|
181
|
+
co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
182
|
+
unless File.exists?( co )
|
183
|
+
raise AccurevException.new( "Checkout dir does not exist" )
|
184
|
+
end
|
185
|
+
info = {}
|
186
|
+
with_working_dir( co ) do
|
187
|
+
cmd = Command.instance
|
188
|
+
io = StringIO.new( cmd.accurev_nofx( "info" ) )
|
189
|
+
io.each_line do |line|
|
190
|
+
next unless line =~ /\S/
|
191
|
+
if line =~ /^(.*?):\s+(.*)$/
|
192
|
+
info[$1] = $2
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
return info
|
197
|
+
end
|
198
|
+
|
146
199
|
# ac mkws
|
147
200
|
# -b orbitz-host-gt3-0-impl
|
148
201
|
# -w orbitz-host-gt3-0-impl-test2_gfast
|
@@ -156,7 +209,7 @@ module RSCM::Accurev
|
|
156
209
|
# (eg, no in-process diffing ala cvs diff)
|
157
210
|
# lists modified lines in xml
|
158
211
|
|
159
|
-
#
|
212
|
+
#
|
160
213
|
# "Checks out or updates[!] contents from a central SCM
|
161
214
|
# to +checkout_dir+ - a local working copy."
|
162
215
|
#
|
@@ -164,20 +217,21 @@ module RSCM::Accurev
|
|
164
217
|
# obtain files up to a particular time or label."
|
165
218
|
#
|
166
219
|
# For accurev, this:
|
167
|
-
# * checks to see if
|
168
|
-
# If it's already checked out, this calls update()
|
220
|
+
# * checks to see if +@checkout_dir+ exists and appears checked out.
|
221
|
+
# If it's already checked out, this calls +update()+. If
|
222
|
+
# +@checkout_dir+ exists and +to_identifier+ is given, an
|
223
|
+
# exception is raised.
|
169
224
|
# * otherwise, this creates a new workspace stream and populates it
|
170
|
-
# at
|
225
|
+
# at +@checkout_dir+.
|
171
226
|
#
|
172
|
-
#
|
227
|
+
# This both returns and yields a list of updated files.
|
228
|
+
# Only updated files are returned, not directories.
|
229
|
+
#
|
230
|
+
# Current, ac_update returns both files and directories, including
|
231
|
+
# deleted files.
|
173
232
|
#
|
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
|
179
233
|
def checkout( to_identifier=Time.infinite )
|
180
|
-
co = PathConverter.nativepath_to_filepath( @checkout_dir )
|
234
|
+
co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
181
235
|
unless File.exists?( co )
|
182
236
|
puts "> creating new workspace..."
|
183
237
|
if @backing_stream.nil?
|
@@ -186,13 +240,16 @@ module RSCM::Accurev
|
|
186
240
|
if @workspace_stream.nil?
|
187
241
|
raise "Workspace stream must be set"
|
188
242
|
end
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
243
|
+
Command.instance do |cmd|
|
244
|
+
cmd.working_dir = co
|
245
|
+
mkws_out = cmd.accurev_nofx( "mkws",
|
246
|
+
"-b", @backing_stream,
|
247
|
+
"-w", @workspace_stream,
|
248
|
+
"-l", co )
|
249
|
+
# sucks:
|
250
|
+
if ( mkws_out =~ /already exists/ )
|
251
|
+
raise AccurevException.new( "Failed to checkout", mkws_out )
|
252
|
+
end
|
196
253
|
end
|
197
254
|
end
|
198
255
|
puts "> Updating workspace.."
|
@@ -205,8 +262,8 @@ module RSCM::Accurev
|
|
205
262
|
raise AccurevException.new( "Workspace does not exist!" )
|
206
263
|
end
|
207
264
|
updated = []
|
208
|
-
|
209
|
-
cmd
|
265
|
+
with_working_dir( co ) do
|
266
|
+
cmd = Command.instance
|
210
267
|
acresponse = cmd.accurev( "update" )
|
211
268
|
if acresponse.error
|
212
269
|
if acresponse.error =~ /workspace have been modified/
|
@@ -219,8 +276,12 @@ module RSCM::Accurev
|
|
219
276
|
end
|
220
277
|
if acresponse['element']
|
221
278
|
acresponse['element'].each do |up|
|
222
|
-
|
223
|
-
|
279
|
+
# "ac update" on a new workspace yields element locations
|
280
|
+
# with leading "/"s, which should be removed to get a proper
|
281
|
+
# relative path:
|
282
|
+
loc = up.location.sub( /^\//, "" )
|
283
|
+
yield loc if block_given?
|
284
|
+
updated << loc
|
224
285
|
end
|
225
286
|
end
|
226
287
|
end
|
@@ -240,3 +301,7 @@ module RSCM::Accurev
|
|
240
301
|
end
|
241
302
|
|
242
303
|
end
|
304
|
+
|
305
|
+
#
|
306
|
+
# Copyright (c) 2005 Gregory D. Fast <gdf@speakeasy.net>
|
307
|
+
#
|
@@ -10,7 +10,7 @@ module RSCM
|
|
10
10
|
#
|
11
11
|
class Command
|
12
12
|
|
13
|
-
attr_accessor :debug, :debug_to, :accurev_bin
|
13
|
+
attr_accessor :debug, :debug_to, :accurev_bin
|
14
14
|
|
15
15
|
# If you need to swap out the mapper class
|
16
16
|
attr_accessor :xmlmapper
|
@@ -20,7 +20,6 @@ module RSCM
|
|
20
20
|
@debug = false
|
21
21
|
@debug_to = STDOUT
|
22
22
|
@accurev_bin = "accurev"
|
23
|
-
@working_dir = "."
|
24
23
|
end
|
25
24
|
|
26
25
|
#
|
@@ -41,10 +40,10 @@ module RSCM
|
|
41
40
|
# `-fx` for xml output.)
|
42
41
|
#
|
43
42
|
def accurev_nofx( cmd, *opts )
|
44
|
-
# nativepath_to_filepath is actually generic to native
|
45
|
-
dir = PathConverter.nativepath_to_filepath( @working_dir )
|
46
|
-
dir = File.expand_path( dir )
|
47
|
-
with_working_dir( dir ) do
|
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
|
48
47
|
cmdline = self.accurev_cmdline( cmd, opts )
|
49
48
|
if @debug
|
50
49
|
@debug_to.puts("ac> #{cmdline}")
|
@@ -52,7 +51,7 @@ module RSCM
|
|
52
51
|
Better.popen( cmdline ) do |stdout|
|
53
52
|
return stdout.read()
|
54
53
|
end
|
55
|
-
end
|
54
|
+
## end
|
56
55
|
end
|
57
56
|
|
58
57
|
#
|
@@ -67,11 +66,11 @@ module RSCM
|
|
67
66
|
# accurev subcommands support the "-fx" option.
|
68
67
|
#
|
69
68
|
def accurev_xml( cmd, *opts )
|
70
|
-
# nativepath_to_filepath is actually generic to native
|
71
|
-
dir = PathConverter.nativepath_to_filepath( @working_dir )
|
72
|
-
dir = File.expand_path( dir )
|
73
69
|
opts << "-fx"
|
74
|
-
|
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
|
75
74
|
cmdline = self.accurev_cmdline( cmd, opts )
|
76
75
|
if @debug
|
77
76
|
@debug_to.puts("ac> #{cmdline}")
|
@@ -88,7 +87,7 @@ module RSCM
|
|
88
87
|
raise "Unexpected output from #{cmdline}: #{e}"
|
89
88
|
end
|
90
89
|
end
|
91
|
-
end
|
90
|
+
## end
|
92
91
|
end
|
93
92
|
|
94
93
|
#
|
@@ -3,17 +3,19 @@ require 'stringio'
|
|
3
3
|
module RSCM
|
4
4
|
module Accurev
|
5
5
|
|
6
|
+
#
|
6
7
|
# IO stream which cleans irregularities out of accurev xml output.
|
7
8
|
#
|
8
9
|
# In particular:
|
9
10
|
#
|
10
|
-
#
|
11
|
-
#
|
11
|
+
# * Unlike other commands, the +-fx+ output from _accurev update_
|
12
|
+
# has a root element of +<acResponse>+, not +<AcResponse>+.
|
12
13
|
#
|
13
|
-
#
|
14
|
-
#
|
14
|
+
# * _accurev update_ emits broken XML when there are no files
|
15
|
+
# to update.
|
15
16
|
#
|
16
17
|
class AcXMLScrubIO < StringIO
|
18
|
+
|
17
19
|
# @param: sourceio - io or string source to wrap
|
18
20
|
def initialize( sourceio )
|
19
21
|
if sourceio.respond_to?( :read )
|
data/lib/rscm/scm/accurev/xml.rb
CHANGED
@@ -11,9 +11,11 @@ module RSCM::Accurev
|
|
11
11
|
# and builds a new object of that type from the element.
|
12
12
|
#
|
13
13
|
# The nodename-class associations are determined by finding all
|
14
|
-
# classes derived from
|
14
|
+
# classes derived from ElementBackedClass and checking
|
15
15
|
# each of those classes +element_name+ methods.
|
16
16
|
#
|
17
|
+
# See ElementBackedClass for examples.
|
18
|
+
#
|
17
19
|
class XMLMapper
|
18
20
|
|
19
21
|
# Map of element (tag) names to (ruby) class.
|
@@ -55,19 +57,47 @@ module RSCM::Accurev
|
|
55
57
|
end
|
56
58
|
|
57
59
|
#
|
58
|
-
#
|
60
|
+
# Abstract base class for defining typed mirror classes for XML elements.
|
59
61
|
#
|
60
62
|
# A subclass of ElementBackedClass has:
|
61
63
|
#
|
62
|
-
#
|
63
|
-
#
|
64
|
+
# * A class static +element_name+ method, identifying what
|
65
|
+
# type of XML element it shadows
|
66
|
+
#
|
67
|
+
# * A set of attributes shadowing the XML attributes of its target element
|
68
|
+
#
|
69
|
+
# * A map (+children+) of child elements, keyed by element name
|
70
|
+
#
|
71
|
+
# * A (optional) +text_content+ attribute, populated when the
|
72
|
+
# target element has text subnodes.
|
73
|
+
#
|
74
|
+
# ---
|
75
|
+
#
|
76
|
+
# === Example
|
77
|
+
#
|
78
|
+
# For the XML element:
|
79
|
+
#
|
80
|
+
# <book title="The Monkey Wrench Gang" author="Edward Albee">
|
81
|
+
# <note>Lots of beer and dynamite</note>
|
82
|
+
# </book>
|
83
|
+
#
|
84
|
+
# You can define:
|
64
85
|
#
|
65
|
-
#
|
86
|
+
# class Book < ElementBackedClass
|
87
|
+
# element_name 'book'
|
88
|
+
# attr_accessor :title, :author
|
89
|
+
# end
|
66
90
|
#
|
67
|
-
#
|
91
|
+
# And then use XMLMapper to create instances:
|
68
92
|
#
|
69
|
-
#
|
70
|
-
#
|
93
|
+
# e = ...; # <book> node: REXML::Element
|
94
|
+
# book = XMLMapper.map(e)
|
95
|
+
# puts "Title: #{book.title}"
|
96
|
+
# puts "Author: #{book.author}"
|
97
|
+
# puts "Notes:"
|
98
|
+
# book['note'].each do |n|
|
99
|
+
# puts n.text_content
|
100
|
+
# end
|
71
101
|
#
|
72
102
|
class ElementBackedClass
|
73
103
|
|
@@ -0,0 +1,165 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'test/unit/ui/testrunnermediator'
|
4
|
+
require 'test/unit/ui/testrunnerutilities'
|
5
|
+
require 'test/unit/ui/console/testrunner'
|
6
|
+
require 'test/unit/autorunner'
|
7
|
+
require 'rexml/document'
|
8
|
+
|
9
|
+
module Test
|
10
|
+
module Unit
|
11
|
+
module UI
|
12
|
+
module XML
|
13
|
+
|
14
|
+
#
|
15
|
+
# XML::TestRunner - generate xml output for test results
|
16
|
+
#
|
17
|
+
# Example use:
|
18
|
+
#
|
19
|
+
# $ ruby -rtest/unit/ui/xml/testrunner test/test_1.rb --runner=xml
|
20
|
+
#
|
21
|
+
# By default, XML::TestRunner will output to stdout.
|
22
|
+
# You can set the environment variable $XMLTEST_OUTPUT to
|
23
|
+
# a filename to send the output to that file.
|
24
|
+
#
|
25
|
+
# The summary file created by this testrunner is XML, but
|
26
|
+
# this module also includes a stylesheet
|
27
|
+
# (test/unit/ui/xml/xmltestrunner.xslt) which converts it to
|
28
|
+
# HTML. Copy the XSLT file into the same directory as the
|
29
|
+
# test results file, and open the results file with a browser.
|
30
|
+
#
|
31
|
+
# ---
|
32
|
+
#
|
33
|
+
# (todo: use with rake)
|
34
|
+
#
|
35
|
+
class TestRunner < Test::Unit::UI::Console::TestRunner
|
36
|
+
|
37
|
+
def initialize( suite, output_level )
|
38
|
+
super( suite )
|
39
|
+
if ENV['XMLTEST_OUTPUT']
|
40
|
+
fn = ENV['XMLTEST_OUTPUT']
|
41
|
+
puts "Writing to #{fn}"
|
42
|
+
@io = File.open( fn, "w" )
|
43
|
+
@using_stdout = false
|
44
|
+
else
|
45
|
+
puts "Writing to stdout (along with everyone else...)"
|
46
|
+
@io = STDOUT
|
47
|
+
@using_stdout = true
|
48
|
+
end
|
49
|
+
create_document()
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_document()
|
53
|
+
@doc = REXML::Document.new()
|
54
|
+
@doc << REXML::XMLDecl.new()
|
55
|
+
|
56
|
+
pi = REXML::Instruction.new(
|
57
|
+
"xml-stylesheet",
|
58
|
+
"type='text/xsl' href='xmltestrunner.xslt' "
|
59
|
+
)
|
60
|
+
@doc << pi
|
61
|
+
|
62
|
+
e = REXML::Element.new( "testsuite" )
|
63
|
+
e.attributes['rundate'] = Time.now
|
64
|
+
@doc << e
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_s
|
68
|
+
@doc.to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
def start
|
72
|
+
@current_test = nil
|
73
|
+
# setup_mediator
|
74
|
+
@mediator = TestRunnerMediator.new( @suite )
|
75
|
+
suite_name = @suite.to_s
|
76
|
+
if @suite.kind_of?(Module)
|
77
|
+
suite_name = @suite.name
|
78
|
+
end
|
79
|
+
@doc.root.attributes['name'] = suite_name
|
80
|
+
# attach_to_mediator - define callbacks
|
81
|
+
@mediator.add_listener( TestResult::FAULT,
|
82
|
+
&method(:add_fault) )
|
83
|
+
@mediator.add_listener( TestRunnerMediator::STARTED,
|
84
|
+
&method(:started) )
|
85
|
+
@mediator.add_listener( TestRunnerMediator::FINISHED,
|
86
|
+
&method(:finished) )
|
87
|
+
@mediator.add_listener( TestCase::STARTED,
|
88
|
+
&method(:test_started) )
|
89
|
+
@mediator.add_listener( TestCase::FINISHED,
|
90
|
+
&method(:test_finished) )
|
91
|
+
# return start_mediator
|
92
|
+
return @mediator.run_suite
|
93
|
+
end
|
94
|
+
|
95
|
+
# callbacks
|
96
|
+
|
97
|
+
def add_fault( fault )
|
98
|
+
##STDERR.puts "Fault:"
|
99
|
+
@faults << fault
|
100
|
+
e = REXML::Element.new( "fault" )
|
101
|
+
e << REXML::CData.new( fault.long_display )
|
102
|
+
@current_test << e
|
103
|
+
end
|
104
|
+
|
105
|
+
def started( result )
|
106
|
+
#STDERR.puts "Started"
|
107
|
+
@result = result
|
108
|
+
end
|
109
|
+
|
110
|
+
def finished( elapsed_time )
|
111
|
+
#STDERR.puts "Finished"
|
112
|
+
res = REXML::Element.new( "result" )
|
113
|
+
summ = REXML::Element.new( "summary" )
|
114
|
+
summ.text = @result
|
115
|
+
res << summ
|
116
|
+
# @result is a Test::Unit::TestResults
|
117
|
+
res.attributes['passed'] = @result.passed?
|
118
|
+
res.attributes['testcount'] = @result.run_count
|
119
|
+
res.attributes['assertcount'] = @result.assertion_count
|
120
|
+
res.attributes['failures'] = @result.failure_count
|
121
|
+
res.attributes['errors'] = @result.error_count
|
122
|
+
@doc.root << res
|
123
|
+
|
124
|
+
e = REXML::Element.new( "elapsed-time" )
|
125
|
+
e.text = elapsed_time
|
126
|
+
@doc.root << e
|
127
|
+
@io.puts( @doc.to_s )
|
128
|
+
|
129
|
+
unless @using_stdout
|
130
|
+
puts @result
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_started( name )
|
135
|
+
#STDERR.puts "Test: #{name} started"
|
136
|
+
e = REXML::Element.new( "test" )
|
137
|
+
e.attributes['name'] = name
|
138
|
+
#e.attributes['status'] = "failed"
|
139
|
+
@doc.root << e
|
140
|
+
@current_test = e
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_finished( name )
|
144
|
+
#STDERR.puts "Test: #{name} finished"
|
145
|
+
# find //test[@name='name']
|
146
|
+
@current_test = nil
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# "plug in" xmltestrunner into autorunner's list of known runners
|
156
|
+
# This enables the "--runner=xml" commandline option.
|
157
|
+
Test::Unit::AutoRunner::RUNNERS[:xml] = proc do |r|
|
158
|
+
require 'test/unit/ui/xml/testrunner'
|
159
|
+
Test::Unit::UI::XML::TestRunner
|
160
|
+
end
|
161
|
+
|
162
|
+
if __FILE__ == $0
|
163
|
+
Test::Unit::UI::XML::TestRunner.start_command_line_test
|
164
|
+
end
|
165
|
+
|
@@ -0,0 +1,79 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<xsl:stylesheet
|
3
|
+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
4
|
+
>
|
5
|
+
|
6
|
+
<xsl:output method="html" />
|
7
|
+
|
8
|
+
<xsl:template match="/testsuite">
|
9
|
+
<html>
|
10
|
+
<head>
|
11
|
+
<title>Test Suite Results for <xsl:value-of select="@name" /></title>
|
12
|
+
<style>
|
13
|
+
.error { color: #ff0000; }
|
14
|
+
.eresult {
|
15
|
+
background: #ffcccc;
|
16
|
+
color: #ff0000;
|
17
|
+
}
|
18
|
+
h1,h2 {
|
19
|
+
background: #cccccc;
|
20
|
+
color: #000055;
|
21
|
+
border: 1px dotted black;
|
22
|
+
}
|
23
|
+
</style>
|
24
|
+
</head>
|
25
|
+
<body>
|
26
|
+
<h1>Test Suite Results</h1>
|
27
|
+
|
28
|
+
<p>Results for: <xsl:value-of select="@name" /></p>
|
29
|
+
|
30
|
+
<p>
|
31
|
+
Test suite run at: <b><xsl:value-of select="@rundate" /></b>
|
32
|
+
</p>
|
33
|
+
|
34
|
+
<h2>Summary</h2>
|
35
|
+
|
36
|
+
<p>
|
37
|
+
<xsl:if test="result[@passed = 'false']">
|
38
|
+
<xsl:attribute name="class">error</xsl:attribute>
|
39
|
+
</xsl:if>
|
40
|
+
<xsl:value-of select="result/summary/text()" />
|
41
|
+
</p>
|
42
|
+
<p>
|
43
|
+
Elapsed time: <xsl:value-of select="elapsed-time/text()" />
|
44
|
+
</p>
|
45
|
+
|
46
|
+
<table border="1">
|
47
|
+
<tr>
|
48
|
+
<th>Case</th>
|
49
|
+
<th>Result</th>
|
50
|
+
</tr>
|
51
|
+
<xsl:for-each select="test">
|
52
|
+
<tr>
|
53
|
+
<td>
|
54
|
+
<xsl:if test="fault/text()">
|
55
|
+
<xsl:attribute name="class">error</xsl:attribute>
|
56
|
+
</xsl:if>
|
57
|
+
<xsl:value-of select="@name" />
|
58
|
+
</td>
|
59
|
+
<td>
|
60
|
+
<xsl:choose>
|
61
|
+
<xsl:when test="fault/text()">
|
62
|
+
<xsl:attribute name="class">eresult</xsl:attribute>
|
63
|
+
<pre>
|
64
|
+
<xsl:value-of select="fault/text()" />
|
65
|
+
</pre>
|
66
|
+
</xsl:when>
|
67
|
+
<xsl:otherwise>
|
68
|
+
(pass)
|
69
|
+
</xsl:otherwise>
|
70
|
+
</xsl:choose>
|
71
|
+
</td>
|
72
|
+
</tr>
|
73
|
+
</xsl:for-each>
|
74
|
+
</table>
|
75
|
+
</body>
|
76
|
+
</html>
|
77
|
+
</xsl:template>
|
78
|
+
|
79
|
+
</xsl:stylesheet>
|
data/test/eg/info.txt
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
Principal: gfast
|
3
|
+
Shell: /bin/zsh
|
4
|
+
Host: gfast.duncllc.com
|
5
|
+
Domain: (none)
|
6
|
+
server_name: accurev.duncllc.com
|
7
|
+
port: 5050
|
8
|
+
ACCUREV_BIN: /usr/local/accurev/bin
|
9
|
+
client_time: 2005/08/16 08:56:13 CDT (1124200573)
|
10
|
+
server_time: 2005/08/16 08:56:14 CDT (1124200574)
|
11
|
+
Depot: orbitz-api-hiredcar
|
12
|
+
ws/ref: orbitz-api-hiredcar-0-rc-testing_gfast
|
13
|
+
Basis: orbitz-api-hiredcar-1-rc
|
14
|
+
Top: /home/gfast/dev/orbitz-api-hirdcar-0-rc
|
data/test/t_api.rb
CHANGED
@@ -7,11 +7,10 @@ include RSCM::Accurev
|
|
7
7
|
class AccurevAPITest < Test::Unit::TestCase
|
8
8
|
|
9
9
|
def test_ac_files()
|
10
|
-
Command.instance do |cmd|
|
11
|
-
cmd.working_dir = "test"
|
10
|
+
Command.instance do |cmd|
|
12
11
|
cmd.accurev_bin = "./acreplay.rb eg/ac-files.xml"
|
13
12
|
end
|
14
|
-
api = API.new( "
|
13
|
+
api = API.new( "test", "test-bogus-depot", "test-bogus-depot-0-impl" )
|
15
14
|
# test array returns
|
16
15
|
files = api.ac_files( "." )
|
17
16
|
assert( files.length > 0, "Should get some stat-ed files" )
|
@@ -62,15 +61,61 @@ class AccurevAPITest < Test::Unit::TestCase
|
|
62
61
|
assert_equal( 44, u_elements.length )
|
63
62
|
u_elements.each do |location|
|
64
63
|
# api.update returns a list of relative filenames
|
65
|
-
assert( location =~
|
64
|
+
assert( location =~ /^[^\/]/, "Location '#{location}' should be a relpath" )
|
66
65
|
end
|
67
66
|
# test yield and array return XXX
|
68
67
|
updated = 0
|
69
68
|
api.update().each do |location|
|
70
69
|
updated += 1
|
71
|
-
assert( location =~
|
70
|
+
assert( location =~ /^[^\/]/, "Location '#{location}' should be a relpath" )
|
72
71
|
end
|
73
72
|
assert_equal( 44, updated )
|
74
73
|
end
|
75
74
|
|
75
|
+
# update-updates.xml - update with updated files
|
76
|
+
def test_update_updates()
|
77
|
+
Command.instance do |cmd|
|
78
|
+
cmd.accurev_bin = "./acreplay.rb eg/update-updates.xml"
|
79
|
+
end
|
80
|
+
api = API.new( "test", "test-bogus-depot", "test-bogus-depot-0-impl" )
|
81
|
+
# XXX elements in elements list are just "modified" -
|
82
|
+
# may have been removed!
|
83
|
+
# XXX update() should return only filenames, right? eliminate dirs
|
84
|
+
ue = api.update()
|
85
|
+
assert_not_nil( ue )
|
86
|
+
assert_equal( 23, ue.length )
|
87
|
+
ue.each do |location|
|
88
|
+
assert( location =~ /^[^\/]/, "Location '#{location}' should be a relpath" )
|
89
|
+
end
|
90
|
+
# yielding behavior
|
91
|
+
updated = 0
|
92
|
+
api.update().each do |location|
|
93
|
+
updated += 1
|
94
|
+
assert( location =~ /^[^\/]/, "Location '#{location}' should be a relpath" )
|
95
|
+
end
|
96
|
+
assert_equal( 23, updated )
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_info()
|
100
|
+
Command.instance do |cmd|
|
101
|
+
cmd.accurev_bin = "./acreplay.rb eg/info.txt"
|
102
|
+
end
|
103
|
+
api = API.new( "test", "depot", "stream" )
|
104
|
+
info = api.ac_info()
|
105
|
+
assert( info.size == 13 )
|
106
|
+
# some crap
|
107
|
+
assert_equal( "gfast", info['Principal'] )
|
108
|
+
assert_equal( "5050", info['port'] )
|
109
|
+
assert_equal( "/usr/local/accurev/bin", info['ACCUREV_BIN'] )
|
110
|
+
# the interesting stuff:
|
111
|
+
# - depot name
|
112
|
+
assert_equal( "orbitz-api-hiredcar", info['Depot'] )
|
113
|
+
# - workspace or reference stream name
|
114
|
+
assert_equal( "orbitz-api-hiredcar-0-rc-testing_gfast", info['ws/ref'] )
|
115
|
+
# - basis stream name
|
116
|
+
assert_equal( "orbitz-api-hiredcar-1-rc", info['Basis'] )
|
117
|
+
# - workspace checkout location
|
118
|
+
assert_equal( "/home/gfast/dev/orbitz-api-hirdcar-0-rc", info['Top'] )
|
119
|
+
end
|
120
|
+
|
76
121
|
end
|
data/test/t_command.rb
CHANGED
@@ -23,18 +23,20 @@ class CommandTest < Test::Unit::TestCase
|
|
23
23
|
|
24
24
|
def test_a_e
|
25
25
|
cmd = Command.instance
|
26
|
-
cmd.working_dir = "test"
|
26
|
+
## cmd.working_dir = "test"
|
27
27
|
cmd.debug = true
|
28
28
|
cmd.debug_to = File.open( "/tmp/testing.log", "w" )
|
29
29
|
cmd.accurev_bin = "./acreplay.rb eg/update-newwksp.xml"
|
30
30
|
# test listy output
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
31
|
+
with_working_dir( "test" ) do
|
32
|
+
acresponse = cmd.accurev( "files" )
|
33
|
+
assert_not_nil( acresponse )
|
34
|
+
assert( acresponse.kind_of?( AcResponseData ) )
|
35
|
+
assert( acresponse['element'].size == 44 )
|
36
|
+
assert( acresponse['message'].size == 44 )
|
37
|
+
acresponse['element'].each do |e|
|
38
|
+
assert( e.kind_of?( ElementData ) )
|
39
|
+
end
|
38
40
|
end
|
39
41
|
Command.discard
|
40
42
|
end
|
@@ -52,29 +54,29 @@ class CommandTest < Test::Unit::TestCase
|
|
52
54
|
# instance returns this thread's Command object
|
53
55
|
begin
|
54
56
|
cmd = Command.instance
|
55
|
-
cmd.
|
56
|
-
assert_equal( cmd.
|
57
|
+
cmd.accurev_bin = "/bin/bash"
|
58
|
+
assert_equal( cmd.accurev_bin, "/bin/bash" )
|
57
59
|
end
|
58
60
|
# and calling it again returns the same object
|
59
61
|
begin
|
60
62
|
cmd = Command.instance
|
61
|
-
assert_equal( cmd.
|
63
|
+
assert_equal( cmd.accurev_bin, "/bin/bash" )
|
62
64
|
end
|
63
65
|
# but instance in another thread should be different
|
64
66
|
Thread.new do
|
65
67
|
cmd = Command.instance
|
66
|
-
assert_not_equal( cmd.
|
68
|
+
assert_not_equal( cmd.accurev_bin, "/bin/bash" )
|
67
69
|
end.join()
|
68
70
|
# ...and calling it *again* returns the same object
|
69
71
|
begin
|
70
72
|
cmd = Command.instance
|
71
|
-
assert_equal( cmd.
|
73
|
+
assert_equal( cmd.accurev_bin, "/bin/bash" )
|
72
74
|
end
|
73
75
|
# but discard tosses this thread's object:
|
74
76
|
Command.discard
|
75
77
|
begin
|
76
78
|
cmd = Command.instance
|
77
|
-
assert_not_equal( cmd.
|
79
|
+
assert_not_equal( cmd.accurev_bin, "/bin/bash" )
|
78
80
|
end
|
79
81
|
|
80
82
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: rscm-accurev
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
7
|
-
date: 2005-08-
|
6
|
+
version: 0.0.4
|
7
|
+
date: 2005-08-21 00:00:00 -05:00
|
8
8
|
summary: "RSCM::Accurev - RSCM API for Accurev"
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -31,15 +31,17 @@ authors:
|
|
31
31
|
files:
|
32
32
|
- apitest.rb
|
33
33
|
- bumprelease.sh
|
34
|
+
- doc
|
34
35
|
- lib
|
35
36
|
- LICENSE
|
36
|
-
- pkg
|
37
37
|
- Rakefile
|
38
38
|
- README
|
39
|
+
- STATUS
|
39
40
|
- test
|
40
41
|
- tmp
|
41
42
|
- TODO
|
42
43
|
- lib/rscm
|
44
|
+
- lib/test
|
43
45
|
- lib/rscm/accurev.rb
|
44
46
|
- lib/rscm/scm
|
45
47
|
- lib/rscm/scm/accurev
|
@@ -47,6 +49,11 @@ files:
|
|
47
49
|
- lib/rscm/scm/accurev/command.rb
|
48
50
|
- lib/rscm/scm/accurev/filterio.rb
|
49
51
|
- lib/rscm/scm/accurev/xml.rb
|
52
|
+
- lib/test/unit
|
53
|
+
- lib/test/unit/ui
|
54
|
+
- lib/test/unit/ui/xml
|
55
|
+
- lib/test/unit/ui/xml/testrunner.rb
|
56
|
+
- lib/test/unit/ui/xml/xmltestrunner.xslt
|
50
57
|
- test/acreplay.rb
|
51
58
|
- test/eg
|
52
59
|
- test/t_api.rb
|
@@ -56,6 +63,7 @@ files:
|
|
56
63
|
- test/t_scrubio.rb
|
57
64
|
- test/t_xmlmapper.rb
|
58
65
|
- test/eg/ac-files.xml
|
66
|
+
- test/eg/info.txt
|
59
67
|
- test/eg/update-i-nochanges.xml
|
60
68
|
- test/eg/update-i-updates.xml
|
61
69
|
- test/eg/update-newwksp.xml
|