kwala 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +62 -0
- data/bin/kwala +39 -0
- data/lib/kwala.rb +59 -0
- data/lib/kwala/actions/code_change.rb +128 -0
- data/lib/kwala/actions/code_coverage.rb +303 -0
- data/lib/kwala/actions/code_duplication.rb +222 -0
- data/lib/kwala/actions/code_formatting.rb +358 -0
- data/lib/kwala/actions/cycle_detection.rb +118 -0
- data/lib/kwala/actions/cyclomatic_complexity.rb +159 -0
- data/lib/kwala/actions/dead_code.rb +68 -0
- data/lib/kwala/actions/executable_files_check.rb +111 -0
- data/lib/kwala/actions/flagged_comments.rb +128 -0
- data/lib/kwala/actions/gem_plugin.rb +31 -0
- data/lib/kwala/actions/loc_count.rb +153 -0
- data/lib/kwala/actions/multi_ruby_unit_test.rb +62 -0
- data/lib/kwala/actions/outside_links.rb +85 -0
- data/lib/kwala/actions/rails_migrate.rb +62 -0
- data/lib/kwala/actions/strange_requires.rb +106 -0
- data/lib/kwala/actions/syntax_check.rb +130 -0
- data/lib/kwala/actions/unit_test.rb +368 -0
- data/lib/kwala/build_action.rb +88 -0
- data/lib/kwala/build_context.rb +49 -0
- data/lib/kwala/command_line_runner.rb +184 -0
- data/lib/kwala/ext/demos.jar +0 -0
- data/lib/kwala/ext/pmd.jar +0 -0
- data/lib/kwala/ext/prefuse.jar +0 -0
- data/lib/kwala/extensions.rb +36 -0
- data/lib/kwala/lib/code_analyzer.rb +678 -0
- data/lib/kwala/lib/cycle_detector.rb +793 -0
- data/lib/kwala/lib/strange_requires_detector.rb +145 -0
- data/lib/kwala/notification.rb +45 -0
- data/lib/kwala/notifications/email.rb +54 -0
- data/lib/kwala/notifications/rss.rb +151 -0
- data/lib/kwala/project_builder_utils.rb +178 -0
- data/lib/kwala/templates/build_template.html +33 -0
- data/lib/kwala/templates/code_change_summary.html +27 -0
- data/lib/kwala/templates/code_coverage_detailed.html +25 -0
- data/lib/kwala/templates/code_coverage_summary.html +30 -0
- data/lib/kwala/templates/code_duplication_detailed.html +45 -0
- data/lib/kwala/templates/code_duplication_summary.html +9 -0
- data/lib/kwala/templates/code_formatting_detailed.html +27 -0
- data/lib/kwala/templates/code_formatting_summary.html +11 -0
- data/lib/kwala/templates/cycle_detection_detailed.html +20 -0
- data/lib/kwala/templates/cycle_detection_summary.html +7 -0
- data/lib/kwala/templates/cyclomatic_complexity_summary.html +27 -0
- data/lib/kwala/templates/executable_files_check_detailed.html +31 -0
- data/lib/kwala/templates/executable_files_check_summary.html +20 -0
- data/lib/kwala/templates/flagged_comments_detailed.html +22 -0
- data/lib/kwala/templates/flagged_comments_summary.html +10 -0
- data/lib/kwala/templates/loc_count_detailed.html +24 -0
- data/lib/kwala/templates/loc_count_summary.html +14 -0
- data/lib/kwala/templates/mdd/1.png +0 -0
- data/lib/kwala/templates/mdd/2.png +0 -0
- data/lib/kwala/templates/mdd/3.png +0 -0
- data/lib/kwala/templates/mdd/4.png +0 -0
- data/lib/kwala/templates/mdd/5.png +0 -0
- data/lib/kwala/templates/outside_links_summary.html +4 -0
- data/lib/kwala/templates/strange_requires_detailed.html +23 -0
- data/lib/kwala/templates/strange_requires_summary.html +13 -0
- data/lib/kwala/templates/style.css +95 -0
- data/lib/kwala/templates/syntax_check_detailed.html +21 -0
- data/lib/kwala/templates/syntax_check_summary.html +7 -0
- data/lib/kwala/templates/unit_test_detailed.html +66 -0
- data/lib/kwala/templates/unit_test_summary.html +70 -0
- data/test/tc_build_action.rb +32 -0
- data/test/tc_templates.rb +24 -0
- metadata +118 -0
@@ -0,0 +1,118 @@
|
|
1
|
+
# $Id: cycle_detection.rb 32 2008-04-02 07:50:18Z zev $
|
2
|
+
#
|
3
|
+
# Implements a Ruby require cycle detection and graphing action.
|
4
|
+
|
5
|
+
# Copyright (c) 2006, Ubiquitous Business Technology (http://ubit.com)
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
# Redistribution and use in source and binary forms, with or without
|
9
|
+
# modification, are permitted provided that the following conditions are
|
10
|
+
# met:
|
11
|
+
#
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright
|
14
|
+
# notice, this list of conditions and the following disclaimer.
|
15
|
+
#
|
16
|
+
# * Redistributions in binary form must reproduce the above
|
17
|
+
# copyright notice, this list of conditions and the following
|
18
|
+
# disclaimer in the documentation and/or other materials provided
|
19
|
+
# with the distribution.
|
20
|
+
#
|
21
|
+
# * Neither the name of Ubit nor the names of its
|
22
|
+
# contributors may be used to endorse or promote products derived
|
23
|
+
# from this software without specific prior written permission.
|
24
|
+
#
|
25
|
+
#
|
26
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
27
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
28
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
29
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
30
|
+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
31
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
32
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
33
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
34
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
35
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
36
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
37
|
+
#
|
38
|
+
# == Author
|
39
|
+
# Zev Blut (zb@ubit.com)
|
40
|
+
|
41
|
+
require 'stringio'
|
42
|
+
|
43
|
+
require "#{LIB_DIR}/cycle_detector"
|
44
|
+
|
45
|
+
class CycleDetectionAction < BuildAction
|
46
|
+
|
47
|
+
def initialize
|
48
|
+
@cycle_detector = CycleDetector.new
|
49
|
+
@cycle_detector.print_strategy = self
|
50
|
+
@output_directory = nil
|
51
|
+
@cycles = nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def build_action(context)
|
55
|
+
# convert obj?
|
56
|
+
@cycle_detector.make_graph(context.project_directory)
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
def summary_display(context)
|
61
|
+
template = TemplateFile.new(self.class.summary_template_file)
|
62
|
+
@cycle_detector.print_unique_cycles( @cycle_detector.find_cycles )
|
63
|
+
|
64
|
+
if @cycles.empty?
|
65
|
+
context.amrita_data[:cycle_results] = "There are no require cycles."
|
66
|
+
else
|
67
|
+
data = @cycles.map do |cycle|
|
68
|
+
{
|
69
|
+
:name => "#{ cycle.first} <=> #{ cycle.last }",
|
70
|
+
:list => cycle
|
71
|
+
}
|
72
|
+
end
|
73
|
+
context.amrita_data[:cycle_results] = { :entry => data }
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
loc_base = "#{context.project_name}_cycle.html"
|
78
|
+
context.amrita_data[:cycle_details] =
|
79
|
+
Amrita.e(:a, :href => loc_base ) { "Require Graph Details" }
|
80
|
+
|
81
|
+
summary_expand(template, context)
|
82
|
+
end
|
83
|
+
|
84
|
+
def detailed_display(context)
|
85
|
+
template = TemplateFile.new(self.class.detailed_template_file)
|
86
|
+
|
87
|
+
@output_directory = context.output_directory
|
88
|
+
@cycle_detector.print_graph
|
89
|
+
|
90
|
+
["demos.jar", "prefuse.jar"].each do |jarfile|
|
91
|
+
FileUtils.cp(EXTERNAL_DIR + jarfile, context.output_directory)
|
92
|
+
end
|
93
|
+
|
94
|
+
det_res = ProjectBuilderUtils.expand_template(template, context.amrita_data)
|
95
|
+
det_file = "#{context.output_directory}/#{context.project_name}_cycle.html"
|
96
|
+
[det_file, det_res]
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
def print_graph(graph)
|
101
|
+
graph_ml = CycleDetector::GraphMLPrintStrategy.new
|
102
|
+
begin
|
103
|
+
oldstd = $stdout
|
104
|
+
$stdout = StringIO.new
|
105
|
+
graph_ml.print_graph(graph)
|
106
|
+
gxml = $stdout.string
|
107
|
+
ensure
|
108
|
+
$stdout = oldstd
|
109
|
+
end
|
110
|
+
# now dump that into the out dir
|
111
|
+
File.open(@output_directory + "/require_graph.xml", "w") { |f| f.puts gxml }
|
112
|
+
end
|
113
|
+
|
114
|
+
def print_cycles(cycles)
|
115
|
+
@cycles = cycles
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# $Id: cyclomatic_complexity.rb 34 2008-04-03 06:01:19Z zev $
|
2
|
+
#
|
3
|
+
# This file checks the cyclomatic complexity of a source base.
|
4
|
+
#
|
5
|
+
# Uses Saikuro http://saikuro.rubyforge.org
|
6
|
+
|
7
|
+
# Copyright (c) 2006, Ubiquitous Business Technology (http://ubit.com)
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are
|
12
|
+
# met:
|
13
|
+
#
|
14
|
+
#
|
15
|
+
# * Redistributions of source code must retain the above copyright
|
16
|
+
# notice, this list of conditions and the following disclaimer.
|
17
|
+
#
|
18
|
+
# * Redistributions in binary form must reproduce the above
|
19
|
+
# copyright notice, this list of conditions and the following
|
20
|
+
# disclaimer in the documentation and/or other materials provided
|
21
|
+
# with the distribution.
|
22
|
+
#
|
23
|
+
# * Neither the name of Ubit nor the names of its
|
24
|
+
# contributors may be used to endorse or promote products derived
|
25
|
+
# from this software without specific prior written permission.
|
26
|
+
#
|
27
|
+
#
|
28
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
29
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
30
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
31
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
32
|
+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
33
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
34
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
35
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
36
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
37
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
38
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
|
+
#
|
40
|
+
# == Author
|
41
|
+
# Zev Blut (zb@ubit.com)
|
42
|
+
|
43
|
+
class CyclomaticComplexityAction < BuildAction
|
44
|
+
|
45
|
+
def initialize
|
46
|
+
@limit = 11 # 1 more for header
|
47
|
+
@cyclo_count = nil
|
48
|
+
@bound = 0 # This should be methods instead of files.
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_action(context)
|
52
|
+
args = [ "-o #{context.output_directory}" ]
|
53
|
+
args << [ "-c -t"]
|
54
|
+
args << [ "-y 0 -w 11 -e 15"]
|
55
|
+
args << [ "-k 0 -s 30 -d 35"]
|
56
|
+
args << [ "-i #{context.project_directory}" ]
|
57
|
+
|
58
|
+
stdout_data = stderr_data = Array.new
|
59
|
+
system("/usr/bin/env saikuro #{args.join(" ")}")
|
60
|
+
@cyclo_count = get_cyclo_violations(context)
|
61
|
+
@bound = context.ruby_files.size + context.test_files.size
|
62
|
+
end
|
63
|
+
|
64
|
+
def summary_display(context)
|
65
|
+
template = TemplateFile.new(self.class.summary_template_file)
|
66
|
+
context.amrita_data[:saikuro_metrics_summary] = {
|
67
|
+
:cyclo_summary => get_cyclo_summary(context),
|
68
|
+
:token_summary => get_token_summary(context),
|
69
|
+
:cyclo_violations => get_cyclo_violations(context),
|
70
|
+
:token_violations => get_token_violations(context),
|
71
|
+
:cyclo_link => Amrita::e(:a, :href => "index_cyclo.html") { "Cyclomatic Complexity Details" },
|
72
|
+
:token_link => Amrita::e(:a, :href => "index_token.html") { "Token Count Details" }
|
73
|
+
}
|
74
|
+
summary_expand(template, context)
|
75
|
+
end
|
76
|
+
|
77
|
+
def score
|
78
|
+
# high complexity is probably one of the things that should weigh higher.
|
79
|
+
score_scaling(( @cyclo_count[:errors] * 3 + @cyclo_count[:warnings]), @bound)
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.detailed_template_file
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_cyclo_summary(context)
|
87
|
+
get_summary_from_file(context.output_directory + "/index_cyclo.html")
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_token_summary(context)
|
91
|
+
get_summary_from_file(context.output_directory + "/index_token.html")
|
92
|
+
end
|
93
|
+
|
94
|
+
def get_cyclo_violations(context)
|
95
|
+
count_violations(context.output_directory + "/index_cyclo.html")
|
96
|
+
end
|
97
|
+
|
98
|
+
def get_token_violations(context)
|
99
|
+
count_violations(context.output_directory + "/index_token.html")
|
100
|
+
end
|
101
|
+
|
102
|
+
def get_summary_from_file(file)
|
103
|
+
if !File.exists?(file)
|
104
|
+
STDERR.puts "Saikuro : Cannot find #{file}"
|
105
|
+
return ""
|
106
|
+
end
|
107
|
+
data = IO.readlines(file).join
|
108
|
+
res = ""
|
109
|
+
if m = /(<table.*?>)(.*)(<\/table>)/mi.match(data)
|
110
|
+
head = m[1]
|
111
|
+
data = m[2]
|
112
|
+
tail = m[3]
|
113
|
+
rows = Array.new
|
114
|
+
while rows.size < @limit && m = /(<tr>.*?<\/tr>)(.*)/mi.match(data)
|
115
|
+
rows << m[1]
|
116
|
+
data = m[2]
|
117
|
+
end
|
118
|
+
|
119
|
+
res = head.to_s + rows.join("\n") + tail.to_s
|
120
|
+
end
|
121
|
+
|
122
|
+
SanitizedString.new(res)
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
# XXX: This is basically the same as get_summary_from_file, there
|
127
|
+
# should be a nice way to reuse the logic in a more clean way.
|
128
|
+
def count_violations(file)
|
129
|
+
if !File.exists?(file)
|
130
|
+
return 0
|
131
|
+
end
|
132
|
+
|
133
|
+
data = IO.readlines(file).join
|
134
|
+
errors = 0
|
135
|
+
warnings = 0
|
136
|
+
|
137
|
+
if m = /(<table.*?>)(.*)(<\/table>)/mi.match(data)
|
138
|
+
data = m[2]
|
139
|
+
while m = /(<tr>.*?<\/tr>)(.*)/mi.match(data)
|
140
|
+
if /^<tr><th>/ !~ m[1]
|
141
|
+
# Make sure not to count the header row.
|
142
|
+
if /class=\"error\"/ =~ m[1]
|
143
|
+
errors += 1
|
144
|
+
elsif /class=\"warning\"/ =~ m[1]
|
145
|
+
warnings += 1
|
146
|
+
end
|
147
|
+
end
|
148
|
+
data = m[2]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
{
|
153
|
+
:total => errors + warnings,
|
154
|
+
:errors => errors,
|
155
|
+
:warnings => warnings
|
156
|
+
}
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# $Id$
|
2
|
+
#
|
3
|
+
# This file handles logic for dead code checking
|
4
|
+
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are
|
9
|
+
# met:
|
10
|
+
#
|
11
|
+
#
|
12
|
+
# * Redistributions of source code must retain the above copyright
|
13
|
+
# notice, this list of conditions and the following disclaimer.
|
14
|
+
#
|
15
|
+
# * Redistributions in binary form must reproduce the above
|
16
|
+
# copyright notice, this list of conditions and the following
|
17
|
+
# disclaimer in the documentation and/or other materials provided
|
18
|
+
# with the distribution.
|
19
|
+
#
|
20
|
+
# * Neither the name of Ubit nor the names of its
|
21
|
+
# contributors may be used to endorse or promote products derived
|
22
|
+
# from this software without specific prior written permission.
|
23
|
+
#
|
24
|
+
#
|
25
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
26
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
27
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
28
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
29
|
+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
30
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
31
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
32
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
33
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
34
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
35
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
36
|
+
#
|
37
|
+
# == Author
|
38
|
+
# Zev Blut ()
|
39
|
+
|
40
|
+
class DeadCodeAction < BuildAction
|
41
|
+
|
42
|
+
def initialize
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_action(context)
|
46
|
+
end
|
47
|
+
|
48
|
+
def summary_display(context)
|
49
|
+
template = TemplateFile.new("#{TEMPLATE_DIR}/dead_code_template.html")
|
50
|
+
summary_expand(template, context)
|
51
|
+
end
|
52
|
+
|
53
|
+
def detailed_display(context)
|
54
|
+
context.amrita_data[:syntax_results] = {
|
55
|
+
:entry => @syntax_results
|
56
|
+
}
|
57
|
+
det_res = expand_syntax_check_template(context.amrita_data[:syntax_results])
|
58
|
+
det_file = "#{context.output_directory}/#{context.project_name}_dead_code.html"
|
59
|
+
[det_file, det_res]
|
60
|
+
end
|
61
|
+
|
62
|
+
def score
|
63
|
+
10
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# $Id: executable_files_check.rb 29 2008-04-02 07:32:44Z zev $
|
2
|
+
#
|
3
|
+
# This action checks for the code size within ruby scripts starting with
|
4
|
+
# a shell bang. By our convention, we want to keep those files as small
|
5
|
+
# as possible, all logic should be in reusable classes.
|
6
|
+
|
7
|
+
# Copyright (c) 2006, Ubiquitous Business Technology (http://ubit.com)
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are
|
12
|
+
# met:
|
13
|
+
#
|
14
|
+
#
|
15
|
+
# * Redistributions of source code must retain the above copyright
|
16
|
+
# notice, this list of conditions and the following disclaimer.
|
17
|
+
#
|
18
|
+
# * Redistributions in binary form must reproduce the above
|
19
|
+
# copyright notice, this list of conditions and the following
|
20
|
+
# disclaimer in the documentation and/or other materials provided
|
21
|
+
# with the distribution.
|
22
|
+
#
|
23
|
+
# * Neither the name of Ubit nor the names of its
|
24
|
+
# contributors may be used to endorse or promote products derived
|
25
|
+
# from this software without specific prior written permission.
|
26
|
+
#
|
27
|
+
#
|
28
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
29
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
30
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
31
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
32
|
+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
33
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
34
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
35
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
36
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
37
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
38
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
|
+
#
|
40
|
+
# == Author
|
41
|
+
# Michael Reinsch (mr@ubit.com)
|
42
|
+
|
43
|
+
require File.dirname(__FILE__) + "/loc_count.rb"
|
44
|
+
|
45
|
+
class ExecutableFilesCheckAction < BuildAction
|
46
|
+
include LOCCountModule
|
47
|
+
|
48
|
+
def initialize
|
49
|
+
@problem_files = Array.new
|
50
|
+
@shellbang_files_LOC = Hash.new
|
51
|
+
end
|
52
|
+
|
53
|
+
def build_action(context)
|
54
|
+
context.ruby_files.each do |f|
|
55
|
+
exec = File.executable?(f)
|
56
|
+
bang = ("#!/" == IO.read(f, 3, 0))
|
57
|
+
if exec ^ bang
|
58
|
+
if exec
|
59
|
+
prob = "executable, no shell bang"
|
60
|
+
else
|
61
|
+
prob = "shell bang, not executable"
|
62
|
+
end
|
63
|
+
@problem_files << { :filename => f, :problem => prob }
|
64
|
+
end
|
65
|
+
@shellbang_files_LOC[f] = count_loc(f) if bang
|
66
|
+
end
|
67
|
+
@sorted_shellbang_files_LOC = @shellbang_files_LOC.sort {|a,b| b[1] <=> a[1] }
|
68
|
+
end
|
69
|
+
|
70
|
+
def summary_display(context)
|
71
|
+
template = TemplateFile.new(self.class.summary_template_file)
|
72
|
+
|
73
|
+
res = {}
|
74
|
+
if @problem_files.size > 0
|
75
|
+
res[:problem_files] = { :files => @problem_files }
|
76
|
+
end
|
77
|
+
|
78
|
+
# get top 10
|
79
|
+
top_ten_files = @sorted_shellbang_files_LOC[0..9]
|
80
|
+
res[:files] = top_ten_files.map do |f, l|
|
81
|
+
{ :filename => f, :lines_of_code => l }
|
82
|
+
end
|
83
|
+
|
84
|
+
context.amrita_data[:executable_files_check_results] = res
|
85
|
+
execfilecodesize_base = "#{context.project_name}_executable_files_check.html"
|
86
|
+
context.amrita_data[:executable_files_check_details] =
|
87
|
+
(Amrita::e(:a, :href => execfilecodesize_base) { "Executable Files Check Details" } )
|
88
|
+
|
89
|
+
summary_expand(template, context)
|
90
|
+
end
|
91
|
+
|
92
|
+
def detailed_display(context)
|
93
|
+
template = TemplateFile.new(self.class.detailed_template_file)
|
94
|
+
|
95
|
+
res = {}
|
96
|
+
if @problem_files.size > 0
|
97
|
+
res[:problem_files] = { :files => @problem_files }
|
98
|
+
end
|
99
|
+
|
100
|
+
res[:files] = @sorted_shellbang_files_LOC.map do |f, l|
|
101
|
+
{ :filename => f, :lines_of_code => l }
|
102
|
+
end
|
103
|
+
|
104
|
+
context.amrita_data[:executable_files_check_results] = res
|
105
|
+
|
106
|
+
det_res = ProjectBuilderUtils.expand_template(template, context.amrita_data)
|
107
|
+
det_file = "#{context.output_directory}/#{context.project_name}_executable_files_check.html"
|
108
|
+
[det_file, det_res]
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|