rscm-accurev 0.0.4 → 0.0.6
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 +55 -8
- data/TODO +1 -1
- data/bumprelease.sh +3 -0
- data/lib/rscm/accurev.rb +3 -2
- data/lib/rscm/scm/accurev/api.rb +181 -71
- data/lib/rscm/scm/accurev/exception.rb +38 -0
- data/lib/rscm/scm/accurev/xml.rb +42 -0
- data/test/coverage/analyzer.rb +127 -0
- data/test/coverage/c_loader.rb +34 -0
- data/test/coverage/cover.rb +91 -0
- data/test/coverage/coverage_loader.rb +21 -0
- data/test/coverage/coveragetask.rb +38 -0
- data/test/coverage/index_tmpl.html +42 -0
- data/test/coverage/template.html +36 -0
- data/test/eg/ac-files.xml +39 -39
- data/test/eg/ac-pop.txt +195 -0
- data/test/eg/files-various-states.xml +188 -0
- data/test/eg/hist-oneweek-all.xml +1483 -0
- data/test/eg/hist-oneweek-external.xml +246 -0
- data/test/eg/hist-oneweek-promotes.xml +1092 -0
- data/test/eg/info.txt +7 -7
- data/test/eg/stat-a-various.xml +1789 -0
- data/test/eg/stat-m.xml +13 -0
- data/test/eg/stat-overlap.xml +13 -0
- data/test/eg/stat-x.xml +20 -0
- data/test/eg/update-i-mods-and-updates-and-overlap.xml +73 -0
- data/test/eg/update-i-updates.xml +46 -46
- data/test/eg/update-newwksp.xml +88 -88
- data/test/eg/update-updates.xml +46 -46
- data/test/fl +18 -0
- data/test/suite_all.rb +34 -0
- data/test/t_api.rb +47 -5
- data/test/t_command.rb +1 -0
- data/test/t_load.rb +1 -0
- data/test/t_rscm.rb +26 -0
- data/test/t_scrubio.rb +1 -0
- data/test/t_xmlmapper.rb +1 -0
- metadata +25 -3
- data/apitest.rb +0 -21
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
#
|
3
|
+
# = exception.rb
|
4
|
+
#
|
5
|
+
# Exception classes for RSCM::Accurev
|
6
|
+
#
|
7
|
+
# Includes:
|
8
|
+
#
|
9
|
+
# * AccurevException
|
10
|
+
#
|
11
|
+
# * StaleWorkspaceException
|
12
|
+
#
|
13
|
+
module RSCM
|
14
|
+
module Accurev
|
15
|
+
|
16
|
+
#
|
17
|
+
# General exception class for errors processing commands.
|
18
|
+
#
|
19
|
+
# @attr error_msg Error message output by accurev.
|
20
|
+
#
|
21
|
+
class AccurevException < Exception
|
22
|
+
attr_reader :error_msg
|
23
|
+
def initialize( msg, error_msg=nil )
|
24
|
+
super( "#{msg}: #{error_msg}" )
|
25
|
+
@error_msg = error_msg
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Exception thrown when an update is performed
|
31
|
+
# on a workspace with unkept/unanchored modifications.
|
32
|
+
# Accurev requires that all modifications be handled before
|
33
|
+
# an update is performed.
|
34
|
+
#
|
35
|
+
class StaleWorkspaceException < AccurevException; end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/lib/rscm/scm/accurev/xml.rb
CHANGED
@@ -109,6 +109,11 @@ module RSCM::Accurev
|
|
109
109
|
end.send( :define_method, "element_name" ) {name}
|
110
110
|
end
|
111
111
|
|
112
|
+
# currently advisory only
|
113
|
+
def self.children( *kidtypes )
|
114
|
+
# nothing XXX
|
115
|
+
end
|
116
|
+
|
112
117
|
def initialize( element=nil )
|
113
118
|
@children = {}
|
114
119
|
unless element.nil?
|
@@ -121,6 +126,18 @@ module RSCM::Accurev
|
|
121
126
|
return self.children[key]
|
122
127
|
end
|
123
128
|
|
129
|
+
def to_s
|
130
|
+
s = "<#{self.class.element_name} "
|
131
|
+
self.instance_variables.each do |a|
|
132
|
+
unless a == "@children"
|
133
|
+
attr = a.sub( /^@/, "" )
|
134
|
+
s += "#{attr}='#{self.send(attr)}' "
|
135
|
+
end
|
136
|
+
end
|
137
|
+
s += "/>"
|
138
|
+
return s
|
139
|
+
end
|
140
|
+
|
124
141
|
protected
|
125
142
|
# Does the work of calling object setters for each XML attribute.
|
126
143
|
def set_from_element( e )
|
@@ -179,4 +196,29 @@ module RSCM::Accurev
|
|
179
196
|
attr_accessor :error, :text_content
|
180
197
|
end
|
181
198
|
|
199
|
+
#
|
200
|
+
# Version (element) records in a history transaction
|
201
|
+
#
|
202
|
+
class VersionData < ElementBackedClass
|
203
|
+
element_name 'version'
|
204
|
+
attr_accessor :path, :eid, :virtual, :real, :elem_type
|
205
|
+
end
|
206
|
+
|
207
|
+
#
|
208
|
+
# Commit messages on transactions
|
209
|
+
#
|
210
|
+
class CommentData < ElementBackedClass
|
211
|
+
element_name 'comment'
|
212
|
+
end
|
213
|
+
|
214
|
+
#
|
215
|
+
# Data from "accurev hist" - transaction groups
|
216
|
+
# Contains one or more VersionData.
|
217
|
+
#
|
218
|
+
class TransactionData < ElementBackedClass
|
219
|
+
element_name 'transaction'
|
220
|
+
children VersionData, CommentData
|
221
|
+
attr_accessor :id, :type, :time, :user
|
222
|
+
end
|
223
|
+
|
182
224
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
require 'erb'
|
3
|
+
require 'fileutils'
|
4
|
+
include FileUtils
|
5
|
+
|
6
|
+
#
|
7
|
+
# usage:
|
8
|
+
# rake coverage
|
9
|
+
#
|
10
|
+
#
|
11
|
+
|
12
|
+
trace_file = ARGV.shift
|
13
|
+
output_dir = ARGV.shift
|
14
|
+
template_file = ARGV.shift
|
15
|
+
template_index = ARGV.shift
|
16
|
+
|
17
|
+
if trace_file.nil? or output_dir.nil?
|
18
|
+
raise "Usage: $0 <tracefile> <output_dir> <template> <index_template>"
|
19
|
+
end
|
20
|
+
|
21
|
+
# stdout.printf("#%d:%s:%d:%s:%s: %s",
|
22
|
+
# get_thread_no,
|
23
|
+
# file,
|
24
|
+
# line,
|
25
|
+
# klass || '',
|
26
|
+
# EVENT_SYMBOL[event],
|
27
|
+
# get_line(file, line))
|
28
|
+
|
29
|
+
puts "Reading trace data #{trace_file}..."
|
30
|
+
files = {}
|
31
|
+
File.open( trace_file, "r" ).each_line do |line|
|
32
|
+
data, linedump = line.split(/ /)
|
33
|
+
threadno, file, n, classname, eventsym = data.split(/:/)
|
34
|
+
files[file] ||= []
|
35
|
+
files[file][n.to_i] ||= 0
|
36
|
+
files[file][n.to_i] += 1
|
37
|
+
end
|
38
|
+
|
39
|
+
class Summary
|
40
|
+
attr_accessor :filename, :total_lines, :covered_lines
|
41
|
+
attr_accessor :lines, :seen
|
42
|
+
def initialize( filename )
|
43
|
+
@filename = filename
|
44
|
+
@total_lines = 0
|
45
|
+
@covered_lines = 0
|
46
|
+
@lines = []
|
47
|
+
@seen = []
|
48
|
+
end
|
49
|
+
def pct
|
50
|
+
@covered_lines.to_f / @total_lines.to_f
|
51
|
+
end
|
52
|
+
def htmlfile
|
53
|
+
@filename.gsub(/[\.\/]/, '_') + ".html"
|
54
|
+
end
|
55
|
+
def get_binding
|
56
|
+
binding
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class IndexSummary
|
61
|
+
attr_accessor :summary
|
62
|
+
def get_binding
|
63
|
+
binding
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def pretty( template, output_dir, s )
|
68
|
+
htmlfile = "#{output_dir}/#{s.htmlfile}"
|
69
|
+
puts htmlfile
|
70
|
+
File.open( htmlfile, "w" ) do |out|
|
71
|
+
rhtml = ERB.new( template )
|
72
|
+
out.print( rhtml.result( s.get_binding ) )
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def index( template, output_dir, summaries )
|
77
|
+
idx = IndexSummary.new
|
78
|
+
idx.summary = summaries
|
79
|
+
puts "#{output_dir}/index.html"
|
80
|
+
File.open( "#{output_dir}/index.html", "w" ) do |out|
|
81
|
+
rhtml = ERB.new( template )
|
82
|
+
out.print( rhtml.result( idx.get_binding ) )
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
template = File.read( template_file )
|
87
|
+
index_tmpl = File.read( template_index )
|
88
|
+
|
89
|
+
puts "Outputting to #{output_dir}..."
|
90
|
+
mkdir_p( output_dir )
|
91
|
+
summary = {}
|
92
|
+
files.each do |file, linelist|
|
93
|
+
s = Summary.new( file )
|
94
|
+
lineno = 0
|
95
|
+
File.open( file ).each_line do |line|
|
96
|
+
lineno += 1
|
97
|
+
seen_this = false
|
98
|
+
# basic: line was traced
|
99
|
+
unless linelist[lineno].nil?
|
100
|
+
seen_this = true
|
101
|
+
end
|
102
|
+
# misc: various comments, blank lines, other "untraceables"
|
103
|
+
# mark them as seen
|
104
|
+
if line =~ /^\s*$/
|
105
|
+
seen_this = true
|
106
|
+
end
|
107
|
+
if line =~ /^\s*#/
|
108
|
+
seen_this = true
|
109
|
+
end
|
110
|
+
if line =~ /^\s*(require|class|module|end|else|include|def)/
|
111
|
+
seen_this = true
|
112
|
+
end
|
113
|
+
s.seen << seen_this
|
114
|
+
if seen_this
|
115
|
+
s.covered_lines += 1
|
116
|
+
end
|
117
|
+
s.total_lines +=1
|
118
|
+
s.lines << line
|
119
|
+
end
|
120
|
+
summary[file] = s
|
121
|
+
pretty( template, output_dir, summary[file] )
|
122
|
+
end
|
123
|
+
index( index_tmpl, output_dir, summary )
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'tracer'
|
3
|
+
|
4
|
+
# Initialize tracer
|
5
|
+
TRACE_FILE = "xxx.trace"
|
6
|
+
OUTPUT = File.open( TRACE_FILE, "w" )
|
7
|
+
puts "Tracing to #{TRACE_FILE}"
|
8
|
+
t = Tracer.new()
|
9
|
+
def t.stdout
|
10
|
+
OUTPUT
|
11
|
+
end
|
12
|
+
def t.coverage_filter( event, file, line, id, binding, klass )
|
13
|
+
# skip c libs
|
14
|
+
return false if event == 'c-call'
|
15
|
+
return false if event == 'c-return'
|
16
|
+
return false if event == 'class'
|
17
|
+
# skip any (other) core libs
|
18
|
+
return false if file =~ /^\//
|
19
|
+
# skip magical eval code
|
20
|
+
return false if file =~ /\(eval\)/
|
21
|
+
# log everything else
|
22
|
+
return true
|
23
|
+
end
|
24
|
+
t.add_filter( t.method(:coverage_filter).to_proc )
|
25
|
+
|
26
|
+
# load in test files
|
27
|
+
ARGV.each do |f|
|
28
|
+
load f unless f =~ /^-/
|
29
|
+
end
|
30
|
+
|
31
|
+
# turn tracing on: test::unit::autorunner runs test in an at_exit proc
|
32
|
+
t.on
|
33
|
+
|
34
|
+
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# set_trace_func proc do |event,file,line,id,binding,classname|
|
4
|
+
# 'c-call' # call into clib - file:line -> caller
|
5
|
+
# 'c-return' # return out of clib - file:line -> caller
|
6
|
+
# 'call' # call into ruby fn - file:line -> fn def
|
7
|
+
# 'class' # start class/mod def (only for dyn classes?)
|
8
|
+
# 'end' # end class/mod def
|
9
|
+
# 'line' # exec line
|
10
|
+
# 'raise' # exception
|
11
|
+
# 'return' # return from ruby fn - file:line -> returning stmt
|
12
|
+
# end
|
13
|
+
|
14
|
+
require 'rexml/document'
|
15
|
+
include REXML
|
16
|
+
|
17
|
+
# defining script_lines make ruby dump all scripts into this hash
|
18
|
+
SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
|
19
|
+
|
20
|
+
|
21
|
+
module Test
|
22
|
+
|
23
|
+
class Cover
|
24
|
+
|
25
|
+
attr_accessor :codebase_files
|
26
|
+
|
27
|
+
def initialize()
|
28
|
+
@codebase_files = []
|
29
|
+
# seen_lines is a hash of hashes
|
30
|
+
@seen_lines = {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def trace_func( event, file, line, id, binding, classname )
|
34
|
+
return if event == 'c-call'
|
35
|
+
return if event == 'c-return'
|
36
|
+
return if event == 'class'
|
37
|
+
@seen_lines[file] ||= {}
|
38
|
+
@seen_lines[file][line] ||= 0
|
39
|
+
@seen_lines[file][line] += 1
|
40
|
+
end
|
41
|
+
|
42
|
+
def coverage()
|
43
|
+
set_trace_func( self.method(:trace_func).to_proc )
|
44
|
+
yield self
|
45
|
+
set_trace_func( nil )
|
46
|
+
end
|
47
|
+
|
48
|
+
def coverage_all()
|
49
|
+
set_trace_func( self.method(:trace_func).to_proc )
|
50
|
+
end
|
51
|
+
|
52
|
+
def coverage_clear()
|
53
|
+
set_trace_func( nil )
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_xml
|
57
|
+
doc = Document.new()
|
58
|
+
doc << XMLDecl.new()
|
59
|
+
root = Element.new( "coverage" )
|
60
|
+
doc << root
|
61
|
+
root.attributes['timestamp'] = Time.now
|
62
|
+
codebase = Element.new( "codebase" )
|
63
|
+
root << codebase
|
64
|
+
@codebase_files.each do |file|
|
65
|
+
e = Element.new( "file" )
|
66
|
+
e.attributes['name'] = file
|
67
|
+
codebase << e
|
68
|
+
if @seen_lines.has_key?( file )
|
69
|
+
seen = Element.new( "seen" )
|
70
|
+
e << seen
|
71
|
+
linehash = @seen_lines[file]
|
72
|
+
next unless SCRIPT_LINES__.has_key?( file )
|
73
|
+
linehash.each do |n,occur|
|
74
|
+
le = Element.new( "line" )
|
75
|
+
le.attributes['n'] = n
|
76
|
+
le.attributes['occur'] = occur
|
77
|
+
seen << le
|
78
|
+
end
|
79
|
+
ce = Element.new( "coverage" )
|
80
|
+
ce.attributes['seen'] = linehash.size
|
81
|
+
ce.attributes['total'] = SCRIPT_LINES__[file].size
|
82
|
+
ce.attributes['pct'] = linehash.size.to_f / SCRIPT_LINES__[file].size.to_f
|
83
|
+
seen << ce
|
84
|
+
end
|
85
|
+
end
|
86
|
+
return doc
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
#require 'tracer'
|
4
|
+
require 'test/cover'
|
5
|
+
|
6
|
+
cover = Test::Cover.new()
|
7
|
+
cover.coverage_all
|
8
|
+
cover.codebase_files << "./lib/rscm/accurev.rb"
|
9
|
+
cover.codebase_files << "./lib/rscm/scm/accurev/command.rb"
|
10
|
+
|
11
|
+
#Tracer.on
|
12
|
+
ARGV.each do |f|
|
13
|
+
load f unless f =~ /^-/
|
14
|
+
end
|
15
|
+
|
16
|
+
END {
|
17
|
+
cover.coverage_clear
|
18
|
+
File.open( "xxx.xml", "w" ) do |f|
|
19
|
+
f.puts( cover.to_xml )
|
20
|
+
end
|
21
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/tasklib'
|
5
|
+
|
6
|
+
module Rake
|
7
|
+
|
8
|
+
class CoverageTask < TaskLib
|
9
|
+
attr_accessor :name
|
10
|
+
attr_accessor :libs
|
11
|
+
attr_accessor :test_files
|
12
|
+
attr_accessor :ruby_opts
|
13
|
+
|
14
|
+
def initialize( name=:coverage )
|
15
|
+
@name = name
|
16
|
+
@libs = ["lib"]
|
17
|
+
@test_files = nil
|
18
|
+
@ruby_opts = []
|
19
|
+
yield self if block_given?
|
20
|
+
define
|
21
|
+
end
|
22
|
+
|
23
|
+
def define
|
24
|
+
lib_path = @libs.join( File::PATH_SEPARATOR )
|
25
|
+
@ruby_opts.unshift( "-I#{lib_path}" )
|
26
|
+
task @name do
|
27
|
+
ruby @ruby_opts.join(" ") +
|
28
|
+
"test/coverage_loader.rb " +
|
29
|
+
file_list.collect {|fn| "\"#{fn}\"".join(" ")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_loader()
|
34
|
+
find_file( 'test/coverage_loader' ) or fail "I DIE"
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Coverage Summary</title>
|
4
|
+
</head>
|
5
|
+
<body>
|
6
|
+
<h1>Coverage Summary</h1>
|
7
|
+
|
8
|
+
<%
|
9
|
+
def grad( pct )
|
10
|
+
zero_end = [255,0,0]
|
11
|
+
one_end = [0,255,0]
|
12
|
+
g = []
|
13
|
+
(0..2).each do |i|
|
14
|
+
g[i] = (pct * (one_end[i]-zero_end[i])) + zero_end[i]
|
15
|
+
end
|
16
|
+
return "#"+g.collect{|x| "%02x" % x }.join("")
|
17
|
+
end
|
18
|
+
%>
|
19
|
+
<p>
|
20
|
+
Codebase:
|
21
|
+
|
22
|
+
<table border="1">
|
23
|
+
<tr>
|
24
|
+
<td>File</td>
|
25
|
+
<td>Lines</td>
|
26
|
+
<td>Covered</td>
|
27
|
+
<td>% Covered</td>
|
28
|
+
</tr>
|
29
|
+
|
30
|
+
<% summary.each do |filename,s| %>
|
31
|
+
<tr>
|
32
|
+
<td><a href="<%= s.htmlfile %>"><%= filename %></a></td>
|
33
|
+
<td><%= s.total_lines %></td>
|
34
|
+
<td><%= s.covered_lines %></td>
|
35
|
+
<td bgcolor="<%= grad(s.pct) %>"><%= s.pct %></td>
|
36
|
+
</tr>
|
37
|
+
<% end %>
|
38
|
+
|
39
|
+
</table>
|
40
|
+
</p>
|
41
|
+
</body>
|
42
|
+
</html>
|