appmap 0.43.0 → 0.44.0
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/.travis.yml +17 -2
- data/CHANGELOG.md +9 -0
- data/README.md +28 -1
- data/appmap.gemspec +0 -2
- data/lib/appmap.rb +3 -7
- data/lib/appmap/class_map.rb +7 -10
- data/lib/appmap/command/record.rb +1 -1
- data/lib/appmap/config.rb +88 -28
- data/lib/appmap/cucumber.rb +1 -1
- data/lib/appmap/hook.rb +25 -20
- data/lib/appmap/middleware/remote_recording.rb +1 -1
- data/lib/appmap/minitest.rb +22 -20
- data/lib/appmap/record.rb +1 -1
- data/lib/appmap/rspec.rb +22 -21
- data/lib/appmap/util.rb +16 -0
- data/lib/appmap/version.rb +1 -1
- data/patch +1447 -0
- data/spec/abstract_controller_base_spec.rb +2 -4
- data/spec/class_map_spec.rb +3 -11
- data/spec/config_spec.rb +31 -1
- data/spec/fixtures/hook/custom_instance_method.rb +11 -0
- data/spec/fixtures/hook/method_named_call.rb +11 -0
- data/spec/hook_spec.rb +134 -10
- data/test/expectations/openssl_test_key_sign1.json +2 -4
- data/test/gem_test.rb +1 -1
- data/test/rspec_test.rb +0 -13
- metadata +7 -7
- data/exe/appmap +0 -154
- data/test/cli_test.rb +0 -116
@@ -27,6 +27,8 @@ describe 'Rails' do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
let(:appmap) { JSON.parse File.read File.join tmpdir, 'appmap/rspec', appmap_json_file }
|
30
|
+
let(:appmap_json_path) { File.join(tmpdir, 'appmap/rspec', appmap_json_file) }
|
31
|
+
let(:appmap) { JSON.parse File.read(appmap_json_path) }
|
30
32
|
let(:events) { appmap['events'] }
|
31
33
|
|
32
34
|
describe 'an API route' do
|
@@ -35,10 +37,6 @@ describe 'Rails' do
|
|
35
37
|
'Api_UsersController_POST_api_users_with_required_parameters_creates_a_user.appmap.json'
|
36
38
|
end
|
37
39
|
|
38
|
-
it 'inventory file is printed' do
|
39
|
-
expect(File).to exist(File.join(tmpdir, 'appmap/rspec/Inventory.appmap.json'))
|
40
|
-
end
|
41
|
-
|
42
40
|
it 'http_server_request is recorded in the appmap' do
|
43
41
|
expect(events).to include(
|
44
42
|
hash_including(
|
data/spec/class_map_spec.rb
CHANGED
@@ -4,18 +4,10 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe 'AppMap::ClassMap' do
|
6
6
|
describe '.build_from_methods' do
|
7
|
-
it 'includes
|
8
|
-
map = AppMap.class_map([scoped_method(method
|
7
|
+
it 'includes method comment' do
|
8
|
+
map = AppMap.class_map([scoped_method((method :test_method))])
|
9
9
|
function = dig_map(map, 5)[0]
|
10
|
-
expect(function
|
11
|
-
expect(function[:comment]).to include 'test method comment'
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'can omit source code even if available' do
|
15
|
-
map = AppMap.class_map([scoped_method((method :test_method))], include_source: false)
|
16
|
-
function = dig_map(map, 5)[0]
|
17
|
-
expect(function).to_not include(:source)
|
18
|
-
expect(function).to_not include(:comment)
|
10
|
+
expect(function).to include(:comment)
|
19
11
|
end
|
20
12
|
|
21
13
|
# test method comment
|
data/spec/config_spec.rb
CHANGED
@@ -17,10 +17,40 @@ describe AppMap::Config, docker: false do
|
|
17
17
|
path: 'path-2',
|
18
18
|
exclude: [ 'exclude-1' ]
|
19
19
|
}
|
20
|
+
],
|
21
|
+
functions: [
|
22
|
+
{
|
23
|
+
package: 'pkg',
|
24
|
+
class: 'cls',
|
25
|
+
function: 'fn',
|
26
|
+
label: 'lbl'
|
27
|
+
}
|
20
28
|
]
|
21
29
|
}.deep_stringify_keys!
|
22
30
|
config = AppMap::Config.load(config_data)
|
23
31
|
|
24
|
-
|
32
|
+
config_expectation = {
|
33
|
+
exclude: [],
|
34
|
+
name: 'test',
|
35
|
+
packages: [
|
36
|
+
{
|
37
|
+
path: 'path-1'
|
38
|
+
},
|
39
|
+
{
|
40
|
+
path: 'path-2',
|
41
|
+
exclude: [ 'exclude-1' ]
|
42
|
+
}
|
43
|
+
],
|
44
|
+
functions: [
|
45
|
+
{
|
46
|
+
package: 'pkg',
|
47
|
+
class: 'cls',
|
48
|
+
functions: [ :fn ],
|
49
|
+
labels: ['lbl']
|
50
|
+
}
|
51
|
+
]
|
52
|
+
}.deep_stringify_keys!
|
53
|
+
|
54
|
+
expect(config.to_h.deep_stringify_keys!).to eq(config_expectation)
|
25
55
|
end
|
26
56
|
end
|
data/spec/hook_spec.rb
CHANGED
@@ -64,13 +64,144 @@ describe 'AppMap class Hooking', docker: false do
|
|
64
64
|
it 'excludes named classes and methods' do
|
65
65
|
load 'spec/fixtures/hook/exclude.rb'
|
66
66
|
package = AppMap::Config::Package.build_from_path('spec/fixtures/hook/exclude.rb')
|
67
|
-
config = AppMap::Config.new('hook_spec', [ package ], %w[ExcludeTest])
|
67
|
+
config = AppMap::Config.new('hook_spec', [ package ], exclude: %w[ExcludeTest])
|
68
68
|
AppMap.configuration = config
|
69
69
|
|
70
70
|
expect(config.never_hook?(ExcludeTest.new.method(:instance_method))).to be_truthy
|
71
71
|
expect(config.never_hook?(ExcludeTest.method(:cls_method))).to be_truthy
|
72
72
|
end
|
73
73
|
|
74
|
+
it "handles an instance method named 'call' without issues" do
|
75
|
+
events_yaml = <<~YAML
|
76
|
+
---
|
77
|
+
- :id: 1
|
78
|
+
:event: :call
|
79
|
+
:defined_class: MethodNamedCall
|
80
|
+
:method_id: call
|
81
|
+
:path: spec/fixtures/hook/method_named_call.rb
|
82
|
+
:lineno: 8
|
83
|
+
:static: false
|
84
|
+
:parameters:
|
85
|
+
- :name: :a
|
86
|
+
:class: Integer
|
87
|
+
:value: '1'
|
88
|
+
:kind: :req
|
89
|
+
- :name: :b
|
90
|
+
:class: Integer
|
91
|
+
:value: '2'
|
92
|
+
:kind: :req
|
93
|
+
- :name: :c
|
94
|
+
:class: Integer
|
95
|
+
:value: '3'
|
96
|
+
:kind: :req
|
97
|
+
- :name: :d
|
98
|
+
:class: Integer
|
99
|
+
:value: '4'
|
100
|
+
:kind: :req
|
101
|
+
- :name: :e
|
102
|
+
:class: Integer
|
103
|
+
:value: '5'
|
104
|
+
:kind: :req
|
105
|
+
:receiver:
|
106
|
+
:class: MethodNamedCall
|
107
|
+
:value: MethodNamedCall
|
108
|
+
- :id: 2
|
109
|
+
:event: :return
|
110
|
+
:parent_id: 1
|
111
|
+
:return_value:
|
112
|
+
:class: String
|
113
|
+
:value: 1 2 3 4 5
|
114
|
+
YAML
|
115
|
+
|
116
|
+
_, tracer = test_hook_behavior 'spec/fixtures/hook/method_named_call.rb', events_yaml do
|
117
|
+
expect(MethodNamedCall.new.call(1, 2, 3, 4, 5)).to eq('1 2 3 4 5')
|
118
|
+
end
|
119
|
+
class_map = AppMap.class_map(tracer.event_methods)
|
120
|
+
expect(Diffy::Diff.new(<<~CLASSMAP, YAML.dump(class_map)).to_s).to eq('')
|
121
|
+
---
|
122
|
+
- :name: spec/fixtures/hook/method_named_call.rb
|
123
|
+
:type: package
|
124
|
+
:children:
|
125
|
+
- :name: MethodNamedCall
|
126
|
+
:type: class
|
127
|
+
:children:
|
128
|
+
- :name: call
|
129
|
+
:type: function
|
130
|
+
:location: spec/fixtures/hook/method_named_call.rb:8
|
131
|
+
:static: false
|
132
|
+
CLASSMAP
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'can custom hook and label a function' do
|
136
|
+
events_yaml = <<~YAML
|
137
|
+
---
|
138
|
+
- :id: 1
|
139
|
+
:event: :call
|
140
|
+
:defined_class: CustomInstanceMethod
|
141
|
+
:method_id: say_default
|
142
|
+
:path: spec/fixtures/hook/custom_instance_method.rb
|
143
|
+
:lineno: 8
|
144
|
+
:static: false
|
145
|
+
:parameters: []
|
146
|
+
:receiver:
|
147
|
+
:class: CustomInstanceMethod
|
148
|
+
:value: CustomInstance Method fixture
|
149
|
+
- :id: 2
|
150
|
+
:event: :return
|
151
|
+
:parent_id: 1
|
152
|
+
:return_value:
|
153
|
+
:class: String
|
154
|
+
:value: default
|
155
|
+
YAML
|
156
|
+
|
157
|
+
config = AppMap::Config.load({
|
158
|
+
functions: [
|
159
|
+
{
|
160
|
+
package: 'hook_spec',
|
161
|
+
class: 'CustomInstanceMethod',
|
162
|
+
functions: [ :say_default ],
|
163
|
+
labels: ['cowsay']
|
164
|
+
}
|
165
|
+
]
|
166
|
+
}.deep_stringify_keys)
|
167
|
+
|
168
|
+
load 'spec/fixtures/hook/custom_instance_method.rb'
|
169
|
+
hook_cls = CustomInstanceMethod
|
170
|
+
method = hook_cls.instance_method(:say_default)
|
171
|
+
|
172
|
+
require 'appmap/hook/method'
|
173
|
+
hook_method = AppMap::Hook::Method.new(config.package_for_method(method), hook_cls, method)
|
174
|
+
hook_method.activate
|
175
|
+
|
176
|
+
tracer = AppMap.tracing.trace
|
177
|
+
AppMap::Event.reset_id_counter
|
178
|
+
begin
|
179
|
+
expect(CustomInstanceMethod.new.say_default).to eq('default')
|
180
|
+
ensure
|
181
|
+
AppMap.tracing.delete(tracer)
|
182
|
+
end
|
183
|
+
|
184
|
+
events = collect_events(tracer).to_yaml
|
185
|
+
|
186
|
+
expect(Diffy::Diff.new(events_yaml, events).to_s).to eq('')
|
187
|
+
class_map = AppMap.class_map(tracer.event_methods)
|
188
|
+
expect(Diffy::Diff.new(<<~CLASSMAP, YAML.dump(class_map)).to_s).to eq('')
|
189
|
+
---
|
190
|
+
- :name: hook_spec
|
191
|
+
:type: package
|
192
|
+
:children:
|
193
|
+
- :name: CustomInstanceMethod
|
194
|
+
:type: class
|
195
|
+
:children:
|
196
|
+
- :name: say_default
|
197
|
+
:type: function
|
198
|
+
:location: spec/fixtures/hook/custom_instance_method.rb:8
|
199
|
+
:static: false
|
200
|
+
:labels:
|
201
|
+
- cowsay
|
202
|
+
CLASSMAP
|
203
|
+
end
|
204
|
+
|
74
205
|
it 'parses labels from comments' do
|
75
206
|
_, tracer = invoke_test_file 'spec/fixtures/hook/labels.rb' do
|
76
207
|
ClassWithLabel.new.fn_with_label
|
@@ -91,9 +222,6 @@ describe 'AppMap class Hooking', docker: false do
|
|
91
222
|
:labels:
|
92
223
|
- has-fn-label
|
93
224
|
:comment: "# @label has-fn-label\\n"
|
94
|
-
:source: |2
|
95
|
-
def fn_with_label
|
96
|
-
end
|
97
225
|
YAML
|
98
226
|
end
|
99
227
|
|
@@ -148,10 +276,6 @@ describe 'AppMap class Hooking', docker: false do
|
|
148
276
|
:type: function
|
149
277
|
:location: spec/fixtures/hook/instance_method.rb:8
|
150
278
|
:static: false
|
151
|
-
:source: |2
|
152
|
-
def say_default
|
153
|
-
'default'
|
154
|
-
end
|
155
279
|
YAML
|
156
280
|
end
|
157
281
|
|
@@ -746,6 +870,7 @@ describe 'AppMap class Hooking', docker: false do
|
|
746
870
|
end
|
747
871
|
secure_compare_event = YAML.load(events).find { |evt| evt[:defined_class] == 'ActiveSupport::SecurityUtils' }
|
748
872
|
secure_compare_event.delete(:lineno)
|
873
|
+
secure_compare_event.delete(:path)
|
749
874
|
|
750
875
|
expect(Diffy::Diff.new(<<~YAML, secure_compare_event.to_yaml).to_s).to eq('')
|
751
876
|
---
|
@@ -753,7 +878,6 @@ describe 'AppMap class Hooking', docker: false do
|
|
753
878
|
:event: :call
|
754
879
|
:defined_class: ActiveSupport::SecurityUtils
|
755
880
|
:method_id: secure_compare
|
756
|
-
:path: lib/active_support/security_utils.rb
|
757
881
|
:static: true
|
758
882
|
:parameters:
|
759
883
|
- :name: :a
|
@@ -837,7 +961,7 @@ describe 'AppMap class Hooking', docker: false do
|
|
837
961
|
entry = cm[1][:children][0][:children][0][:children][0]
|
838
962
|
# Sanity check, make sure we got the right one
|
839
963
|
expect(entry[:name]).to eq('secure_compare')
|
840
|
-
expect(entry[:labels]).to eq(%w[
|
964
|
+
expect(entry[:labels]).to eq(%w[crypto.secure_compare])
|
841
965
|
end
|
842
966
|
end
|
843
967
|
|
@@ -11,8 +11,7 @@
|
|
11
11
|
"name": "sign",
|
12
12
|
"type": "function",
|
13
13
|
"location": "lib/openssl_key_sign.rb:10",
|
14
|
-
"static": true
|
15
|
-
"source": " def Example.sign\n key = OpenSSL::PKey::RSA.new 2048\n\n document = 'the document'\n\n digest = OpenSSL::Digest::SHA256.new\n key.sign digest, document\n end\n"
|
14
|
+
"static": true
|
16
15
|
}
|
17
16
|
]
|
18
17
|
}
|
@@ -40,8 +39,7 @@
|
|
40
39
|
"location": "OpenSSL::PKey::PKey#sign",
|
41
40
|
"static": false,
|
42
41
|
"labels": [
|
43
|
-
"
|
44
|
-
"crypto"
|
42
|
+
"crypto.pkey"
|
45
43
|
]
|
46
44
|
}
|
47
45
|
]
|
data/test/gem_test.rb
CHANGED
@@ -26,7 +26,7 @@ class MinitestTest < Minitest::Test
|
|
26
26
|
assert_equal 2, events.size
|
27
27
|
assert_equal 'call', events.first['event']
|
28
28
|
assert_equal 'default_parser', events.first['method_id']
|
29
|
-
|
29
|
+
assert_match /\lib\/parser\/base\.rb$/, events.first['path']
|
30
30
|
assert_equal 'return', events.second['event']
|
31
31
|
assert_equal 1, events.second['parent_id']
|
32
32
|
end
|
data/test/rspec_test.rb
CHANGED
@@ -18,19 +18,6 @@ class RSpecTest < Minitest::Test
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
def test_inventory
|
22
|
-
perform_test 'plain_hello_spec' do
|
23
|
-
appmap_file = 'tmp/appmap/rspec/Inventory.appmap.json'
|
24
|
-
|
25
|
-
assert File.file?(appmap_file), 'appmap output file does not exist'
|
26
|
-
appmap = JSON.parse(File.read(appmap_file))
|
27
|
-
assert_equal AppMap::APPMAP_FORMAT_VERSION, appmap['version']
|
28
|
-
assert_includes appmap.keys, 'metadata'
|
29
|
-
metadata = appmap['metadata']
|
30
|
-
assert_equal 'Inventory', metadata['name']
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
21
|
def test_record_decorated_rspec
|
35
22
|
perform_test 'decorated_hello_spec' do
|
36
23
|
appmap_file = 'tmp/appmap/rspec/Hello_says_hello.appmap.json'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appmap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.44.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Gilpin
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -307,8 +307,7 @@ dependencies:
|
|
307
307
|
description:
|
308
308
|
email:
|
309
309
|
- kgilpin@gmail.com
|
310
|
-
executables:
|
311
|
-
- appmap
|
310
|
+
executables: []
|
312
311
|
extensions:
|
313
312
|
- ext/appmap/extconf.rb
|
314
313
|
extra_rdoc_files: []
|
@@ -334,7 +333,6 @@ files:
|
|
334
333
|
- examples/mock_webapp/lib/mock_webapp/controller.rb
|
335
334
|
- examples/mock_webapp/lib/mock_webapp/request.rb
|
336
335
|
- examples/mock_webapp/lib/mock_webapp/user.rb
|
337
|
-
- exe/appmap
|
338
336
|
- ext/appmap/appmap.c
|
339
337
|
- ext/appmap/extconf.rb
|
340
338
|
- lib/appmap.rb
|
@@ -379,16 +377,19 @@ files:
|
|
379
377
|
- lore/public/stylesheets/style.css
|
380
378
|
- package-lock.json
|
381
379
|
- package.json
|
380
|
+
- patch
|
382
381
|
- spec/abstract_controller_base_spec.rb
|
383
382
|
- spec/class_map_spec.rb
|
384
383
|
- spec/config_spec.rb
|
385
384
|
- spec/fixtures/hook/attr_accessor.rb
|
386
385
|
- spec/fixtures/hook/compare.rb
|
387
386
|
- spec/fixtures/hook/constructor.rb
|
387
|
+
- spec/fixtures/hook/custom_instance_method.rb
|
388
388
|
- spec/fixtures/hook/exception_method.rb
|
389
389
|
- spec/fixtures/hook/exclude.rb
|
390
390
|
- spec/fixtures/hook/instance_method.rb
|
391
391
|
- spec/fixtures/hook/labels.rb
|
392
|
+
- spec/fixtures/hook/method_named_call.rb
|
392
393
|
- spec/fixtures/hook/singleton_method.rb
|
393
394
|
- spec/fixtures/rack_users_app/.dockerignore
|
394
395
|
- spec/fixtures/rack_users_app/.gitignore
|
@@ -550,7 +551,6 @@ files:
|
|
550
551
|
- spec/remote_recording_spec.rb
|
551
552
|
- spec/spec_helper.rb
|
552
553
|
- spec/util_spec.rb
|
553
|
-
- test/cli_test.rb
|
554
554
|
- test/cucumber_test.rb
|
555
555
|
- test/expectations/openssl_test_key_sign1.json
|
556
556
|
- test/expectations/openssl_test_key_sign2.json
|
data/exe/appmap
DELETED
@@ -1,154 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'gli'
|
5
|
-
|
6
|
-
ENV['APPMAP_INITIALIZE'] = 'false'
|
7
|
-
|
8
|
-
require 'appmap'
|
9
|
-
require 'appmap/version'
|
10
|
-
|
11
|
-
# AppMap CLI.
|
12
|
-
module AppMap
|
13
|
-
class App
|
14
|
-
extend GLI::App
|
15
|
-
|
16
|
-
program_desc 'AppMap client'
|
17
|
-
|
18
|
-
version AppMap::VERSION
|
19
|
-
|
20
|
-
subcommand_option_handling :normal
|
21
|
-
arguments :strict
|
22
|
-
preserve_argv true
|
23
|
-
|
24
|
-
class << self
|
25
|
-
protected
|
26
|
-
|
27
|
-
def default_appmap_file
|
28
|
-
ENV['APPMAP_FILE'] || 'appmap.json'
|
29
|
-
end
|
30
|
-
|
31
|
-
def output_file_flag(c, default_value: nil)
|
32
|
-
c.desc 'Name of the output file'
|
33
|
-
c.long_desc <<~DESC
|
34
|
-
Use a single dash '-' for stdout.
|
35
|
-
DESC
|
36
|
-
c.default_value default_value if default_value
|
37
|
-
c.arg_name 'filename'
|
38
|
-
c.flag %i[o output]
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
desc 'AppMap configuration file name'
|
43
|
-
default_value ENV['APPMAP_CONFIG'] || 'appmap.yml'
|
44
|
-
arg_name 'filename'
|
45
|
-
flag %i[c config]
|
46
|
-
|
47
|
-
desc 'Record the execution of a program and generate an AppMap.'
|
48
|
-
arg_name 'program'
|
49
|
-
command :record do |c|
|
50
|
-
output_file_flag(c, default_value: default_appmap_file)
|
51
|
-
|
52
|
-
c.action do |_, _, args|
|
53
|
-
# My subcommand name
|
54
|
-
ARGV.shift
|
55
|
-
|
56
|
-
# Consume the :output option, if provided
|
57
|
-
if %w[-o --output].find { |arg_name| ARGV[0] == arg_name.to_s }
|
58
|
-
ARGV.shift
|
59
|
-
ARGV.shift
|
60
|
-
end
|
61
|
-
|
62
|
-
# Name of the program to execute. GLI will ensure that it's present.
|
63
|
-
program = args.shift or help_now!("'program' argument is required")
|
64
|
-
|
65
|
-
# Also pop the program name from ARGV, because the command will use raw ARGV
|
66
|
-
# to load the extra arguments into this Ruby process.
|
67
|
-
ARGV.shift
|
68
|
-
|
69
|
-
require 'appmap/command/record'
|
70
|
-
AppMap::Command::Record.new(@config, program).perform do |version, metadata, class_map, events|
|
71
|
-
@output_file.write JSON.generate(version: version,
|
72
|
-
metadata: metadata,
|
73
|
-
classMap: class_map,
|
74
|
-
events: events)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
desc 'Calculate and print statistics of scenario files.'
|
80
|
-
arg_name 'filename'
|
81
|
-
command :stats do |c|
|
82
|
-
output_file_flag(c, default_value: '-')
|
83
|
-
|
84
|
-
c.desc 'Display format for the result (text | json)'
|
85
|
-
c.default_value 'text'
|
86
|
-
c.flag %i[f format]
|
87
|
-
|
88
|
-
c.desc 'Maximum number of lines to display for each stat'
|
89
|
-
c.flag %i[l limit]
|
90
|
-
|
91
|
-
c.action do |_, options, args|
|
92
|
-
require 'appmap/command/stats'
|
93
|
-
|
94
|
-
limit = options[:limit].to_i if options[:limit]
|
95
|
-
|
96
|
-
# Name of the file to analyze. GLI will ensure that it's present.
|
97
|
-
filenames = args
|
98
|
-
help_now!("'filename' argument is required") if filenames.empty?
|
99
|
-
|
100
|
-
require 'appmap/algorithm/stats'
|
101
|
-
result = filenames.inject(::AppMap::Algorithm::Stats::Result.new([], [])) do |stats_result, filename|
|
102
|
-
appmap = begin
|
103
|
-
JSON.parse(File.read(filename))
|
104
|
-
rescue JSON::ParserError
|
105
|
-
STDERR.puts "#{filename} is not valid JSON : #{$!}"
|
106
|
-
nil
|
107
|
-
end
|
108
|
-
stats_result.tap do
|
109
|
-
if appmap
|
110
|
-
limit = options[:limit].to_i if options[:limit]
|
111
|
-
stats_for_file = AppMap::Command::Stats.new(appmap).perform(limit: limit)
|
112
|
-
stats_result.merge!(stats_for_file)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
result.sort!
|
118
|
-
result.limit!(limit) if limit
|
119
|
-
|
120
|
-
display = case options[:format]
|
121
|
-
when 'json'
|
122
|
-
JSON.pretty_generate(result.as_json)
|
123
|
-
else
|
124
|
-
result.as_text
|
125
|
-
end
|
126
|
-
@output_file.write display
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
pre do |global, _, options, _|
|
131
|
-
@config = interpret_config_option(global[:config])
|
132
|
-
@output_file = interpret_output_file_option(options[:output])
|
133
|
-
|
134
|
-
true
|
135
|
-
end
|
136
|
-
|
137
|
-
class << self
|
138
|
-
protected
|
139
|
-
|
140
|
-
def interpret_config_option(fname)
|
141
|
-
AppMap.initialize fname
|
142
|
-
end
|
143
|
-
|
144
|
-
def interpret_output_file_option(file_name)
|
145
|
-
Hash.new { |_, fname| -> { File.new(fname, 'w') } }.tap do |open_output_file|
|
146
|
-
open_output_file[nil] = -> { nil }
|
147
|
-
open_output_file['-'] = -> { $stdout }
|
148
|
-
end[file_name].call
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
exit AppMap::App.run(ARGV)
|