rscm-accurev 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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>