appmap 0.50.0 → 0.52.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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -1
  3. data/CHANGELOG.md +38 -0
  4. data/Rakefile +21 -5
  5. data/appmap.gemspec +11 -6
  6. data/exe/appmap-agent-setup +47 -0
  7. data/exe/appmap-inspect +7 -0
  8. data/lib/appmap.rb +56 -17
  9. data/lib/appmap/command/agent_setup/init.rb +44 -0
  10. data/lib/appmap/command/inspect.rb +27 -0
  11. data/lib/appmap/command_error.rb +13 -0
  12. data/lib/appmap/config.rb +96 -29
  13. data/lib/appmap/handler/rails/template.rb +19 -5
  14. data/lib/appmap/node_cli.rb +59 -0
  15. data/lib/appmap/service/guesser.rb +26 -0
  16. data/lib/appmap/trace.rb +4 -2
  17. data/lib/appmap/util.rb +52 -2
  18. data/lib/appmap/version.rb +4 -1
  19. data/package.json +6 -7
  20. data/spec/config_spec.rb +21 -0
  21. data/spec/fixtures/rails5_users_app/docker-compose.yml +1 -1
  22. data/spec/fixtures/rails6_users_app/Dockerfile +9 -0
  23. data/spec/fixtures/rails6_users_app/docker-compose.yml +1 -1
  24. data/spec/hook_spec.rb +2 -2
  25. data/spec/{abstract_controller_base_spec.rb → rails_recording_spec.rb} +39 -19
  26. data/spec/rails_spec_helper.rb +22 -0
  27. data/spec/record_net_http_spec.rb +1 -1
  28. data/test/agent_setup_cli_test.rb +37 -0
  29. data/test/fixtures/gem_test/Gemfile +1 -0
  30. data/test/inspect_cli_test.rb +12 -0
  31. data/yarn.lock +477 -0
  32. metadata +23 -47
  33. data/lib/appmap/algorithm/prune_class_map.rb +0 -67
  34. data/lib/appmap/algorithm/stats.rb +0 -91
  35. data/lib/appmap/command/record.rb +0 -38
  36. data/lib/appmap/command/stats.rb +0 -14
  37. data/lore/pages/2019-05-21-install-and-record/index.pug +0 -51
  38. data/lore/pages/2019-05-21-install-and-record/install_example_appmap.png +0 -0
  39. data/lore/pages/2019-05-21-install-and-record/metadata.yml +0 -5
  40. data/lore/pages/layout.pug +0 -66
  41. data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.css +0 -1912
  42. data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.css.map +0 -1
  43. data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.min.css +0 -7
  44. data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-grid.min.css.map +0 -1
  45. data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.css +0 -331
  46. data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.css.map +0 -1
  47. data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.min.css +0 -8
  48. data/lore/public/lib/bootstrap-4.1.3/css/bootstrap-reboot.min.css.map +0 -1
  49. data/lore/public/lib/bootstrap-4.1.3/css/bootstrap.css +0 -9030
  50. data/lore/public/lib/bootstrap-4.1.3/css/bootstrap.css.map +0 -1
  51. data/lore/public/lib/bootstrap-4.1.3/css/bootstrap.min.css +0 -7
  52. data/lore/public/lib/bootstrap-4.1.3/css/bootstrap.min.css.map +0 -1
  53. data/lore/public/stylesheets/style.css +0 -8
  54. data/package-lock.json +0 -1064
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce006905408a0ee15ccaee33ecb13e8bfbf1bc7b93f3cc4cbb105e2be9849bee
4
- data.tar.gz: 4f73e289a332301d6efbf0c7e8985b5e62a8a030f90c4265b221fc1d67c801be
3
+ metadata.gz: 91abfbaf6b18062625413f1a4ba9a465325af82734a04ab875bb8b4092f3bc34
4
+ data.tar.gz: 9fb260bc1fb09cc1a6bc6771114b8306f596d1595bcaf1234dd346abe871d3b7
5
5
  SHA512:
6
- metadata.gz: 86108afa917712908800f9303368ee48c8b0bf7d66892e6aadd76a18d76d355106f751984579bf57f9fdd876f7e4071f75a0d6cdf4fd90dfa5ce90a93d1ed9a1
7
- data.tar.gz: b62b7793fd03c9d3cb43792b0a9b056547b4dd9f75a6b31f582a12d7a19cfdf4eaee7f566b27eaaf9a36dd4477afa396184b31bc753858b979ac5fb6804d3027
6
+ metadata.gz: 4eb0fe09e7657fbb3541c17b047e2c0c24cb171201828b684353fd2de94fcca216f84b2776ce4a1f57fe1e721aaeb66c55fbea5fc627d9529f4bf687805a1079
7
+ data.tar.gz: 938da5ae0d846bc3e2c7f571ef836fe35f4d0fefebe5af9f5b5846b949c87c1cc1812881a973168c014cc789a0b6bb1ee9eb556d11406e846f99fdecd0eeb04a
data/.travis.yml CHANGED
@@ -26,7 +26,9 @@ before_install:
26
26
  if [ ! -z "$DOCKERHUB_PASSWORD" ] && [ ! -z "$DOCKERHUB_USERNAME" ]; then
27
27
  echo "$DOCKERHUB_PASSWORD" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin ;
28
28
  fi
29
-
29
+ - |
30
+ nvm install --lts \
31
+ && nvm use --lts
30
32
 
31
33
  # GEM_ALTERNATIVE_NAME only needed for deployment
32
34
  jobs:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,41 @@
1
+ # [0.52.0](https://github.com/applandinc/appmap-ruby/compare/v0.51.3...v0.52.0) (2021-06-22)
2
+
3
+
4
+ ### Features
5
+
6
+ * Bundle NPM package @appland/cli with this gem ([945e28c](https://github.com/applandinc/appmap-ruby/commit/945e28c699fff6bd97ae51983816e97955c4ff36))
7
+
8
+ ## [0.51.3](https://github.com/applandinc/appmap-ruby/compare/v0.51.2...v0.51.3) (2021-06-22)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Remove outdate lore, command, and algorithm code ([d899989](https://github.com/applandinc/appmap-ruby/commit/d8999896c611c16f51a092f5f7afb3d7203d7e72))
14
+
15
+ ## [0.51.2](https://github.com/applandinc/appmap-ruby/compare/v0.51.1...v0.51.2) (2021-06-22)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * Be less verbose when logging config messages ([fba2fd0](https://github.com/applandinc/appmap-ruby/commit/fba2fd01dbb7b1830194b49285654d6657d1c786))
21
+ * Method objects must support eql? and hash to ensure they are unique in a Set ([f4d5b11](https://github.com/applandinc/appmap-ruby/commit/f4d5b11db90aa50bdd1f768e039927833e83c30f))
22
+ * Require rails, then appmap/railtie ([07967a1](https://github.com/applandinc/appmap-ruby/commit/07967a14609891544a7dd874c648b7ef5a505f21))
23
+ * Use a hybrid strategy to auto-requiring appmap modules ([6fb09b8](https://github.com/applandinc/appmap-ruby/commit/6fb09b8c0bd55b1e29967d459ce1e2bd5b1ba9fe))
24
+
25
+ ## [0.51.1](https://github.com/applandinc/appmap-ruby/compare/v0.51.0...v0.51.1) (2021-06-21)
26
+
27
+
28
+ ### Bug Fixes
29
+
30
+ * Add missing require 'yaml' ([1187a02](https://github.com/applandinc/appmap-ruby/commit/1187a023243caaab8cd48de5cbbddefa361636ad))
31
+
32
+ # [0.51.0](https://github.com/applandinc/appmap-ruby/compare/v0.50.0...v0.51.0) (2021-06-21)
33
+
34
+
35
+ ### Features
36
+
37
+ * Provide default appmap.yml settings ([7fa8159](https://github.com/applandinc/appmap-ruby/commit/7fa8159b5020e35f13379017b44906d671e62e64))
38
+
1
39
  # [0.50.0](https://github.com/applandinc/appmap-ruby/compare/v0.49.0...v0.50.0) (2021-06-17)
2
40
 
3
41
 
data/Rakefile CHANGED
@@ -16,6 +16,22 @@ end
16
16
 
17
17
  namespace 'gem' do
18
18
  require 'bundler/gem_tasks'
19
+
20
+ module Bundler
21
+ class GemHelper
22
+ alias default_build_gem build_gem
23
+
24
+ # A handy tip - find the location of any Rake task using `rake -W`.
25
+ # rake -W build
26
+ # ~/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/gem_helper.rb:39:in `install'
27
+ def build_gem
28
+ # Ensure that NPM packages are installed before building.
29
+ sh('yarn install --prod'.shellsplit)
30
+
31
+ default_build_gem
32
+ end
33
+ end
34
+ end
19
35
  end
20
36
 
21
37
  RUBY_VERSIONS=%w[2.5 2.6 2.7]
@@ -34,18 +50,19 @@ def run_cmd(*cmd)
34
50
  raise 'Docker build failed'
35
51
  end
36
52
  end
37
-
53
+
38
54
  def build_base_image(ruby_version)
39
55
  run_cmd "docker build" \
40
56
  " --build-arg RUBY_VERSION=#{ruby_version}" \
41
57
  " --build-arg GEM_VERSION=#{GEM_VERSION}" \
42
58
  " -t appmap:#{GEM_VERSION} -f Dockerfile.appmap ."
43
59
  end
44
-
60
+
45
61
  def build_app_image(app, ruby_version)
46
62
  Dir.chdir "spec/fixtures/#{app}" do
47
- run_cmd( {"RUBY_VERSION" => ruby_version, "GEM_VERSION" => GEM_VERSION},
48
- " docker-compose build" \
63
+ env = {"RUBY_VERSION" => ruby_version, "GEM_VERSION" => GEM_VERSION}
64
+ run_cmd(env,
65
+ "docker-compose build" \
49
66
  " --build-arg RUBY_VERSION=#{ruby_version}" \
50
67
  " --build-arg GEM_VERSION=#{GEM_VERSION}" )
51
68
  end
@@ -139,4 +156,3 @@ task spec: %i[spec:all]
139
156
  task test: %i[spec:all minitest]
140
157
 
141
158
  task default: :test
142
-
data/appmap.gemspec CHANGED
@@ -4,8 +4,6 @@ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'appmap/version'
6
6
 
7
-
8
-
9
7
  Gem::Specification.new do |spec|
10
8
  # ability to parameterize gem name is added intentionally,
11
9
  # to support the possibility of unofficial releases, e.g. during CI tests
@@ -22,19 +20,26 @@ Gem::Specification.new do |spec|
22
20
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
21
  spec.files = `git ls-files --no-deleted`.split("
24
22
  ")
25
- spec.extensions << "ext/appmap/extconf.rb"
23
+ spec.bindir = 'exe'
24
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
25
 
26
+ strip_dir = ->(file) { file.index(Dir.pwd) == 0 ? file[Dir.pwd.length+1...file.length] : file }
27
+ Dir.glob(File.join(__dir__, 'node_modules/**/*')).map(&strip_dir).each do |filename|
28
+ next if File.directory?(filename) || filename.length > 100
29
+ spec.files << filename
30
+ end
31
+
32
+ spec.extensions << "ext/appmap/extconf.rb"
27
33
  spec.require_paths = ['lib']
28
34
 
29
35
  spec.add_dependency 'activesupport'
30
- spec.add_dependency 'faraday'
31
36
  spec.add_dependency 'gli'
32
37
  spec.add_dependency 'method_source'
33
- spec.add_dependency 'parser'
34
38
  spec.add_dependency 'rack'
39
+ spec.add_dependency 'reverse_markdown'
35
40
 
36
41
  spec.add_development_dependency 'bundler', '>= 1.16'
37
- spec.add_development_dependency 'minitest', '~> 5.0'
42
+ spec.add_development_dependency 'minitest', '= 5.14.4'
38
43
  spec.add_development_dependency 'pry-byebug'
39
44
  spec.add_development_dependency 'rake', '>= 12.3.3'
40
45
  spec.add_development_dependency 'rdoc'
@@ -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 code editor plugins 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/agent_setup/init'
28
+ AppMap::Command::AgentSetup::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)
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift File.join(__dir__, '../lib')
5
+
6
+ require 'appmap/command/inspect'
7
+ AppMap::Command::Inspect.run
data/lib/appmap.rb CHANGED
@@ -8,12 +8,12 @@ rescue NameError
8
8
  end
9
9
 
10
10
  require 'appmap/version'
11
+ require 'appmap/util'
11
12
  require 'appmap/hook'
12
13
  require 'appmap/config'
13
14
  require 'appmap/trace'
14
15
  require 'appmap/class_map'
15
16
  require 'appmap/metadata'
16
- require 'appmap/util'
17
17
  require 'appmap/open'
18
18
 
19
19
  # load extension
@@ -27,7 +27,7 @@ module AppMap
27
27
  # Gets the configuration. If there is no configuration, the default
28
28
  # configuration is initialized.
29
29
  def configuration
30
- @configuration ||= initialize
30
+ @configuration ||= initialize_configuration
31
31
  end
32
32
 
33
33
  # Sets the configuration. This is only expected to happen once per
@@ -38,13 +38,20 @@ module AppMap
38
38
  @configuration = config
39
39
  end
40
40
 
41
- # Configures AppMap for recording. Default behavior is to configure from "appmap.yml".
41
+ def default_config_file_path
42
+ ENV['APPMAP_CONFIG_FILE'] || 'appmap.yml'
43
+ end
44
+
45
+ # Configures AppMap for recording. Default behavior is to configure from
46
+ # APPMAP_CONFIG_FILE, or 'appmap.yml'. If no config file is available, a
47
+ # configuration will be automatically generated and used - and the user is prompted
48
+ # to create the config file.
49
+ #
42
50
  # This method also activates the code hooks which record function calls as trace events.
43
51
  # Call this function before the program code is loaded by the Ruby VM, otherwise
44
52
  # the load events won't be seen and the hooks won't activate.
45
- def initialize(config_file_path = 'appmap.yml')
46
- raise "AppMap configuration file #{config_file_path} does not exist" unless ::File.exists?(config_file_path)
47
- warn "Configuring AppMap from path #{config_file_path}"
53
+ def initialize_configuration(config_file_path = default_config_file_path)
54
+ Util.startup_message "Configuring AppMap from path #{config_file_path}"
48
55
  Config.load_from_file(config_file_path).tap do |configuration|
49
56
  self.configuration = configuration
50
57
  Hook.new(configuration).enable
@@ -105,17 +112,49 @@ module AppMap
105
112
  end
106
113
  end
107
114
 
108
- if defined?(::Rails::Railtie)
109
- require 'appmap/railtie'
110
- end
115
+ lambda do
116
+ Initializer = Struct.new(:class_name, :module_name, :gem_module_name)
111
117
 
112
- if defined?(::RSpec)
113
- require 'appmap/rspec'
114
- end
118
+ INITIALIZERS = {
119
+ 'Rails::Railtie' => Initializer.new('AppMap::Railtie', 'appmap/railtie', 'railtie'),
120
+ 'RSpec' => Initializer.new('AppMap::RSpec', 'appmap/rspec', 'rspec-core'),
121
+ 'Minitest::Unit::TestCase' => Initializer.new('AppMap::Minitest', 'appmap/minitest', 'minitest')
122
+ }
115
123
 
116
- # defined?(::Minitest) returns nil...
117
- if Gem.loaded_specs['minitest']
118
- require 'appmap/minitest'
119
- end
124
+ TracePoint.new(:class) do |tp|
125
+ cls_name = tp.self.name
126
+ initializers = INITIALIZERS.delete(cls_name)
127
+ if initializers
128
+ initializers = [ initializers ] unless initializers.is_a?(Array)
129
+ next if Object.const_defined?(initializers.first.class_name)
130
+
131
+ gem_module_name = initializers.first.gem_module_name
132
+
133
+ AppMap::Util.startup_message AppMap::Util.color(<<~LOAD_MSG, :magenta)
134
+ When 'appmap' was loaded, '#{gem_module_name}' had not been loaded yet. Now '#{gem_module_name}' has
135
+ just been loaded, so the following AppMap modules will be automatically required:
136
+
137
+ #{initializers.map(&:module_name).join("\n")}
138
+
139
+ To suppress this message, ensure '#{gem_module_name}' appears before 'appmap' in your Gemfile.
140
+ LOAD_MSG
141
+ initializers.each do |init|
142
+ require init.module_name
143
+ end
144
+ end
145
+ end.enable
146
+
147
+ if defined?(::Rails::Railtie)
148
+ require 'appmap/railtie'
149
+ end
150
+
151
+ if defined?(::RSpec)
152
+ require 'appmap/rspec'
153
+ end
154
+
155
+ if defined?(::Minitest)
156
+ require 'appmap/minitest'
157
+ end
158
+ end.call
120
159
 
121
- AppMap.initialize if ENV['APPMAP'] == 'true'
160
+ AppMap.initialize_configuration if ENV['APPMAP'] == 'true'
@@ -0,0 +1,44 @@
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
+ module AgentSetup
10
+ InitStruct = Struct.new(:config_file)
11
+
12
+ class Init < InitStruct
13
+ def perform
14
+ if File.exist?(config_file)
15
+ puts AppMap::Util.color(%(The AppMap config file #{config_file} already exists.), :magenta)
16
+ return
17
+ end
18
+
19
+ ensure_directory_exists
20
+
21
+ config = {
22
+ 'name' => Service::Guesser.guess_name,
23
+ 'packages' => Service::Guesser.guess_paths.map { |path| { 'path' => path } }
24
+ }
25
+ content = YAML.dump(config).gsub("---\n", '')
26
+
27
+ File.write(config_file, content)
28
+ puts AppMap::Util.color(
29
+ %(The following AppMap config file #{config_file} has been created:),
30
+ :green
31
+ )
32
+ puts content
33
+ end
34
+
35
+ private
36
+
37
+ def ensure_directory_exists
38
+ dirname = File.dirname(config_file)
39
+ FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,27 @@
1
+ require 'appmap/version'
2
+ require 'appmap/config'
3
+ require 'appmap/node_cli'
4
+
5
+ module AppMap
6
+ module Command
7
+ class Inspect < AppMap::NodeCLI
8
+ class << self
9
+ def run
10
+ command = Inspect.new(verbose: ENV['DEBUG'] == 'true')
11
+ command.inspect(ARGV)
12
+ end
13
+ end
14
+
15
+ def inspect(arguments)
16
+ detect_nodejs
17
+ index_appmaps
18
+
19
+ arguments.unshift 'inspect'
20
+ arguments.unshift APPMAP_JS
21
+ arguments.unshift 'node'
22
+
23
+ exec(*arguments)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ module AppMap
2
+ # Raised when a system / shell command fails.
3
+ class CommandError < StandardError
4
+ attr_reader :command, :msg
5
+
6
+ def initialize(command, msg = nil)
7
+ super [ "Command failed: #{command}", msg ].compact.join('; ')
8
+
9
+ @command = command
10
+ @msg = msg
11
+ end
12
+ end
13
+ end
data/lib/appmap/config.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'yaml'
4
+ require 'appmap/util'
3
5
  require 'appmap/handler/net_http'
4
6
  require 'appmap/handler/rails/template'
7
+ require 'appmap/service/guesser'
5
8
 
6
9
  module AppMap
7
10
  class Config
@@ -52,7 +55,7 @@ module AppMap
52
55
  if path
53
56
  Package.new(path, gem, package_name, exclude, labels, shallow)
54
57
  else
55
- warn "#{gem} is not available in the bundle" if AppMap::Hook::LOG
58
+ AppMap::Util.startup_message "#{gem} is not available in the bundle"
56
59
  end
57
60
  end
58
61
 
@@ -223,10 +226,14 @@ module AppMap
223
226
  'JSON::Ext::Generator::State' => TargetMethods.new(:generate, Package.build_from_path('json', package_name: 'json', labels: %w[format.json.generate])),
224
227
  }.freeze
225
228
 
226
- attr_reader :name, :packages, :exclude, :hooked_methods, :builtin_hooks
229
+ attr_reader :name, :appmap_dir, :packages, :exclude, :hooked_methods, :builtin_hooks
227
230
 
228
- def initialize(name, packages, exclude: [], functions: [])
231
+ def initialize(name,
232
+ packages: [],
233
+ exclude: [],
234
+ functions: [])
229
235
  @name = name
236
+ @appmap_dir = AppMap::DEFAULT_APPMAP_DIR
230
237
  @packages = packages
231
238
  @hook_paths = Set.new(packages.map(&:path))
232
239
  @exclude = exclude
@@ -253,38 +260,98 @@ module AppMap
253
260
  class << self
254
261
  # Loads configuration data from a file, specified by the file name.
255
262
  def load_from_file(config_file_name)
256
- require 'yaml'
257
- load YAML.safe_load(::File.read(config_file_name))
263
+ logo = lambda do
264
+ Util.color(<<~LOGO, :magenta)
265
+ ___ __ ___
266
+ / _ | ___ ___ / |/ /__ ____
267
+ / __ |/ _ \\/ _ \\/ /|_/ / _ `/ _ \\
268
+ /_/ |_/ .__/ .__/_/ /_/\\_,_/ .__/
269
+ /_/ /_/ /_/
270
+ LOGO
271
+ end
272
+
273
+ config_present = true if File.exists?(config_file_name)
274
+
275
+ config_data = if config_present
276
+ YAML.safe_load(::File.read(config_file_name))
277
+ else
278
+ warn logo.()
279
+ warn ''
280
+ warn Util.color(%Q|NOTICE: The AppMap config file #{config_file_name} was not found!|, :magenta, bold: true)
281
+ warn ''
282
+ warn Util.color(<<~MISSING_FILE_MSG, :magenta)
283
+ AppMap uses this file to customize its behavior. For example, you can use
284
+ the 'packages' setting to indicate which local file paths and dependency
285
+ gems you want to include in the AppMap. Since you haven't provided specific
286
+ settings, the appmap gem will try and guess some reasonable defaults.
287
+ To suppress this message, create the file:
288
+
289
+ #{Pathname.new(config_file_name).expand_path}
290
+
291
+ Here are the default settings that will be used in the meantime. You can
292
+ copy and paste this example to start your appmap.yml.
293
+ MISSING_FILE_MSG
294
+ {}
295
+ end
296
+ load(config_data).tap do |config|
297
+ config_yaml = {
298
+ 'name' => config.name,
299
+ 'packages' => config.packages.select{|p| p.path}.map do |pkg|
300
+ { 'path' => pkg.path }
301
+ end,
302
+ 'exclude' => []
303
+ }.compact
304
+ unless config_present
305
+ warn Util.color(YAML.dump(config_yaml), :magenta)
306
+ warn logo.()
307
+ end
308
+ end
258
309
  end
259
310
 
260
311
  # Loads configuration from a Hash.
261
312
  def load(config_data)
262
- functions = (config_data['functions'] || []).map do |function_data|
263
- package = function_data['package']
264
- cls = function_data['class']
265
- functions = function_data['function'] || function_data['functions']
266
- raise 'AppMap class configuration should specify package, class and function(s)' unless package && cls && functions
267
- functions = Array(functions).map(&:to_sym)
268
- labels = function_data['label'] || function_data['labels']
269
- labels = Array(labels).map(&:to_s) if labels
270
- Function.new(package, cls, labels, functions)
313
+ name = config_data['name'] || Service::Guesser.guess_name
314
+ config_params = {
315
+ exclude: config_data['exclude']
316
+ }.compact
317
+
318
+ if config_data['functions']
319
+ config_params[:functions] = config_data['functions'].map do |function_data|
320
+ package = function_data['package']
321
+ cls = function_data['class']
322
+ functions = function_data['function'] || function_data['functions']
323
+ raise %q(AppMap config 'function' element should specify 'package', 'class' and 'function' or 'functions') unless package && cls && functions
324
+
325
+ functions = Array(functions).map(&:to_sym)
326
+ labels = function_data['label'] || function_data['labels']
327
+ labels = Array(labels).map(&:to_s) if labels
328
+ Function.new(package, cls, labels, functions)
329
+ end
271
330
  end
272
- packages = (config_data['packages'] || []).map do |package|
273
- gem = package['gem']
274
- path = package['path']
275
- raise 'AppMap package configuration should specify gem or path, not both' if gem && path
276
-
277
- if gem
278
- shallow = package['shallow']
279
- # shallow is true by default for gems
280
- shallow = true if shallow.nil?
281
- Package.build_from_gem(gem, exclude: package['exclude'] || [], shallow: shallow)
331
+
332
+ config_params[:packages] = \
333
+ if config_data['packages']
334
+ config_data['packages'].map do |package|
335
+ gem = package['gem']
336
+ path = package['path']
337
+ raise %q(AppMap config 'package' element should specify 'gem' or 'path', not both) if gem && path
338
+
339
+ if gem
340
+ shallow = package['shallow']
341
+ # shallow is true by default for gems
342
+ shallow = true if shallow.nil?
343
+ Package.build_from_gem(gem, exclude: package['exclude'] || [], shallow: shallow)
344
+ else
345
+ Package.build_from_path(path, exclude: package['exclude'] || [], shallow: package['shallow'])
346
+ end
347
+ end.compact
282
348
  else
283
- Package.build_from_path(path, exclude: package['exclude'] || [], shallow: package['shallow'])
349
+ Array(Service::Guesser.guess_paths).map do |path|
350
+ Package.build_from_path(path)
351
+ end
284
352
  end
285
- end.compact
286
- exclude = config_data['exclude'] || []
287
- Config.new config_data['name'], packages, exclude: exclude, functions: functions
353
+
354
+ Config.new name, config_params
288
355
  end
289
356
  end
290
357
 
@@ -294,7 +361,7 @@ module AppMap
294
361
  packages: packages.map(&:to_h),
295
362
  functions: @functions.map(&:to_h),
296
363
  exclude: exclude
297
- }
364
+ }.compact
298
365
  end
299
366
 
300
367
  # Determines if methods defined in a file path should possibly be hooked.