diver_down 0.0.1.alpha14 → 0.0.1.alpha15
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 +4 -4
- data/exe/diver_down_web +2 -3
- data/lib/diver_down/version.rb +1 -1
- data/lib/diver_down/web/action.rb +92 -105
- data/lib/diver_down/web/definition_filter.rb +112 -0
- data/lib/diver_down/web/definition_module_dependencies.rb +79 -0
- data/lib/diver_down/web/definition_to_dot.rb +50 -105
- data/lib/diver_down/web/metadata/source_metadata.rb +14 -13
- data/lib/diver_down/web/metadata.rb +6 -1
- data/lib/diver_down/web.rb +44 -29
- data/web/assets/DyDCovOQ.css +1 -0
- data/web/assets/bundle.js +127 -134
- data/web/index.html +1 -1
- metadata +6 -5
- data/lib/diver_down/web/module_sources_filter.rb +0 -54
- data/web/assets/CFQbqqGu.css +0 -1
@@ -7,7 +7,6 @@ module DiverDown
|
|
7
7
|
class Web
|
8
8
|
class DefinitionToDot
|
9
9
|
ATTRIBUTE_DELIMITER = ' '
|
10
|
-
MODULE_DELIMITER = '::'
|
11
10
|
|
12
11
|
# Between modules is prominently distanced
|
13
12
|
MODULE_MINLEN = 3
|
@@ -31,18 +30,12 @@ module DiverDown
|
|
31
30
|
private
|
32
31
|
|
33
32
|
def source_to_h
|
34
|
-
modules = metadata.source(data.source_name).modules.map do
|
35
|
-
{
|
36
|
-
module_name: _1,
|
37
|
-
}
|
38
|
-
end
|
39
|
-
|
40
33
|
{
|
41
34
|
id:,
|
42
35
|
type: 'source',
|
43
36
|
source_name: data.source_name,
|
44
37
|
memo: metadata.source(data.source_name).memo,
|
45
|
-
|
38
|
+
module: metadata.source(data.source_name).module,
|
46
39
|
}
|
47
40
|
end
|
48
41
|
|
@@ -68,11 +61,7 @@ module DiverDown
|
|
68
61
|
{
|
69
62
|
id:,
|
70
63
|
type: 'module',
|
71
|
-
|
72
|
-
{
|
73
|
-
module_name: _1,
|
74
|
-
}
|
75
|
-
end,
|
64
|
+
module: data,
|
76
65
|
}
|
77
66
|
end
|
78
67
|
end
|
@@ -100,13 +89,13 @@ module DiverDown
|
|
100
89
|
|
101
90
|
# @param module_names [Array<String>]
|
102
91
|
# @return [String]
|
103
|
-
def
|
104
|
-
issued_metadata = @to_h.values.find { _1.type == :module && _1.data ==
|
92
|
+
def issue_module_id(modulee)
|
93
|
+
issued_metadata = @to_h.values.find { _1.type == :module && _1.data == modulee }
|
105
94
|
|
106
95
|
if issued_metadata
|
107
96
|
issued_metadata.id
|
108
97
|
else
|
109
|
-
build_dot_metadata_and_return_id(:module,
|
98
|
+
build_dot_metadata_and_return_id(:module, modulee)
|
110
99
|
end
|
111
100
|
end
|
112
101
|
|
@@ -186,60 +175,45 @@ module DiverDown
|
|
186
175
|
dependency_map = Hash.new { |h, k| h[k] = Hash.new { |hi, ki| hi[ki] = [] } }
|
187
176
|
|
188
177
|
definition.sources.sort_by(&:source_name).each do |source|
|
189
|
-
|
190
|
-
next if
|
178
|
+
source_module = metadata.source(source.source_name).module
|
179
|
+
next if source_module.nil?
|
191
180
|
|
192
181
|
source.dependencies.each do |dependency|
|
193
|
-
|
194
|
-
next if
|
182
|
+
dependency_module = metadata.source(dependency.source_name).module
|
183
|
+
next if dependency_module.nil?
|
195
184
|
|
196
|
-
dependency_map[
|
185
|
+
dependency_map[source_module][dependency_module].push(dependency)
|
197
186
|
end
|
198
187
|
end
|
199
188
|
|
200
189
|
# Remove duplicated prefix modules
|
201
|
-
|
202
|
-
uniq_modules
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
indexes = (0..(specific_module_names.length - 1)).to_a
|
211
|
-
|
212
|
-
chain_yield(indexes) do |index, next_proc|
|
213
|
-
module_names = specific_module_names[0..index]
|
214
|
-
module_name = specific_module_names[index]
|
215
|
-
|
216
|
-
io.puts %(subgraph "#{escape_quote(module_label(module_names))}" {)
|
217
|
-
io.indented do
|
218
|
-
io.puts %(id="#{@dot_metadata_store.issue_modules_id(module_names)}")
|
219
|
-
io.puts %(label="#{escape_quote(module_name)}")
|
220
|
-
io.puts %("#{escape_quote(module_name)}" #{build_attributes(label: module_name, id: @dot_metadata_store.issue_modules_id(module_names))})
|
221
|
-
|
222
|
-
next_proc&.call
|
223
|
-
end
|
224
|
-
io.puts '}'
|
225
|
-
end
|
190
|
+
uniq_modules = [*dependency_map.keys, *dependency_map.values.map(&:keys).flatten].uniq.sort
|
191
|
+
uniq_modules.reject!(&:nil?)
|
192
|
+
|
193
|
+
uniq_modules.each do |modulee|
|
194
|
+
io.puts %(subgraph "#{escape_quote(module_label(modulee))}" {)
|
195
|
+
io.indented do
|
196
|
+
io.puts %(id="#{@dot_metadata_store.issue_module_id(modulee)}")
|
197
|
+
io.puts %(label="#{escape_quote(modulee)}")
|
198
|
+
io.puts %("#{escape_quote(modulee)}" #{build_attributes(label: modulee, id: @dot_metadata_store.issue_module_id(modulee))})
|
226
199
|
end
|
227
|
-
|
228
|
-
io.write buf.string
|
200
|
+
io.puts '}'
|
229
201
|
end
|
230
202
|
|
231
|
-
dependency_map.each do |
|
232
|
-
|
203
|
+
dependency_map.keys.sort_by(&:to_s).each do |from_module|
|
204
|
+
dependency_map.fetch(from_module).keys.sort_by(&:to_s).each do |to_module|
|
205
|
+
all_dependencies = dependency_map.fetch(from_module).fetch(to_module)
|
206
|
+
|
233
207
|
# Do not render standalone source
|
234
208
|
# Do not render self-dependency
|
235
|
-
next if
|
209
|
+
next if from_module.nil? || to_module.empty? || from_module == to_module
|
236
210
|
|
237
211
|
dependencies = DiverDown::Definition::Dependency.combine(*all_dependencies)
|
238
212
|
|
239
213
|
dependencies.each do
|
240
214
|
attributes = {}
|
241
|
-
ltail = module_label(
|
242
|
-
lhead = module_label(
|
215
|
+
ltail = module_label(from_module)
|
216
|
+
lhead = module_label(to_module)
|
243
217
|
|
244
218
|
# Already rendered dependencies between modules
|
245
219
|
# Add the dependency to the edge of the compound
|
@@ -259,7 +233,7 @@ module DiverDown
|
|
259
233
|
minlen: MODULE_MINLEN
|
260
234
|
)
|
261
235
|
|
262
|
-
io.write(%("#{escape_quote(
|
236
|
+
io.write(%("#{escape_quote(from_module)}" -> "#{escape_quote(to_module)}"))
|
263
237
|
io.write(%( #{build_attributes(**attributes)}), indent: false) unless attributes.empty?
|
264
238
|
io.write("\n")
|
265
239
|
end
|
@@ -268,46 +242,38 @@ module DiverDown
|
|
268
242
|
end
|
269
243
|
|
270
244
|
def render_sources
|
271
|
-
# Hash{
|
272
|
-
# Hash{
|
273
|
-
|
274
|
-
metadata.source(source.source_name).
|
245
|
+
# Hash{ module => sources }
|
246
|
+
# Hash{ String => Array<DiverDown::Definition::Source> }
|
247
|
+
by_module = definition.sources.group_by do |source|
|
248
|
+
metadata.source(source.source_name).module
|
275
249
|
end
|
276
250
|
|
277
251
|
# Render subgraph for each module and its sources second
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
# Render dependencies last
|
282
|
-
definition.sources.sort_by(&:source_name).each do |source|
|
283
|
-
insert_dependencies(source)
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
def render_nested_modules_sources(by_modules, nested_modules, prefix = [])
|
288
|
-
nested_modules.each do |module_name, next_nested_modules|
|
289
|
-
module_names = prefix + [module_name].compact
|
290
|
-
sources = (by_modules[module_names] || []).sort_by(&:source_name)
|
252
|
+
by_module.keys.sort_by(&:to_s).each do |modulee|
|
253
|
+
sources = by_module.fetch(modulee).sort_by(&:source_name)
|
291
254
|
|
292
|
-
if
|
255
|
+
if modulee.nil?
|
293
256
|
sources.each do |source|
|
294
257
|
io.puts build_source_node(source)
|
295
258
|
end
|
296
259
|
else
|
297
|
-
io.puts %(subgraph "#{escape_quote(module_label(
|
260
|
+
io.puts %(subgraph "#{escape_quote(module_label(modulee))}" {)
|
298
261
|
io.indented do
|
299
|
-
io.puts %(id="#{@dot_metadata_store.
|
300
|
-
io.puts %(label="#{escape_quote(
|
262
|
+
io.puts %(id="#{@dot_metadata_store.issue_module_id(modulee)}")
|
263
|
+
io.puts %(label="#{escape_quote(modulee)}")
|
301
264
|
|
302
265
|
sources.each do |source|
|
303
266
|
io.puts build_source_node(source)
|
304
267
|
end
|
305
|
-
|
306
|
-
render_nested_modules_sources(by_modules, next_nested_modules, module_names)
|
307
268
|
end
|
308
269
|
io.puts '}'
|
309
270
|
end
|
310
271
|
end
|
272
|
+
|
273
|
+
# Render dependencies last
|
274
|
+
definition.sources.sort_by(&:source_name).each do |source|
|
275
|
+
insert_dependencies(source)
|
276
|
+
end
|
311
277
|
end
|
312
278
|
|
313
279
|
def build_source_node(source)
|
@@ -317,8 +283,8 @@ module DiverDown
|
|
317
283
|
def insert_dependencies(source)
|
318
284
|
source.dependencies.each do
|
319
285
|
attributes = {}
|
320
|
-
ltail = module_label(
|
321
|
-
lhead = module_label(
|
286
|
+
ltail = module_label(metadata.source(source.source_name).module)
|
287
|
+
lhead = module_label(metadata.source(_1.source_name).module)
|
322
288
|
|
323
289
|
if @compound && (ltail || lhead)
|
324
290
|
# Rendering of dependencies between modules is done only once
|
@@ -343,7 +309,8 @@ module DiverDown
|
|
343
309
|
)
|
344
310
|
else
|
345
311
|
attributes.merge!(
|
346
|
-
id: @dot_metadata_store.issue_dependency_id(_1)
|
312
|
+
id: @dot_metadata_store.issue_dependency_id(_1),
|
313
|
+
minlen: MODULE_MINLEN
|
347
314
|
)
|
348
315
|
end
|
349
316
|
|
@@ -401,37 +368,15 @@ module DiverDown
|
|
401
368
|
@io = old_io
|
402
369
|
end
|
403
370
|
|
404
|
-
def module_label(
|
405
|
-
return if
|
371
|
+
def module_label(modulee)
|
372
|
+
return if modulee.nil?
|
406
373
|
|
407
|
-
"cluster_#{
|
374
|
+
"cluster_#{modulee}"
|
408
375
|
end
|
409
376
|
|
410
377
|
def escape_quote(string)
|
411
378
|
string.to_s.gsub(/"/, '\"')
|
412
379
|
end
|
413
|
-
|
414
|
-
# from [["A"], ["A", "B"], ["A", "C"], ["D"]] to { "A" => { "B" => {}, "C" => {} }, "D" => {} }
|
415
|
-
def array_to_hash(array)
|
416
|
-
hash = {}
|
417
|
-
array.each do |sub_array|
|
418
|
-
current_hash = hash
|
419
|
-
|
420
|
-
if sub_array.empty?
|
421
|
-
current_hash[nil] = {}
|
422
|
-
else
|
423
|
-
sub_array.each_with_index do |element, index|
|
424
|
-
if index == sub_array.length - 1
|
425
|
-
current_hash[element] = {}
|
426
|
-
else
|
427
|
-
current_hash[element] ||= {}
|
428
|
-
current_hash = current_hash[element]
|
429
|
-
end
|
430
|
-
end
|
431
|
-
end
|
432
|
-
end
|
433
|
-
hash
|
434
|
-
end
|
435
380
|
end
|
436
381
|
end
|
437
382
|
end
|
@@ -6,17 +6,16 @@ module DiverDown
|
|
6
6
|
class SourceMetadata
|
7
7
|
BLANK_MEMO = ''
|
8
8
|
BLANK_RE = /\A\s*\z/
|
9
|
-
BLANK_ARRAY = [].freeze
|
10
9
|
private_constant(:BLANK_MEMO)
|
11
10
|
private_constant(:BLANK_RE)
|
12
|
-
private_constant(:BLANK_ARRAY)
|
13
11
|
|
14
|
-
attr_reader :memo, :
|
12
|
+
attr_reader :memo, :module
|
15
13
|
|
16
14
|
# @param source_name [String]
|
17
|
-
|
15
|
+
# NOTE: `module` is a reserved keyword in Ruby
|
16
|
+
def initialize(memo: BLANK_MEMO, modulee: nil)
|
18
17
|
@memo = memo
|
19
|
-
@
|
18
|
+
@module = modulee
|
20
19
|
end
|
21
20
|
|
22
21
|
# @param memo [String]
|
@@ -25,17 +24,19 @@ module DiverDown
|
|
25
24
|
@memo = memo.strip
|
26
25
|
end
|
27
26
|
|
28
|
-
# @param
|
27
|
+
# @param modulee [String, nil]
|
29
28
|
# @return [void]
|
30
|
-
def
|
31
|
-
@
|
32
|
-
|
33
|
-
|
29
|
+
def module=(modulee)
|
30
|
+
@module = if modulee.nil? || BLANK_RE.match?(modulee)
|
31
|
+
nil
|
32
|
+
else
|
33
|
+
modulee.strip
|
34
|
+
end
|
34
35
|
end
|
35
36
|
|
36
37
|
# @return [Boolean]
|
37
|
-
def
|
38
|
-
|
38
|
+
def module?
|
39
|
+
!@module.nil?
|
39
40
|
end
|
40
41
|
|
41
42
|
# @return [Hash]
|
@@ -43,7 +44,7 @@ module DiverDown
|
|
43
44
|
hash = {}
|
44
45
|
|
45
46
|
hash[:memo] = memo unless memo == BLANK_MEMO
|
46
|
-
hash[:
|
47
|
+
hash[:module] = @module unless @module.nil?
|
47
48
|
|
48
49
|
hash
|
49
50
|
end
|
@@ -54,7 +54,12 @@ module DiverDown
|
|
54
54
|
# NOTE: This is for backward compatibility. It will be removed in the future.
|
55
55
|
(loaded[:sources] || loaded || []).each do |source_name, source_hash|
|
56
56
|
source(source_name).memo = source_hash[:memo] if source_hash[:memo]
|
57
|
-
|
57
|
+
|
58
|
+
if source_hash[:modules].is_a?(Array)
|
59
|
+
source(source_name).module = source_hash[:modules][0]
|
60
|
+
elsif source_hash[:module]
|
61
|
+
source(source_name).module = source_hash[:module]
|
62
|
+
end
|
58
63
|
end
|
59
64
|
|
60
65
|
loaded[:source_alias]&.each do |alias_name, source_names|
|
data/lib/diver_down/web.rb
CHANGED
@@ -15,22 +15,28 @@ module DiverDown
|
|
15
15
|
require 'diver_down/web/indented_string_io'
|
16
16
|
require 'diver_down/web/definition_store'
|
17
17
|
require 'diver_down/web/definition_loader'
|
18
|
+
require 'diver_down/web/definition_module_dependencies'
|
18
19
|
require 'diver_down/web/source_alias_resolver'
|
19
|
-
require 'diver_down/web/
|
20
|
+
require 'diver_down/web/definition_filter'
|
20
21
|
|
21
22
|
# For development
|
22
23
|
autoload :DevServerMiddleware, 'diver_down/web/dev_server_middleware'
|
23
24
|
|
25
|
+
# @return [DiverDown::Web::DefinitionStore]
|
26
|
+
def self.store
|
27
|
+
@store ||= DiverDown::Web::DefinitionStore.new
|
28
|
+
end
|
29
|
+
|
24
30
|
# @param definition_dir [String]
|
25
31
|
# @param metadata [DiverDown::Web::Metadata]
|
26
32
|
# @param store [DiverDown::Web::DefinitionStore]
|
27
|
-
def initialize(definition_dir:, metadata
|
28
|
-
@store = store
|
33
|
+
def initialize(definition_dir:, metadata:)
|
29
34
|
@metadata = metadata
|
30
35
|
@files_server = Rack::Files.new(File.join(WEB_DIR))
|
31
36
|
|
32
37
|
definition_files = ::Dir["#{definition_dir}/**/*.{yml,yaml,msgpack,json}"].sort
|
33
38
|
@total_definition_files_size = definition_files.size
|
39
|
+
@action = nil
|
34
40
|
|
35
41
|
load_definition_files_on_thread(definition_files)
|
36
42
|
end
|
@@ -39,11 +45,14 @@ module DiverDown
|
|
39
45
|
# @return [Array[Integer, Hash, Array]]
|
40
46
|
def call(env)
|
41
47
|
request = Rack::Request.new(env)
|
42
|
-
|
48
|
+
|
49
|
+
if @action&.store.object_id != self.class.store.object_id
|
50
|
+
@action = DiverDown::Web::Action.new(store: self.class.store, metadata: @metadata)
|
51
|
+
end
|
43
52
|
|
44
53
|
case [request.request_method, request.path]
|
45
54
|
in ['GET', %r{\A/api/definitions\.json\z}]
|
46
|
-
action.definitions(
|
55
|
+
@action.definitions(
|
47
56
|
page: request.params['page']&.to_i || 1,
|
48
57
|
per: request.params['per']&.to_i || 100,
|
49
58
|
title: request.params['title'] || '',
|
@@ -51,51 +60,48 @@ module DiverDown
|
|
51
60
|
definition_group: request.params['definition_group'] || ''
|
52
61
|
)
|
53
62
|
in ['GET', %r{\A/api/sources\.json\z}]
|
54
|
-
action.sources
|
63
|
+
@action.sources
|
55
64
|
in ['GET', %r{\A/api/modules\.json\z}]
|
56
|
-
action.modules
|
57
|
-
in ['GET', %r{\A/api/modules/(?<
|
58
|
-
|
59
|
-
action.module(
|
60
|
-
in ['GET', %r{\A/api/module_definitions/(?<modules>.+)\.json\z}]
|
61
|
-
modules = CGI.unescape(Regexp.last_match[:modules]).split('/')
|
62
|
-
compound = request.params['compound'] == '1'
|
63
|
-
concentrate = request.params['concentrate'] == '1'
|
64
|
-
only_module = request.params['only_module'] == '1'
|
65
|
-
action.module_definition(compound, concentrate, only_module, modules)
|
65
|
+
@action.modules
|
66
|
+
in ['GET', %r{\A/api/modules/(?<modulee>[^/]+)\.json\z}]
|
67
|
+
modulee = CGI.unescape(Regexp.last_match[:modulee])
|
68
|
+
@action.module(modulee)
|
66
69
|
in ['GET', %r{\A/api/definitions/(?<bit_id>\d+)\.json\z}]
|
67
70
|
bit_id = Regexp.last_match[:bit_id].to_i
|
68
71
|
compound = request.params['compound'] == '1'
|
69
72
|
concentrate = request.params['concentrate'] == '1'
|
70
73
|
only_module = request.params['only_module'] == '1'
|
71
|
-
|
74
|
+
remove_internal_sources = request.params['remove_internal_sources'] == '1'
|
75
|
+
focus_modules = request.params['focus_modules'] || []
|
76
|
+
modules = request.params['modules'] || []
|
77
|
+
@action.combine_definitions(bit_id, compound, concentrate, only_module, remove_internal_sources, focus_modules, modules)
|
72
78
|
in ['GET', %r{\A/api/sources/(?<source>[^/]+)\.json\z}]
|
73
79
|
source = Regexp.last_match[:source]
|
74
|
-
action.source(source)
|
75
|
-
in ['POST', %r{\A/api/sources/(?<source>[^/]+)/
|
80
|
+
@action.source(source)
|
81
|
+
in ['POST', %r{\A/api/sources/(?<source>[^/]+)/module.json\z}]
|
76
82
|
source = Regexp.last_match[:source]
|
77
|
-
|
78
|
-
action.
|
83
|
+
modulee = request.params['module'] || ''
|
84
|
+
@action.set_module(source, modulee)
|
79
85
|
in ['POST', %r{\A/api/sources/(?<source>[^/]+)/memo.json\z}]
|
80
86
|
source = Regexp.last_match[:source]
|
81
87
|
memo = request.params['memo'] || ''
|
82
|
-
action.set_memo(source, memo)
|
88
|
+
@action.set_memo(source, memo)
|
83
89
|
in ['GET', %r{\A/api/pid\.json\z}]
|
84
|
-
action.pid
|
90
|
+
@action.pid
|
85
91
|
in ['GET', %r{\A/api/initialization_status\.json\z}]
|
86
|
-
action.initialization_status(@total_definition_files_size)
|
92
|
+
@action.initialization_status(@total_definition_files_size)
|
87
93
|
in ['GET', %r{\A/api/source_aliases\.json\z}]
|
88
|
-
action.source_aliases
|
94
|
+
@action.source_aliases
|
89
95
|
in ['POST', %r{\A/api/source_aliases\.json\z}]
|
90
96
|
alias_name = request.params['alias_name']
|
91
97
|
old_alias_name = request.params['old_alias_name'] # NOTE: nillable
|
92
98
|
source_names = request.params['source_names'] || []
|
93
99
|
|
94
|
-
action.update_source_alias(alias_name, old_alias_name, source_names)
|
100
|
+
@action.update_source_alias(alias_name, old_alias_name, source_names)
|
95
101
|
in ['GET', %r{\A/assets/}]
|
96
102
|
@files_server.call(env)
|
97
103
|
in ['GET', /\.json\z/], ['POST', /\.json\z/]
|
98
|
-
action.not_found
|
104
|
+
@action.not_found
|
99
105
|
else
|
100
106
|
@files_server.call(env.merge('PATH_INFO' => '/index.html'))
|
101
107
|
end
|
@@ -105,20 +111,29 @@ module DiverDown
|
|
105
111
|
|
106
112
|
def load_definition_files_on_thread(definition_files)
|
107
113
|
definition_loader = DiverDown::Web::DefinitionLoader.new
|
114
|
+
store = self.class.store
|
108
115
|
|
109
116
|
Thread.new do
|
110
117
|
loop do
|
111
118
|
break if definition_files.empty?
|
112
119
|
|
120
|
+
# If store is changed in test, stop loading.
|
121
|
+
break if store != self.class.store
|
122
|
+
|
113
123
|
definition_file = definition_files.shift
|
114
124
|
definition = definition_loader.load_file(definition_file)
|
115
125
|
|
116
126
|
# No needed to synchronize because this is executed on a single thread.
|
117
|
-
|
127
|
+
store.set(definition)
|
118
128
|
end
|
119
129
|
|
120
130
|
# Cache combined_definition
|
121
|
-
|
131
|
+
store.combined_definition
|
132
|
+
|
133
|
+
# For development
|
134
|
+
if ENV['DIVER_DOWN_DIR']
|
135
|
+
File.write(File.expand_path('../../tmp/combined_definition.yml', __dir__), store.combined_definition.to_h.to_yaml)
|
136
|
+
end
|
122
137
|
end
|
123
138
|
end
|
124
139
|
end
|