rscm-accurev 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|