appmap 0.50.0 → 0.52.0

Sign up to get free protection for your applications and to get access to all the features.
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.