railroader 4.3.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.
- checksums.yaml +7 -0
- data/CHANGES.md +1091 -0
- data/FEATURES +16 -0
- data/README.md +174 -0
- data/bin/railroader +8 -0
- data/lib/railroader/app_tree.rb +191 -0
- data/lib/railroader/call_index.rb +219 -0
- data/lib/railroader/checks/base_check.rb +505 -0
- data/lib/railroader/checks/check_basic_auth.rb +88 -0
- data/lib/railroader/checks/check_basic_auth_timing_attack.rb +33 -0
- data/lib/railroader/checks/check_content_tag.rb +200 -0
- data/lib/railroader/checks/check_create_with.rb +74 -0
- data/lib/railroader/checks/check_cross_site_scripting.rb +381 -0
- data/lib/railroader/checks/check_default_routes.rb +86 -0
- data/lib/railroader/checks/check_deserialize.rb +56 -0
- data/lib/railroader/checks/check_detailed_exceptions.rb +55 -0
- data/lib/railroader/checks/check_digest_dos.rb +38 -0
- data/lib/railroader/checks/check_divide_by_zero.rb +42 -0
- data/lib/railroader/checks/check_dynamic_finders.rb +48 -0
- data/lib/railroader/checks/check_escape_function.rb +21 -0
- data/lib/railroader/checks/check_evaluation.rb +35 -0
- data/lib/railroader/checks/check_execute.rb +189 -0
- data/lib/railroader/checks/check_file_access.rb +71 -0
- data/lib/railroader/checks/check_file_disclosure.rb +35 -0
- data/lib/railroader/checks/check_filter_skipping.rb +31 -0
- data/lib/railroader/checks/check_forgery_setting.rb +81 -0
- data/lib/railroader/checks/check_header_dos.rb +31 -0
- data/lib/railroader/checks/check_i18n_xss.rb +48 -0
- data/lib/railroader/checks/check_jruby_xml.rb +36 -0
- data/lib/railroader/checks/check_json_encoding.rb +47 -0
- data/lib/railroader/checks/check_json_parsing.rb +107 -0
- data/lib/railroader/checks/check_link_to.rb +132 -0
- data/lib/railroader/checks/check_link_to_href.rb +146 -0
- data/lib/railroader/checks/check_mail_to.rb +49 -0
- data/lib/railroader/checks/check_mass_assignment.rb +196 -0
- data/lib/railroader/checks/check_mime_type_dos.rb +39 -0
- data/lib/railroader/checks/check_model_attr_accessible.rb +55 -0
- data/lib/railroader/checks/check_model_attributes.rb +119 -0
- data/lib/railroader/checks/check_model_serialize.rb +67 -0
- data/lib/railroader/checks/check_nested_attributes.rb +38 -0
- data/lib/railroader/checks/check_nested_attributes_bypass.rb +58 -0
- data/lib/railroader/checks/check_number_to_currency.rb +74 -0
- data/lib/railroader/checks/check_permit_attributes.rb +43 -0
- data/lib/railroader/checks/check_quote_table_name.rb +40 -0
- data/lib/railroader/checks/check_redirect.rb +256 -0
- data/lib/railroader/checks/check_regex_dos.rb +68 -0
- data/lib/railroader/checks/check_render.rb +97 -0
- data/lib/railroader/checks/check_render_dos.rb +37 -0
- data/lib/railroader/checks/check_render_inline.rb +53 -0
- data/lib/railroader/checks/check_response_splitting.rb +21 -0
- data/lib/railroader/checks/check_route_dos.rb +42 -0
- data/lib/railroader/checks/check_safe_buffer_manipulation.rb +31 -0
- data/lib/railroader/checks/check_sanitize_methods.rb +112 -0
- data/lib/railroader/checks/check_secrets.rb +40 -0
- data/lib/railroader/checks/check_select_tag.rb +59 -0
- data/lib/railroader/checks/check_select_vulnerability.rb +60 -0
- data/lib/railroader/checks/check_send.rb +47 -0
- data/lib/railroader/checks/check_send_file.rb +19 -0
- data/lib/railroader/checks/check_session_manipulation.rb +35 -0
- data/lib/railroader/checks/check_session_settings.rb +176 -0
- data/lib/railroader/checks/check_simple_format.rb +58 -0
- data/lib/railroader/checks/check_single_quotes.rb +101 -0
- data/lib/railroader/checks/check_skip_before_filter.rb +60 -0
- data/lib/railroader/checks/check_sql.rb +700 -0
- data/lib/railroader/checks/check_sql_cves.rb +106 -0
- data/lib/railroader/checks/check_ssl_verify.rb +48 -0
- data/lib/railroader/checks/check_strip_tags.rb +89 -0
- data/lib/railroader/checks/check_symbol_dos.rb +71 -0
- data/lib/railroader/checks/check_symbol_dos_cve.rb +30 -0
- data/lib/railroader/checks/check_translate_bug.rb +45 -0
- data/lib/railroader/checks/check_unsafe_reflection.rb +50 -0
- data/lib/railroader/checks/check_unscoped_find.rb +57 -0
- data/lib/railroader/checks/check_validation_regex.rb +116 -0
- data/lib/railroader/checks/check_weak_hash.rb +148 -0
- data/lib/railroader/checks/check_without_protection.rb +80 -0
- data/lib/railroader/checks/check_xml_dos.rb +45 -0
- data/lib/railroader/checks/check_yaml_parsing.rb +121 -0
- data/lib/railroader/checks.rb +209 -0
- data/lib/railroader/codeclimate/engine_configuration.rb +97 -0
- data/lib/railroader/commandline.rb +179 -0
- data/lib/railroader/differ.rb +66 -0
- data/lib/railroader/file_parser.rb +54 -0
- data/lib/railroader/format/style.css +133 -0
- data/lib/railroader/options.rb +339 -0
- data/lib/railroader/parsers/rails2_erubis.rb +6 -0
- data/lib/railroader/parsers/rails2_xss_plugin_erubis.rb +48 -0
- data/lib/railroader/parsers/rails3_erubis.rb +81 -0
- data/lib/railroader/parsers/template_parser.rb +108 -0
- data/lib/railroader/processor.rb +102 -0
- data/lib/railroader/processors/alias_processor.rb +1229 -0
- data/lib/railroader/processors/base_processor.rb +295 -0
- data/lib/railroader/processors/config_processor.rb +14 -0
- data/lib/railroader/processors/controller_alias_processor.rb +278 -0
- data/lib/railroader/processors/controller_processor.rb +249 -0
- data/lib/railroader/processors/erb_template_processor.rb +77 -0
- data/lib/railroader/processors/erubis_template_processor.rb +92 -0
- data/lib/railroader/processors/gem_processor.rb +64 -0
- data/lib/railroader/processors/haml_template_processor.rb +191 -0
- data/lib/railroader/processors/lib/basic_processor.rb +37 -0
- data/lib/railroader/processors/lib/call_conversion_helper.rb +90 -0
- data/lib/railroader/processors/lib/find_all_calls.rb +224 -0
- data/lib/railroader/processors/lib/find_call.rb +183 -0
- data/lib/railroader/processors/lib/find_return_value.rb +166 -0
- data/lib/railroader/processors/lib/module_helper.rb +111 -0
- data/lib/railroader/processors/lib/processor_helper.rb +88 -0
- data/lib/railroader/processors/lib/rails2_config_processor.rb +145 -0
- data/lib/railroader/processors/lib/rails2_route_processor.rb +313 -0
- data/lib/railroader/processors/lib/rails3_config_processor.rb +132 -0
- data/lib/railroader/processors/lib/rails3_route_processor.rb +308 -0
- data/lib/railroader/processors/lib/render_helper.rb +181 -0
- data/lib/railroader/processors/lib/render_path.rb +107 -0
- data/lib/railroader/processors/lib/route_helper.rb +68 -0
- data/lib/railroader/processors/lib/safe_call_helper.rb +16 -0
- data/lib/railroader/processors/library_processor.rb +74 -0
- data/lib/railroader/processors/model_processor.rb +91 -0
- data/lib/railroader/processors/output_processor.rb +144 -0
- data/lib/railroader/processors/route_processor.rb +17 -0
- data/lib/railroader/processors/slim_template_processor.rb +111 -0
- data/lib/railroader/processors/template_alias_processor.rb +118 -0
- data/lib/railroader/processors/template_processor.rb +85 -0
- data/lib/railroader/report/config/remediation.yml +71 -0
- data/lib/railroader/report/ignore/config.rb +153 -0
- data/lib/railroader/report/ignore/interactive.rb +362 -0
- data/lib/railroader/report/pager.rb +112 -0
- data/lib/railroader/report/renderer.rb +24 -0
- data/lib/railroader/report/report_base.rb +292 -0
- data/lib/railroader/report/report_codeclimate.rb +79 -0
- data/lib/railroader/report/report_csv.rb +55 -0
- data/lib/railroader/report/report_hash.rb +23 -0
- data/lib/railroader/report/report_html.rb +216 -0
- data/lib/railroader/report/report_json.rb +45 -0
- data/lib/railroader/report/report_markdown.rb +107 -0
- data/lib/railroader/report/report_table.rb +117 -0
- data/lib/railroader/report/report_tabs.rb +17 -0
- data/lib/railroader/report/report_text.rb +198 -0
- data/lib/railroader/report/templates/controller_overview.html.erb +22 -0
- data/lib/railroader/report/templates/controller_warnings.html.erb +21 -0
- data/lib/railroader/report/templates/error_overview.html.erb +29 -0
- data/lib/railroader/report/templates/header.html.erb +58 -0
- data/lib/railroader/report/templates/ignored_warnings.html.erb +25 -0
- data/lib/railroader/report/templates/model_warnings.html.erb +21 -0
- data/lib/railroader/report/templates/overview.html.erb +38 -0
- data/lib/railroader/report/templates/security_warnings.html.erb +23 -0
- data/lib/railroader/report/templates/template_overview.html.erb +21 -0
- data/lib/railroader/report/templates/view_warnings.html.erb +34 -0
- data/lib/railroader/report/templates/warning_overview.html.erb +17 -0
- data/lib/railroader/report.rb +88 -0
- data/lib/railroader/rescanner.rb +483 -0
- data/lib/railroader/scanner.rb +321 -0
- data/lib/railroader/tracker/collection.rb +93 -0
- data/lib/railroader/tracker/config.rb +154 -0
- data/lib/railroader/tracker/constants.rb +171 -0
- data/lib/railroader/tracker/controller.rb +161 -0
- data/lib/railroader/tracker/library.rb +17 -0
- data/lib/railroader/tracker/model.rb +90 -0
- data/lib/railroader/tracker/template.rb +33 -0
- data/lib/railroader/tracker.rb +362 -0
- data/lib/railroader/util.rb +503 -0
- data/lib/railroader/version.rb +3 -0
- data/lib/railroader/warning.rb +294 -0
- data/lib/railroader/warning_codes.rb +117 -0
- data/lib/railroader.rb +544 -0
- data/lib/ruby_parser/bm_sexp.rb +626 -0
- data/lib/ruby_parser/bm_sexp_processor.rb +116 -0
- metadata +386 -0
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
require 'railroader/scanner'
|
|
2
|
+
require 'railroader/util'
|
|
3
|
+
require 'railroader/differ'
|
|
4
|
+
|
|
5
|
+
#Class for rescanning changed files after an initial scan
|
|
6
|
+
class Railroader::Rescanner < Railroader::Scanner
|
|
7
|
+
include Railroader::Util
|
|
8
|
+
KNOWN_TEMPLATE_EXTENSIONS = Railroader::TemplateParser::KNOWN_TEMPLATE_EXTENSIONS
|
|
9
|
+
SCAN_ORDER = [:config, :gemfile, :initializer, :lib, :routes, :template,
|
|
10
|
+
:model, :controller]
|
|
11
|
+
|
|
12
|
+
#Create new Rescanner to scan changed files
|
|
13
|
+
def initialize options, processor, changed_files
|
|
14
|
+
super(options, processor)
|
|
15
|
+
|
|
16
|
+
@paths = changed_files.map {|f| @app_tree.expand_path(f) }
|
|
17
|
+
@old_results = tracker.filtered_warnings #Old warnings from previous scan
|
|
18
|
+
@changes = nil #True if files had to be rescanned
|
|
19
|
+
@reindex = Set.new
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
#Runs checks.
|
|
23
|
+
#Will rescan files if they have not already been scanned
|
|
24
|
+
def recheck
|
|
25
|
+
rescan if @changes.nil?
|
|
26
|
+
|
|
27
|
+
tracker.run_checks if @changes
|
|
28
|
+
|
|
29
|
+
Railroader::RescanReport.new @old_results, tracker
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
#Rescans changed files
|
|
33
|
+
def rescan
|
|
34
|
+
tracker.template_cache.clear
|
|
35
|
+
|
|
36
|
+
paths_by_type = {}
|
|
37
|
+
|
|
38
|
+
SCAN_ORDER.each do |type|
|
|
39
|
+
paths_by_type[type] = []
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
@paths.each do |path|
|
|
43
|
+
type = file_type(path)
|
|
44
|
+
paths_by_type[type] << path unless type == :unknown
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
@changes = false
|
|
48
|
+
|
|
49
|
+
SCAN_ORDER.each do |type|
|
|
50
|
+
paths_by_type[type].each do |path|
|
|
51
|
+
Railroader.debug "Rescanning #{path} as #{type}"
|
|
52
|
+
|
|
53
|
+
if rescan_file path, type
|
|
54
|
+
@changes = true
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if @changes and not @reindex.empty?
|
|
60
|
+
tracker.reindex_call_sites @reindex
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
self
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
#Rescans a single file
|
|
67
|
+
def rescan_file path, type = nil
|
|
68
|
+
type ||= file_type path
|
|
69
|
+
|
|
70
|
+
unless @app_tree.path_exists?(path)
|
|
71
|
+
return rescan_deleted_file path, type
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
case type
|
|
75
|
+
when :controller
|
|
76
|
+
rescan_controller path
|
|
77
|
+
when :template
|
|
78
|
+
rescan_template path
|
|
79
|
+
when :model
|
|
80
|
+
rescan_model path
|
|
81
|
+
when :lib
|
|
82
|
+
rescan_lib path
|
|
83
|
+
when :config
|
|
84
|
+
process_config
|
|
85
|
+
when :initializer
|
|
86
|
+
rescan_initializer path
|
|
87
|
+
when :routes
|
|
88
|
+
rescan_routes
|
|
89
|
+
when :gemfile
|
|
90
|
+
if tracker.config.has_gem? :rails_xss and tracker.config.escape_html?
|
|
91
|
+
tracker.config.escape_html = false
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
process_gems
|
|
95
|
+
else
|
|
96
|
+
return false #Nothing to do, file hopefully does not need to be rescanned
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
true
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def rescan_controller path
|
|
103
|
+
controller = tracker.reset_controller path
|
|
104
|
+
paths = controller.nil? ? [path] : controller.files
|
|
105
|
+
parse_ruby_files(paths).each do |astfile|
|
|
106
|
+
process_controller astfile
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
#Process data flow and template rendering
|
|
110
|
+
#from the controller
|
|
111
|
+
tracker.controllers.each do |name, controller|
|
|
112
|
+
if controller.files.include?(path)
|
|
113
|
+
tracker.templates.each do |template_name, template|
|
|
114
|
+
next unless template.render_path
|
|
115
|
+
if template.render_path.include_controller? name
|
|
116
|
+
tracker.reset_template template_name
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
controller.src.each do |file, src|
|
|
121
|
+
@processor.process_controller_alias controller.name, src, nil, file
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
@reindex << :templates << :controllers
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def rescan_template path
|
|
130
|
+
return unless path.match KNOWN_TEMPLATE_EXTENSIONS and @app_tree.path_exists?(path)
|
|
131
|
+
|
|
132
|
+
template_name = template_path_to_name(path)
|
|
133
|
+
|
|
134
|
+
tracker.reset_template template_name
|
|
135
|
+
fp = Railroader::FileParser.new(tracker, @app_tree)
|
|
136
|
+
template_parser = Railroader::TemplateParser.new(tracker, fp)
|
|
137
|
+
template_parser.parse_template path, @app_tree.read_path(path)
|
|
138
|
+
process_template fp.file_list[:templates].first
|
|
139
|
+
|
|
140
|
+
@processor.process_template_alias tracker.templates[template_name]
|
|
141
|
+
|
|
142
|
+
rescan = Set.new
|
|
143
|
+
|
|
144
|
+
#Search for processed template and process it.
|
|
145
|
+
#Search for rendered versions of template and re-render (if necessary)
|
|
146
|
+
tracker.templates.each do |_name, template|
|
|
147
|
+
if template.file == path or template.file.nil?
|
|
148
|
+
next unless template.render_path and template.name.to_sym == template_name.to_sym
|
|
149
|
+
|
|
150
|
+
template.render_path.each do |from|
|
|
151
|
+
case from[:type]
|
|
152
|
+
when :template
|
|
153
|
+
rescan << [:template, from[:name]]
|
|
154
|
+
when :controller
|
|
155
|
+
rescan << [:controller, from[:class], from[:method]]
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
rescan.each do |r|
|
|
162
|
+
if r[0] == :controller
|
|
163
|
+
controller = tracker.controllers[r[1]]
|
|
164
|
+
|
|
165
|
+
controller.src.each do |file, src|
|
|
166
|
+
unless @paths.include? file
|
|
167
|
+
@processor.process_controller_alias controller.name, src, r[2], file
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
elsif r[0] == :template
|
|
171
|
+
template = tracker.templates[r[1]]
|
|
172
|
+
|
|
173
|
+
rescan_template template.file
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
@reindex << :templates
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def rescan_model path
|
|
181
|
+
num_models = tracker.models.length
|
|
182
|
+
model = tracker.reset_model path
|
|
183
|
+
paths = model.nil? ? [path] : model.files
|
|
184
|
+
parse_ruby_files(paths).each do |astfile|
|
|
185
|
+
process_model astfile.path, astfile.ast
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
#Only need to rescan other things if a model is added or removed
|
|
189
|
+
if num_models != tracker.models.length
|
|
190
|
+
process_template_data_flows
|
|
191
|
+
process_controller_data_flows
|
|
192
|
+
@reindex << :templates << :controllers
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
@reindex << :models
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def rescan_lib path
|
|
199
|
+
lib = tracker.reset_lib path
|
|
200
|
+
paths = lib.nil? ? [path] : lib.files
|
|
201
|
+
parse_ruby_files(paths).each do |astfile|
|
|
202
|
+
process_lib astfile
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
lib = nil
|
|
206
|
+
|
|
207
|
+
tracker.libs.each do |_name, library|
|
|
208
|
+
if library.files.include?(path)
|
|
209
|
+
lib = library
|
|
210
|
+
break
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
rescan_mixin lib if lib
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def rescan_routes
|
|
218
|
+
# Routes affect which controller methods are treated as actions
|
|
219
|
+
# which affects which templates are rendered, so routes, controllers,
|
|
220
|
+
# and templates rendered from controllers must be rescanned
|
|
221
|
+
tracker.reset_routes
|
|
222
|
+
tracker.reset_templates :only_rendered => true
|
|
223
|
+
process_routes
|
|
224
|
+
process_controller_data_flows
|
|
225
|
+
@reindex << :controllers << :templates
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def rescan_initializer path
|
|
229
|
+
parse_ruby_files([path]).each do |astfile|
|
|
230
|
+
process_initializer astfile
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
#Handle rescanning when a file is deleted
|
|
235
|
+
def rescan_deleted_file path, type
|
|
236
|
+
case type
|
|
237
|
+
when :controller
|
|
238
|
+
rescan_controller path
|
|
239
|
+
when :template
|
|
240
|
+
rescan_deleted_template path
|
|
241
|
+
when :model
|
|
242
|
+
rescan_model path
|
|
243
|
+
when :lib
|
|
244
|
+
rescan_deleted_lib path
|
|
245
|
+
when :initializer
|
|
246
|
+
rescan_deleted_initializer path
|
|
247
|
+
else
|
|
248
|
+
if remove_deleted_file path
|
|
249
|
+
return true
|
|
250
|
+
else
|
|
251
|
+
Railroader.notify "Ignoring deleted file: #{path}"
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
true
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def rescan_deleted_template path
|
|
259
|
+
return unless path.match KNOWN_TEMPLATE_EXTENSIONS
|
|
260
|
+
|
|
261
|
+
template_name = template_path_to_name(path)
|
|
262
|
+
|
|
263
|
+
#Remove template
|
|
264
|
+
tracker.reset_template template_name
|
|
265
|
+
|
|
266
|
+
rendered_from_controller = /^#{template_name}\.(.+Controller)#(.+)/
|
|
267
|
+
rendered_from_view = /^#{template_name}\.Template:(.+)/
|
|
268
|
+
|
|
269
|
+
#Remove any rendered versions, or partials rendered from it
|
|
270
|
+
tracker.templates.delete_if do |_name, template|
|
|
271
|
+
template.file == path or template.name.to_sym == template_name.to_sym
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def rescan_deleted_lib path
|
|
276
|
+
deleted_lib = nil
|
|
277
|
+
|
|
278
|
+
tracker.libs.delete_if do |_name, lib|
|
|
279
|
+
if lib.files.include?(path)
|
|
280
|
+
deleted_lib = lib
|
|
281
|
+
true
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
rescan_mixin deleted_lib if deleted_lib
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def rescan_deleted_initializer path
|
|
289
|
+
tracker.initializers.delete Pathname.new(path).basename.to_s
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
#Check controllers, templates, models and libs for data from file
|
|
293
|
+
#and delete it.
|
|
294
|
+
def remove_deleted_file path
|
|
295
|
+
deleted = false
|
|
296
|
+
|
|
297
|
+
[:controllers, :models, :libs].each do |collection|
|
|
298
|
+
tracker.send(collection).delete_if do |_name, data|
|
|
299
|
+
if data.files.include?(path)
|
|
300
|
+
deleted = true
|
|
301
|
+
true
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
tracker.templates.delete_if do |_name, data|
|
|
307
|
+
if data.file == path
|
|
308
|
+
deleted = true
|
|
309
|
+
true
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
deleted
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
#Guess at what kind of file the path contains
|
|
317
|
+
def file_type path
|
|
318
|
+
case path
|
|
319
|
+
when /\/app\/controllers/
|
|
320
|
+
:controller
|
|
321
|
+
when /\/app\/views/
|
|
322
|
+
:template
|
|
323
|
+
when /\/app\/models/
|
|
324
|
+
:model
|
|
325
|
+
when /\/lib/
|
|
326
|
+
:lib
|
|
327
|
+
when /\/config\/initializers/
|
|
328
|
+
:initializer
|
|
329
|
+
when /config\/routes\.rb/
|
|
330
|
+
:routes
|
|
331
|
+
when /\/config\/.+\.(rb|yml)/
|
|
332
|
+
:config
|
|
333
|
+
when /Gemfile|gems\./
|
|
334
|
+
:gemfile
|
|
335
|
+
else
|
|
336
|
+
:unknown
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def rescan_mixin lib
|
|
341
|
+
method_names = []
|
|
342
|
+
|
|
343
|
+
lib.each_method do |name, _meth|
|
|
344
|
+
method_names << name
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
to_rescan = []
|
|
348
|
+
|
|
349
|
+
#Rescan controllers that mixed in library
|
|
350
|
+
tracker.controllers.each do |_name, controller|
|
|
351
|
+
if controller.includes.include? lib.name
|
|
352
|
+
controller.files.each do |path|
|
|
353
|
+
unless @paths.include? path
|
|
354
|
+
to_rescan << path
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
to_rescan.each do |controller|
|
|
361
|
+
tracker.reset_controller controller
|
|
362
|
+
rescan_file controller
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
to_rescan = []
|
|
366
|
+
|
|
367
|
+
#Check if a method from this mixin was used to render a template.
|
|
368
|
+
#This is not precise, because a different controller might have the
|
|
369
|
+
#same method...
|
|
370
|
+
tracker.templates.each do |name, template|
|
|
371
|
+
next unless template.render_path
|
|
372
|
+
|
|
373
|
+
if template.render_path.include_any_method? method_names
|
|
374
|
+
name.to_s.match /^([^.]+)/
|
|
375
|
+
|
|
376
|
+
original = tracker.templates[$1.to_sym]
|
|
377
|
+
|
|
378
|
+
if original
|
|
379
|
+
to_rescan << [name, original.file]
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
to_rescan.each do |template|
|
|
385
|
+
tracker.reset_template template[0]
|
|
386
|
+
rescan_file template[1]
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def parse_ruby_files list
|
|
391
|
+
paths = list.select { |path| @app_tree.path_exists? path }
|
|
392
|
+
file_parser = Railroader::FileParser.new(tracker, @app_tree)
|
|
393
|
+
file_parser.parse_files paths, :rescan
|
|
394
|
+
file_parser.file_list[:rescan]
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
#Class to make reporting of rescan results simpler to deal with
|
|
399
|
+
class Railroader::RescanReport
|
|
400
|
+
include Railroader::Util
|
|
401
|
+
attr_reader :old_results, :new_results
|
|
402
|
+
|
|
403
|
+
def initialize old_results, tracker
|
|
404
|
+
@tracker = tracker
|
|
405
|
+
@old_results = old_results
|
|
406
|
+
@all_warnings = nil
|
|
407
|
+
@diff = nil
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
#Returns true if any warnings were found (new or old)
|
|
411
|
+
def any_warnings?
|
|
412
|
+
not all_warnings.empty?
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
#Returns an array of all warnings found
|
|
416
|
+
def all_warnings
|
|
417
|
+
@all_warnings ||= @tracker.filtered_warnings
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
#Returns an array of warnings which were in the old report but are not in the
|
|
421
|
+
#new report after rescanning
|
|
422
|
+
def fixed_warnings
|
|
423
|
+
diff[:fixed]
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
#Returns an array of warnings which were in the new report but were not in
|
|
427
|
+
#the old report
|
|
428
|
+
def new_warnings
|
|
429
|
+
diff[:new]
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
#Returns true if there are any new or fixed warnings
|
|
433
|
+
def warnings_changed?
|
|
434
|
+
not (diff[:new].empty? and diff[:fixed].empty?)
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
#Returns a hash of arrays for :new and :fixed warnings
|
|
438
|
+
def diff
|
|
439
|
+
@diff ||= Railroader::Differ.new(all_warnings, @old_results).diff
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
#Returns an array of warnings which were in the old report and the new report
|
|
443
|
+
def existing_warnings
|
|
444
|
+
@old ||= all_warnings.select do |w|
|
|
445
|
+
not new_warnings.include? w
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
#Output total, fixed, and new warnings
|
|
450
|
+
def to_s(verbose = false)
|
|
451
|
+
Railroader.load_railroader_dependency 'terminal-table'
|
|
452
|
+
|
|
453
|
+
if !verbose
|
|
454
|
+
<<-OUTPUT
|
|
455
|
+
Total warnings: #{all_warnings.length}
|
|
456
|
+
Fixed warnings: #{fixed_warnings.length}
|
|
457
|
+
New warnings: #{new_warnings.length}
|
|
458
|
+
OUTPUT
|
|
459
|
+
else
|
|
460
|
+
#Eventually move this to different method, or make default to_s
|
|
461
|
+
out = ""
|
|
462
|
+
|
|
463
|
+
{:fixed => fixed_warnings, :new => new_warnings, :existing => existing_warnings}.each do |warning_type, warnings|
|
|
464
|
+
if warnings.length > 0
|
|
465
|
+
out << "#{warning_type.to_s.titleize} warnings: #{warnings.length}\n"
|
|
466
|
+
|
|
467
|
+
table = Terminal::Table.new(:headings => ["Confidence", "Class", "Method", "Warning Type", "Message"]) do |t|
|
|
468
|
+
warnings.sort_by { |w| w.confidence}.each do |warning|
|
|
469
|
+
w = warning.to_row
|
|
470
|
+
|
|
471
|
+
w["Confidence"] = Railroader::Report::TEXT_CONFIDENCE[w["Confidence"]]
|
|
472
|
+
|
|
473
|
+
t << [w["Confidence"], w["Class"], w["Method"], w["Warning Type"], w["Message"]]
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
out << truncate_table(table.to_s)
|
|
477
|
+
end
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
out
|
|
481
|
+
end
|
|
482
|
+
end
|
|
483
|
+
end
|