appmap 0.51.1 → 0.51.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a51a7f69ebbca275fd9a215a52cd3e4d8db739e8e6cecf3eb522871f23295b5
4
- data.tar.gz: 58f033b5c4f8756532dd3dbe83c631b36560e3215a342f804916de205f53cb56
3
+ metadata.gz: 194f53c7e13b466fef13720503fe9f8c1ee149af724884224ce03753cc0d658f
4
+ data.tar.gz: e9c7d5578da6d9e80d9c06e70deaa32fe7da785ab94840a09739e474601a8cac
5
5
  SHA512:
6
- metadata.gz: e52a4b23f708892b12c3ca68a2b5e3c13a2c9b1d1b52057ede1548faa7c7d03914296ebb1402c7c1cd1f0540df1d6182ffa09de2cf3558410d499703bc8b352f
7
- data.tar.gz: 32201a386bc48ef35395e702a46661f78b12c4b15cab6214203e91e3599537cc53742f5ef2848ecf3d73b3c6c007413b55b4ea22bc4f8c83131733b9b2ace4a3
6
+ metadata.gz: 82da50065460e83bbbd0f35bdce8e04924d9e0388f1da9ba30cea0637594dce2d8dc3a9364c55e1492924e73dfb91cf163eac7fe7028e4b48eb5cb3c34a96c92
7
+ data.tar.gz: 96198ca1c1f3c5bdcd4d75ce275f8e76a39ff9c36cbaf314c642d91dac54403426a28b54c5a478a58295560af804dc3f44ac33ff9b1b710b1d401fab4c72cb75
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## [0.51.2](https://github.com/applandinc/appmap-ruby/compare/v0.51.1...v0.51.2) (2021-06-22)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Be less verbose when logging config messages ([fba2fd0](https://github.com/applandinc/appmap-ruby/commit/fba2fd01dbb7b1830194b49285654d6657d1c786))
7
+ * Method objects must support eql? and hash to ensure they are unique in a Set ([f4d5b11](https://github.com/applandinc/appmap-ruby/commit/f4d5b11db90aa50bdd1f768e039927833e83c30f))
8
+ * Require rails, then appmap/railtie ([07967a1](https://github.com/applandinc/appmap-ruby/commit/07967a14609891544a7dd874c648b7ef5a505f21))
9
+ * Use a hybrid strategy to auto-requiring appmap modules ([6fb09b8](https://github.com/applandinc/appmap-ruby/commit/6fb09b8c0bd55b1e29967d459ce1e2bd5b1ba9fe))
10
+
1
11
  ## [0.51.1](https://github.com/applandinc/appmap-ruby/compare/v0.51.0...v0.51.1) (2021-06-21)
2
12
 
3
13
 
data/appmap.gemspec CHANGED
@@ -22,6 +22,9 @@ Gem::Specification.new do |spec|
22
22
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
23
  spec.files = `git ls-files --no-deleted`.split("
24
24
  ")
25
+ spec.bindir = 'exe'
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+
25
28
  spec.extensions << "ext/appmap/extconf.rb"
26
29
 
27
30
  spec.require_paths = ['lib']
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'gli'
5
+
6
+ require 'appmap'
7
+
8
+ class App
9
+ extend GLI::App
10
+
11
+ program_desc 'CLI tool to be used by IDEs for AppMap setup and configuration'
12
+
13
+ version AppMap::VERSION
14
+
15
+ subcommand_option_handling :normal
16
+ arguments :strict
17
+ preserve_argv true
18
+
19
+ desc 'AppMap configuration file name'
20
+ default_value ENV['APPMAP_CONFIG'] || AppMap::DEFAULT_CONFIG_FILE_PATH
21
+ arg_name 'filename'
22
+ flag %i[c config]
23
+
24
+ desc 'Creates base configuration file for the current project'
25
+ command :init do |c|
26
+ c.action do
27
+ require 'appmap/command/init'
28
+ AppMap::Command::Init.new(@config_file).perform
29
+ end
30
+ end
31
+
32
+ pre do |global, _, _, _|
33
+ @config_file = global[:config]
34
+ @config = interpret_config_option(@config_file) if File.exist?(@config_file)
35
+ true
36
+ end
37
+
38
+ class << self
39
+ protected
40
+
41
+ def interpret_config_option(fname)
42
+ AppMap::Config.load_from_file fname
43
+ end
44
+ end
45
+ end
46
+
47
+ exit App.run(ARGV)
data/lib/appmap.rb CHANGED
@@ -51,7 +51,7 @@ module AppMap
51
51
  # Call this function before the program code is loaded by the Ruby VM, otherwise
52
52
  # the load events won't be seen and the hooks won't activate.
53
53
  def initialize_configuration(config_file_path = default_config_file_path)
54
- warn "Configuring AppMap from path #{config_file_path}"
54
+ startup_message "Configuring AppMap from path #{config_file_path}"
55
55
  Config.load_from_file(config_file_path).tap do |configuration|
56
56
  self.configuration = configuration
57
57
  Hook.new(configuration).enable
@@ -109,20 +109,60 @@ module AppMap
109
109
  @metadata ||= Metadata.detect.freeze
110
110
  @metadata.deep_dup
111
111
  end
112
+
113
+ def startup_message(msg)
114
+ if defined?(::Rails) && defined?(::Rails.logger) && ::Rails.logger
115
+ ::Rails.logger.debug msg
116
+ elsif ENV['DEBUG'] == 'true'
117
+ warn msg
118
+ end
119
+ end
112
120
  end
113
121
  end
114
122
 
115
- if defined?(::Rails::Railtie)
116
- require 'appmap/railtie'
117
- end
123
+ lambda do
124
+ Initializer = Struct.new(:class_name, :module_name, :gem_module_name)
118
125
 
119
- if defined?(::RSpec)
120
- require 'appmap/rspec'
121
- end
126
+ INITIALIZERS = {
127
+ 'Rails::Railtie' => Initializer.new('AppMap::Railtie', 'appmap/railtie', 'railtie'),
128
+ 'RSpec' => Initializer.new('AppMap::RSpec', 'appmap/rspec', 'rspec-core'),
129
+ 'Minitest::Unit::TestCase' => Initializer.new('AppMap::Minitest', 'appmap/minitest', 'minitest')
130
+ }
122
131
 
123
- # defined?(::Minitest) returns nil...
124
- if Gem.loaded_specs['minitest']
125
- require 'appmap/minitest'
126
- end
132
+ TracePoint.new(:class) do |tp|
133
+ cls_name = tp.self.name
134
+ initializers = INITIALIZERS.delete(cls_name)
135
+ if initializers
136
+ initializers = [ initializers ] unless initializers.is_a?(Array)
137
+ next if Object.const_defined?(initializers.first.class_name)
138
+
139
+ gem_module_name = initializers.first.gem_module_name
140
+
141
+ AppMap.startup_message AppMap::Util.color(<<~LOAD_MSG, :magenta)
142
+ When 'appmap' was loaded, '#{gem_module_name}' had not been loaded yet. Now '#{gem_module_name}' has
143
+ just been loaded, so the following AppMap modules will be automatically required:
144
+
145
+ #{initializers.map(&:module_name).join("\n")}
146
+
147
+ To suppress this message, ensure '#{gem_module_name}' appears before 'appmap' in your Gemfile.
148
+ LOAD_MSG
149
+ initializers.each do |init|
150
+ require init.module_name
151
+ end
152
+ end
153
+ end.enable
154
+
155
+ if defined?(::Rails::Railtie)
156
+ require 'appmap/railtie'
157
+ end
158
+
159
+ if defined?(::RSpec)
160
+ require 'appmap/rspec'
161
+ end
162
+
163
+ if defined?(::Minitest)
164
+ require 'appmap/minitest'
165
+ end
166
+ end.call
127
167
 
128
168
  AppMap.initialize_configuration if ENV['APPMAP'] == 'true'
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'appmap/service/guesser'
5
+ require 'appmap/util'
6
+
7
+ module AppMap
8
+ module Command
9
+ InitStruct = Struct.new(:config_file)
10
+
11
+ class Init < InitStruct
12
+ def perform
13
+ if File.exist?(config_file)
14
+ puts AppMap::Util.color(%(The AppMap config file #{config_file} already exists.), :magenta)
15
+ return
16
+ end
17
+
18
+ ensure_directory_exists
19
+
20
+ config = {
21
+ 'name' => Service::Guesser.guess_name,
22
+ 'packages' => Service::Guesser.guess_paths.map { |path| { 'path' => path } }
23
+ }
24
+ content = YAML.dump(config).gsub("---\n", '')
25
+
26
+ File.write(config_file, content)
27
+ puts AppMap::Util.color(
28
+ %(The following AppMap config file #{config_file} has been created:),
29
+ :green
30
+ )
31
+ puts content
32
+ end
33
+
34
+ private
35
+
36
+ def ensure_directory_exists
37
+ dirname = File.dirname(config_file)
38
+ FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
39
+ end
40
+ end
41
+ end
42
+ end
data/lib/appmap/config.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require 'yaml'
4
4
  require 'appmap/handler/net_http'
5
5
  require 'appmap/handler/rails/template'
6
+ require 'appmap/service/guesser'
6
7
 
7
8
  module AppMap
8
9
  class Config
@@ -284,7 +285,7 @@ module AppMap
284
285
  settings, the appmap gem will try and guess some reasonable defaults.
285
286
  To suppress this message, create the file:
286
287
 
287
- #{Pathname.new(config_file_name).expand_path}.
288
+ #{Pathname.new(config_file_name).expand_path}
288
289
 
289
290
  Here are the default settings that will be used in the meantime. You can
290
291
  copy and paste this example to start your appmap.yml.
@@ -308,7 +309,7 @@ module AppMap
308
309
 
309
310
  # Loads configuration from a Hash.
310
311
  def load(config_data)
311
- name = config_data['name'] || guess_name
312
+ name = config_data['name'] || Service::Guesser.guess_name
312
313
  config_params = {
313
314
  exclude: config_data['exclude']
314
315
  }.compact
@@ -344,33 +345,13 @@ module AppMap
344
345
  end
345
346
  end.compact
346
347
  else
347
- Array(guess_paths).map do |path|
348
+ Array(Service::Guesser.guess_paths).map do |path|
348
349
  Package.build_from_path(path)
349
350
  end
350
351
  end
351
352
 
352
353
  Config.new name, config_params
353
354
  end
354
-
355
- def guess_name
356
- reponame = lambda do
357
- next unless File.directory?('.git')
358
-
359
- repo_name = `git config --get remote.origin.url`.strip
360
- repo_name.split('/').last.split('.').first unless repo_name == ''
361
- end
362
- dirname = -> { Dir.pwd.split('/').last }
363
-
364
- reponame.() || dirname.()
365
- end
366
-
367
- def guess_paths
368
- if defined?(::Rails)
369
- %w[app/controllers app/models]
370
- elsif File.directory?('lib')
371
- %w[lib]
372
- end
373
- end
374
355
  end
375
356
 
376
357
  def to_h
@@ -14,16 +14,30 @@ module AppMap
14
14
  # The class name is generated from the template path. The package name is
15
15
  # 'app/views', and the method name is 'render'. The source location of the method
16
16
  # is, of course, the path to the view template.
17
- TemplateMethod = Struct.new(:path) do
18
- private_instance_methods :path
17
+ class TemplateMethod
19
18
  attr_reader :class_name
20
-
19
+
20
+ attr_reader :path
21
+ private_instance_methods :path
22
+
21
23
  def initialize(path)
22
- super
24
+ @path = path
23
25
 
24
26
  @class_name = path.parameterize.underscore
25
27
  end
26
-
28
+
29
+ def id
30
+ [ package, path, name ]
31
+ end
32
+
33
+ def hash
34
+ id.hash
35
+ end
36
+
37
+ def eql?(other)
38
+ other.is_a?(TemplateMethod) && id.eql?(other.id)
39
+ end
40
+
27
41
  def package
28
42
  'app/views'
29
43
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AppMap
4
+ module Service
5
+ class Guesser
6
+ POSSIBLE_PATHS = %w[app/controllers app/models lib]
7
+ class << self
8
+ def guess_name
9
+ reponame = lambda do
10
+ next unless File.directory?('.git')
11
+
12
+ repo_name = `git config --get remote.origin.url`.strip
13
+ repo_name.split('/').last.split('.').first unless repo_name == ''
14
+ end
15
+ dirname = -> { Dir.pwd.split('/').last }
16
+
17
+ reponame.() || dirname.()
18
+ end
19
+
20
+ def guess_paths
21
+ POSSIBLE_PATHS.select { |path| File.directory?(path) }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
data/lib/appmap/trace.rb CHANGED
@@ -2,10 +2,12 @@
2
2
 
3
3
  module AppMap
4
4
  module Trace
5
- class RubyMethod
5
+ class RubyMethod < SimpleDelegator
6
6
  attr_reader :class_name, :static
7
7
 
8
8
  def initialize(package, class_name, method, static)
9
+ super(method)
10
+
9
11
  @package = package
10
12
  @class_name = class_name
11
13
  @method = method
@@ -111,7 +113,7 @@ module AppMap
111
113
  @last_package_for_thread[Thread.current.object_id] = package if package
112
114
  @events << event
113
115
  static = event.static if event.respond_to?(:static)
114
- @methods << Trace::RubyMethod.new(package, defined_class, method, static) \
116
+ record_method Trace::RubyMethod.new(package, defined_class, method, static) \
115
117
  if package && defined_class && method && (event.event == :call)
116
118
  end
117
119
 
@@ -3,9 +3,10 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.51.1'
6
+ VERSION = '0.51.2'
7
7
 
8
8
  APPMAP_FORMAT_VERSION = '1.5.1'
9
9
 
10
10
  DEFAULT_APPMAP_DIR = 'tmp/appmap'.freeze
11
+ DEFAULT_CONFIG_FILE_PATH = 'appmap.yml'.freeze
11
12
  end
data/test/cli_test.rb ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'test_helper'
5
+
6
+ class CLITest < Minitest::Test
7
+ CONFIG_FILENAME = '123.yml'
8
+ SUBFOLDER_CONFIG_FILEPATH = 'conf/123.yml'
9
+ EXPECTED_CONFIG_CONTENT = %(name: appmap-ruby
10
+ packages:
11
+ - path: lib
12
+ )
13
+
14
+ def test_init_when_config_exists
15
+ output = `./exe/appmap-agent-setup init`
16
+ assert_equal 0, $CHILD_STATUS.exitstatus
17
+ assert_includes output, 'The AppMap config file appmap.yml already exists.'
18
+ end
19
+
20
+ def test_init_with_custom_config_filename
21
+ output = `./exe/appmap-agent-setup -c #{CONFIG_FILENAME} init`
22
+ assert_equal 0, $CHILD_STATUS.exitstatus
23
+ assert_includes output, "The following AppMap config file #{CONFIG_FILENAME} has been created:"
24
+ assert_equal EXPECTED_CONFIG_CONTENT, File.read(CONFIG_FILENAME)
25
+ ensure
26
+ File.delete(CONFIG_FILENAME) if File.exist?(CONFIG_FILENAME)
27
+ end
28
+
29
+ def test_init_with_custom_config_file_in_subfolder
30
+ output = `./exe/appmap-agent-setup -c #{SUBFOLDER_CONFIG_FILEPATH} init`
31
+ assert_equal 0, $CHILD_STATUS.exitstatus
32
+ assert_includes output, "The following AppMap config file #{SUBFOLDER_CONFIG_FILEPATH} has been created:"
33
+ assert_equal EXPECTED_CONFIG_CONTENT, File.read(SUBFOLDER_CONFIG_FILEPATH)
34
+ ensure
35
+ File.delete(SUBFOLDER_CONFIG_FILEPATH) if File.exist?(SUBFOLDER_CONFIG_FILEPATH)
36
+ end
37
+ end
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.51.1
4
+ version: 0.51.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Gilpin
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-21 00:00:00.000000000 Z
11
+ date: 2021-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -307,7 +307,8 @@ dependencies:
307
307
  description:
308
308
  email:
309
309
  - kgilpin@gmail.com
310
- executables: []
310
+ executables:
311
+ - appmap-agent-setup
311
312
  extensions:
312
313
  - ext/appmap/extconf.rb
313
314
  extra_rdoc_files: []
@@ -335,12 +336,14 @@ files:
335
336
  - examples/mock_webapp/lib/mock_webapp/controller.rb
336
337
  - examples/mock_webapp/lib/mock_webapp/request.rb
337
338
  - examples/mock_webapp/lib/mock_webapp/user.rb
339
+ - exe/appmap-agent-setup
338
340
  - ext/appmap/appmap.c
339
341
  - ext/appmap/extconf.rb
340
342
  - lib/appmap.rb
341
343
  - lib/appmap/algorithm/prune_class_map.rb
342
344
  - lib/appmap/algorithm/stats.rb
343
345
  - lib/appmap/class_map.rb
346
+ - lib/appmap/command/init.rb
344
347
  - lib/appmap/command/record.rb
345
348
  - lib/appmap/command/stats.rb
346
349
  - lib/appmap/config.rb
@@ -360,6 +363,7 @@ files:
360
363
  - lib/appmap/railtie.rb
361
364
  - lib/appmap/record.rb
362
365
  - lib/appmap/rspec.rb
366
+ - lib/appmap/service/guesser.rb
363
367
  - lib/appmap/trace.rb
364
368
  - lib/appmap/util.rb
365
369
  - lib/appmap/version.rb
@@ -556,6 +560,7 @@ files:
556
560
  - spec/spec_helper.rb
557
561
  - spec/util_spec.rb
558
562
  - test/bundle_vendor_test.rb
563
+ - test/cli_test.rb
559
564
  - test/cucumber_test.rb
560
565
  - test/expectations/openssl_test_key_sign1.json
561
566
  - test/expectations/openssl_test_key_sign2.json