bootsnap 1.3.2-java → 1.4.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 929d3ddcf796d7d001890c5661403ce1ba3cd21dfe63fcce6986857f3c551c70
4
- data.tar.gz: 5c8be3187f173b46127dc09e2fa98c83044d3a1f02a364ae3045d7d3abc85e23
3
+ metadata.gz: b52dcf497cc21a7ce9e7a90d1ce3356c90bfecb2dca0075e9ed18ccd5bd85f46
4
+ data.tar.gz: 848f3b1c68bc8aff09e7f33990d2d25d64fd0e4349ce5ba5ad99696b06eb69bd
5
5
  SHA512:
6
- metadata.gz: 63d4386909d722d027f355d46e719f4c843d3af2abfbd689abe55a8f20b21f01f3c25dbf3dc7bb0461d326dd69b8f0a5e849a7f8b033a7ac9b5344b1e00461f2
7
- data.tar.gz: b832b7992a9b9a700fbdc1e84b1264544b207f03a172f1a95535b76f9ef8f2a8ae8585fee72dc55ad2c3873ed0b0f0122e87860baebae97b557916bbb9b1a395
6
+ metadata.gz: 68f89030acc8fca5f2abaf210ed33cb3cb6f02bf587197f87db2869421496dfc504e0ed1ab04dfc44b3ce1d6d0a5f60fbc4a4520082b833c3cc3d12dcc4751b3
7
+ data.tar.gz: e4fbeab4eae5e93bbde91b95274cb54521733a06780e1f6d677eb212124ae248370f29e941ed89bcb72cb4ffaa88e4c71a73572f6371376102bd97df89751a9c
data/.travis.yml CHANGED
@@ -8,6 +8,17 @@ os:
8
8
  rvm:
9
9
  - ruby-2.4
10
10
  - ruby-2.5
11
+ - ruby-head
11
12
 
12
- before_script: rake
13
- script: bundle exec bin/testunit
13
+ matrix:
14
+ allow_failures:
15
+ - rvm: ruby-head
16
+ include:
17
+ - rvm: jruby
18
+ os: linux
19
+ env: MINIMAL_SUPPORT=1
20
+ - rvm: truffleruby
21
+ os: linux
22
+ env: MINIMAL_SUPPORT=1
23
+
24
+ script: bin/ci
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ # 1.4.0
2
+
3
+ * When running in development mode, always fall back to a full path scan on LoadError, making
4
+ bootsnap more able to detect newly-created files. (#230)
5
+ * Respect `$LOADED_FEATURES.delete` in order to support code reloading, for integration with
6
+ Zeitwerk. (#230)
7
+ * Minor performance improvement: flow-control exceptions no longer generate backtraces.
8
+ * Better support for requiring from environments where some features are not supported (especially
9
+ JRuby). (#226)k
10
+ * More robust handling of OS errors when creating files. (#225)
11
+
1
12
  # 1.3.2
2
13
 
3
14
  * Fix Spring + Bootsnap incompatibility when there are files with similar names.
data/README.jp.md CHANGED
@@ -12,7 +12,7 @@ Bootsnap は RubyVM におけるバイトコード生成やファイルルック
12
12
 
13
13
  ## 使用方法
14
14
 
15
- この gem は MacOS と Linux で作動します。まずは、`bootsnap` を `Gemfile` に追加します:
15
+ この gem は macOS と Linux で作動します。まずは、`bootsnap` を `Gemfile` に追加します:
16
16
 
17
17
  ```ruby
18
18
  gem 'bootsnap', require: false
@@ -24,6 +24,8 @@ Rails を使用している場合は、以下のコードを、`config/boot.rb`
24
24
  require 'bootsnap/setup'
25
25
  ```
26
26
 
27
+ 単に `gem 'bootsnap', require: 'bootsnap/setup'` と指定することも技術的には可能ですが、最大限のパフォーマンス改善を得るためには Bootsnap をできるだけ早く読み込むことが重要です。
28
+
27
29
  この require の仕組みは[こちら](https://github.com/Shopify/bootsnap/blob/master/lib/bootsnap/setup.rb)で確認できます。
28
30
 
29
31
  Rails を使用していない場合、または、より多くの設定を変更したい場合は、以下のコードを `require 'bundler/setup'` の直後に追加してください(早く読み込まれるほど、より多くのものを最適化することができます)。
@@ -67,7 +69,7 @@ Bootsnap は、処理に時間のかかるメソッドの結果をキャッシ
67
69
  _(このライブラリは [bootscale](https://github.com/byroot/bootscale) という別のライブラリを元に開発されました)_
68
70
 
69
71
  Bootsnap の初期化時、あるいはパス(例えば、`$LOAD_PATH`)の変更時に、`Bootsnap::LoadPathCache` がキャッシュから必要なエントリーのリストを読み込みます。または、必要に応じてフルスキャンを実行し結果をキャッシュします。
70
- その後、たとえば `require 'foo'` を評価する場合, Ruby は `$LOAD_PATH` `['x', 'y', ...]` のすべてのエントリーを繰り返し評価することで `x/foo.rb`, `y/foo.rb` などを探索します。これに対して Bootsnap は、キャッシュされた reuiqre 可能なファイルと `$LOAD_PATH` を見ることで、Rubyが最終的に選択するであろうパスで置き換えます。
72
+ その後、たとえば `require 'foo'` を評価する場合, Ruby は `$LOAD_PATH` `['x', 'y', ...]` のすべてのエントリーを繰り返し評価することで `x/foo.rb`, `y/foo.rb` などを探索します。これに対して Bootsnap は、キャッシュされた require 可能なファイルと `$LOAD_PATH` を見ることで、Rubyが最終的に選択するであろうパスで置き換えます。
71
73
 
72
74
  この動作によって生成された syscall を見ると、最終的な結果は以前なら次のようになります。
73
75
 
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
- require 'rake/extensiontask'
2
- require 'bundler/gem_tasks'
1
+ require('rake/extensiontask')
2
+ require('bundler/gem_tasks')
3
3
 
4
4
  gemspec = Gem::Specification.load('bootsnap.gemspec')
5
5
  Rake::ExtensionTask.new do |ext|
data/bin/ci ADDED
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+
3
+ set -euxo pipefail
4
+
5
+ if [[ "${MINIMAL_SUPPORT-0}" -eq 1 ]]; then
6
+ exec bin/test-minimal-support
7
+ else
8
+ rake
9
+ exec bin/testunit
10
+ fi
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "bootsnap"
3
+ require("bundler/setup")
4
+ require("bootsnap")
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "bootsnap"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require("irb")
14
14
  IRB.start(__FILE__)
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+
3
+ set -euxo pipefail
4
+
5
+ cd test/minimal_support
6
+ bundle
7
+ BOOTSNAP_CACHE_DIR=/tmp bundle exec ruby -w -I ../../lib bootsnap_setup.rb
data/bootsnap.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'bootsnap/version'
4
+ require('bootsnap/version')
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "bootsnap"
@@ -15,10 +15,16 @@ Gem::Specification.new do |spec|
15
15
  spec.description = spec.summary
16
16
  spec.homepage = "https://github.com/Shopify/bootsnap"
17
17
 
18
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ spec.metadata = {
19
+ 'bug_tracker_uri' => 'https://github.com/Shopify/bootsnap/issues',
20
+ 'changelog_uri' => 'https://github.com/Shopify/bootsnap/blob/master/CHANGELOG.md',
21
+ 'source_code_uri' => 'https://github.com/Shopify/bootsnap',
22
+ }
23
+
24
+ spec.files = %x(git ls-files -z).split("\x0").reject do |f|
19
25
  f.match(%r{^(test|spec|features)/})
20
26
  end
21
- spec.require_paths = ["lib"]
27
+ spec.require_paths = %w(lib)
22
28
 
23
29
  spec.required_ruby_version = '>= 2.0.0'
24
30
 
@@ -29,11 +35,11 @@ Gem::Specification.new do |spec|
29
35
  spec.extensions = ['ext/bootsnap/extconf.rb']
30
36
  end
31
37
 
32
- spec.add_development_dependency "bundler", '~> 1'
33
- spec.add_development_dependency 'rake', '~> 10.0'
34
- spec.add_development_dependency 'rake-compiler', '~> 0'
35
- spec.add_development_dependency "minitest", "~> 5.0"
36
- spec.add_development_dependency "mocha", "~> 1.2"
38
+ spec.add_development_dependency("bundler")
39
+ spec.add_development_dependency('rake', '~> 10.0')
40
+ spec.add_development_dependency('rake-compiler', '~> 0')
41
+ spec.add_development_dependency("minitest", "~> 5.0")
42
+ spec.add_development_dependency("mocha", "~> 1.2")
37
43
 
38
- spec.add_runtime_dependency "msgpack", "~> 1.0"
44
+ spec.add_runtime_dependency("msgpack", "~> 1.0")
39
45
  end
data/dev.yml CHANGED
@@ -2,9 +2,7 @@ env:
2
2
  BOOTSNAP_PEDANTIC: '1'
3
3
 
4
4
  up:
5
- - ruby:
6
- version: 9.0.5.0
7
- engine: jruby
5
+ - ruby: 2.6.0
8
6
  - bundler
9
7
  commands:
10
8
  build: rake compile
@@ -1,4 +1,4 @@
1
- require "mkmf"
1
+ require("mkmf")
2
2
  $CFLAGS << ' -O3 '
3
3
  $CFLAGS << ' -std=c99'
4
4
 
@@ -12,6 +12,7 @@ unless ['0', '', nil].include?(ENV['BOOTSNAP_PEDANTIC'])
12
12
 
13
13
  $CFLAGS << ' -Wno-unused-parameter' # VALUE self has to be there but we don't care what it is.
14
14
  $CFLAGS << ' -Wno-keyword-macro' # hiding return
15
+ $CFLAGS << ' -Wno-gcc-compat' # ruby.h 2.6.0 on macos 10.14, dunno
15
16
  end
16
17
 
17
18
  create_makefile("bootsnap/bootsnap")
data/lib/bootsnap.rb CHANGED
@@ -1,7 +1,7 @@
1
- require_relative 'bootsnap/version'
2
- require_relative 'bootsnap/bundler'
3
- require_relative 'bootsnap/load_path_cache'
4
- require_relative 'bootsnap/compile_cache'
1
+ require_relative('bootsnap/version')
2
+ require_relative('bootsnap/bundler')
3
+ require_relative('bootsnap/load_path_cache')
4
+ require_relative('bootsnap/compile_cache')
5
5
 
6
6
  module Bootsnap
7
7
  InvalidConfiguration = Class.new(StandardError)
@@ -16,7 +16,7 @@ module Bootsnap
16
16
  compile_cache_yaml: true
17
17
  )
18
18
  if autoload_paths_cache && !load_path_cache
19
- raise InvalidConfiguration, "feature 'autoload_paths_cache' depends on feature 'load_path_cache'"
19
+ raise(InvalidConfiguration, "feature 'autoload_paths_cache' depends on feature 'load_path_cache'")
20
20
  end
21
21
 
22
22
  setup_disable_trace if disable_trace
@@ -36,7 +36,10 @@ module Bootsnap
36
36
 
37
37
  def self.setup_disable_trace
38
38
  if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0')
39
- warn("from #{caller_locations(1, 1)[0]}: The 'disable_trace' method is not allowed with this Ruby version. current: #{RUBY_VERSION}, allowed version: < 2.5.0")
39
+ warn(
40
+ "from #{caller_locations(1, 1)[0]}: The 'disable_trace' method is not allowed with this Ruby version. " \
41
+ "current: #{RUBY_VERSION}, allowed version: < 2.5.0",
42
+ )
40
43
  else
41
44
  RubyVM::InstructionSequence.compile_option = { trace_instruction: false }
42
45
  end
@@ -1,11 +1,11 @@
1
1
  module Bootsnap
2
- module_function
2
+ extend(self)
3
3
 
4
4
  def bundler?
5
5
  return false unless defined?(::Bundler)
6
6
 
7
7
  # Bundler environment variable
8
- ['BUNDLE_BIN_PATH', 'BUNDLE_GEMFILE'].each do |current|
8
+ %w(BUNDLE_BIN_PATH BUNDLE_GEMFILE).each do |current|
9
9
  return true if ENV.key?(current)
10
10
  end
11
11
 
@@ -2,14 +2,29 @@ module Bootsnap
2
2
  module CompileCache
3
3
  def self.setup(cache_dir:, iseq:, yaml:)
4
4
  if iseq
5
- require_relative 'compile_cache/iseq'
6
- Bootsnap::CompileCache::ISeq.install!(cache_dir)
5
+ if supported?
6
+ require_relative('compile_cache/iseq')
7
+ Bootsnap::CompileCache::ISeq.install!(cache_dir)
8
+ elsif $VERBOSE
9
+ warn("[bootsnap/setup] bytecode caching is not supported on this implementation of Ruby")
10
+ end
7
11
  end
8
12
 
9
13
  if yaml
10
- require_relative 'compile_cache/yaml'
11
- Bootsnap::CompileCache::YAML.install!(cache_dir)
14
+ if supported?
15
+ require_relative('compile_cache/yaml')
16
+ Bootsnap::CompileCache::YAML.install!(cache_dir)
17
+ elsif $VERBOSE
18
+ warn("[bootsnap/setup] YAML parsing caching is not supported on this implementation of Ruby")
19
+ end
12
20
  end
13
21
  end
22
+
23
+ def self.supported?
24
+ # only enable on 'ruby' (MRI), POSIX (darwin, linux, *bsd), and >= 2.3.0
25
+ RUBY_ENGINE == 'ruby' &&
26
+ RUBY_PLATFORM =~ /darwin|linux|bsd/ &&
27
+ Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.3.0")
28
+ end
14
29
  end
15
30
  end
@@ -1,25 +1,25 @@
1
- require 'bootsnap/bootsnap'
2
- require 'zlib'
1
+ require('bootsnap/bootsnap')
2
+ require('zlib')
3
3
 
4
4
  module Bootsnap
5
5
  module CompileCache
6
6
  module ISeq
7
7
  class << self
8
- attr_accessor :cache_dir
8
+ attr_accessor(:cache_dir)
9
9
  end
10
10
 
11
11
  def self.input_to_storage(_, path)
12
12
  RubyVM::InstructionSequence.compile_file(path).to_binary
13
13
  rescue SyntaxError
14
- raise Uncompilable, 'syntax error'
14
+ raise(Uncompilable, 'syntax error')
15
15
  end
16
16
 
17
17
  def self.storage_to_output(binary)
18
18
  RubyVM::InstructionSequence.load_from_binary(binary)
19
19
  rescue RuntimeError => e
20
20
  if e.message == 'broken binary format'
21
- STDERR.puts "[Bootsnap::CompileCache] warning: rejecting broken binary"
22
- return nil
21
+ STDERR.puts("[Bootsnap::CompileCache] warning: rejecting broken binary")
22
+ nil
23
23
  else
24
24
  raise
25
25
  end
@@ -41,7 +41,7 @@ module Bootsnap
41
41
  )
42
42
  rescue RuntimeError => e
43
43
  if e.message =~ /unmatched platform/
44
- puts "unmatched platform for file #{path}"
44
+ puts("unmatched platform for file #{path}")
45
45
  end
46
46
  raise
47
47
  end
@@ -62,7 +62,7 @@ module Bootsnap
62
62
  Bootsnap::CompileCache::ISeq.cache_dir = cache_dir
63
63
  Bootsnap::CompileCache::ISeq.compile_option_updated
64
64
  class << RubyVM::InstructionSequence
65
- prepend InstructionSequenceMixin
65
+ prepend(InstructionSequenceMixin)
66
66
  end
67
67
  end
68
68
  end
@@ -1,21 +1,21 @@
1
- require 'bootsnap/bootsnap'
1
+ require('bootsnap/bootsnap')
2
2
 
3
3
  module Bootsnap
4
4
  module CompileCache
5
5
  module YAML
6
6
  class << self
7
- attr_accessor :msgpack_factory
7
+ attr_accessor(:msgpack_factory)
8
8
  end
9
9
 
10
10
  def self.input_to_storage(contents, _)
11
- raise Uncompilable if contents.index("!ruby/object")
11
+ raise(Uncompilable) if contents.index("!ruby/object")
12
12
  obj = ::YAML.load(contents)
13
13
  msgpack_factory.packer.write(obj).to_s
14
14
  rescue NoMethodError, RangeError
15
15
  # if the object included things that we can't serialize, fall back to
16
16
  # Marshal. It's a bit slower, but can encode anything yaml can.
17
17
  # NoMethodError is unexpected types; RangeError is Bignums
18
- return Marshal.dump(obj)
18
+ Marshal.dump(obj)
19
19
  end
20
20
 
21
21
  def self.storage_to_output(data)
@@ -34,8 +34,8 @@ module Bootsnap
34
34
  end
35
35
 
36
36
  def self.install!(cache_dir)
37
- require 'yaml'
38
- require 'msgpack'
37
+ require('yaml')
38
+ require('msgpack')
39
39
 
40
40
  # MessagePack serializes symbols as strings by default.
41
41
  # We want them to roundtrip cleanly, so we use a custom factory.
@@ -5,7 +5,7 @@ module Bootsnap
5
5
  DLEXT = RbConfig::CONFIG['DLEXT']
6
6
 
7
7
  def self.from_self(feature)
8
- require_relative "../#{feature}"
8
+ require_relative("../#{feature}")
9
9
  end
10
10
 
11
11
  def self.from_rubylibdir(feature)
@@ -21,38 +21,51 @@ module Bootsnap
21
21
  CACHED_EXTENSIONS = DLEXT2 ? [DOT_RB, DLEXT, DLEXT2] : [DOT_RB, DLEXT]
22
22
 
23
23
  class << self
24
- attr_reader :load_path_cache, :autoload_paths_cache,
25
- :loaded_features_index, :realpath_cache
24
+ attr_reader(:load_path_cache, :autoload_paths_cache,
25
+ :loaded_features_index, :realpath_cache)
26
26
 
27
27
  def setup(cache_path:, development_mode:, active_support: true)
28
+ unless supported?
29
+ warn("[bootsnap/setup] Load path caching is not supported on this implementation of Ruby") if $VERBOSE
30
+ return
31
+ end
32
+
28
33
  store = Store.new(cache_path)
29
34
 
30
35
  @loaded_features_index = LoadedFeaturesIndex.new
31
36
  @realpath_cache = RealpathCache.new
32
37
 
33
38
  @load_path_cache = Cache.new(store, $LOAD_PATH, development_mode: development_mode)
34
- require_relative 'load_path_cache/core_ext/kernel_require'
39
+ require_relative('load_path_cache/core_ext/kernel_require')
40
+ require_relative('load_path_cache/core_ext/loaded_features')
35
41
 
36
42
  if active_support
37
43
  # this should happen after setting up the initial cache because it
38
44
  # loads a lot of code. It's better to do after +require+ is optimized.
39
- require 'active_support/dependencies'
45
+ require('active_support/dependencies')
40
46
  @autoload_paths_cache = Cache.new(
41
47
  store,
42
48
  ::ActiveSupport::Dependencies.autoload_paths,
43
49
  development_mode: development_mode
44
50
  )
45
- require_relative 'load_path_cache/core_ext/active_support'
51
+ require_relative('load_path_cache/core_ext/active_support')
46
52
  end
47
53
  end
54
+
55
+ def supported?
56
+ RUBY_ENGINE == 'ruby' &&
57
+ RUBY_PLATFORM =~ /darwin|linux|bsd/
58
+ end
48
59
  end
49
60
  end
50
61
  end
51
62
 
52
- require_relative 'load_path_cache/path_scanner'
53
- require_relative 'load_path_cache/path'
54
- require_relative 'load_path_cache/cache'
55
- require_relative 'load_path_cache/store'
56
- require_relative 'load_path_cache/change_observer'
57
- require_relative 'load_path_cache/loaded_features_index'
58
- require_relative 'load_path_cache/realpath_cache'
63
+ if Bootsnap::LoadPathCache.supported?
64
+ require_relative('load_path_cache/path_scanner')
65
+ require_relative('load_path_cache/path')
66
+ require_relative('load_path_cache/cache')
67
+ require_relative('load_path_cache/store')
68
+ require_relative('load_path_cache/change_observer')
69
+ require_relative('load_path_cache/loaded_features_index')
70
+ require_relative('load_path_cache/realpath_cache')
71
+ end
@@ -1,4 +1,4 @@
1
- require_relative '../explicit_require'
1
+ require_relative('../explicit_require')
2
2
 
3
3
  module Bootsnap
4
4
  module LoadPathCache
@@ -56,7 +56,7 @@ module Bootsnap
56
56
  # returns false as if it were already loaded; however, there is no
57
57
  # file to find on disk. We've pre-built a list of these, and we
58
58
  # return false if any of them is loaded.
59
- raise LoadPathCache::ReturnFalse if BUILTIN_FEATURES.key?(feature)
59
+ raise(LoadPathCache::ReturnFalse, '', []) if BUILTIN_FEATURES.key?(feature)
60
60
 
61
61
  # The feature wasn't found on our preliminary search through the index.
62
62
  # We resolve this differently depending on what the extension was.
@@ -73,14 +73,21 @@ module Bootsnap
73
73
  x = search_index(feature[0..-4] + DLEXT)
74
74
  return x if x
75
75
  if DLEXT2
76
- search_index(feature[0..-4] + DLEXT2)
76
+ x = search_index(feature[0..-4] + DLEXT2)
77
+ return x if x
77
78
  end
78
79
  else
79
80
  # other, unknown extension. For example, `.rake`. Since we haven't
80
81
  # cached these, we legitimately need to run the load path search.
81
- raise LoadPathCache::FallbackScan
82
+ raise(LoadPathCache::FallbackScan, '', [])
82
83
  end
83
84
  end
85
+
86
+ # In development mode, we don't want to confidently return failures for
87
+ # cases where the file doesn't appear to be on the load path. We should
88
+ # be able to detect newly-created files without rebooting the
89
+ # application.
90
+ raise(LoadPathCache::FallbackScan, '', []) if @development_mode
84
91
  end
85
92
 
86
93
  if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
@@ -174,7 +181,7 @@ module Bootsnap
174
181
  end
175
182
 
176
183
  def try_index(f)
177
- if p = @index[f]
184
+ if (p = @index[f])
178
185
  p + '/' + f
179
186
  end
180
187
  end
@@ -30,6 +30,8 @@ module Bootsnap
30
30
  Bootsnap::LoadPathCache.autoload_paths_cache.find(path)
31
31
  rescue Bootsnap::LoadPathCache::ReturnFalse
32
32
  nil # doesn't really apply here
33
+ rescue Bootsnap::LoadPathCache::FallbackScan
34
+ nil # doesn't really apply here
33
35
  end
34
36
  end
35
37
 
@@ -92,7 +94,7 @@ end
92
94
  module ActiveSupport
93
95
  module Dependencies
94
96
  class << self
95
- prepend Bootsnap::LoadPathCache::CoreExt::ActiveSupport::ClassMethods
97
+ prepend(Bootsnap::LoadPathCache::CoreExt::ActiveSupport::ClassMethods)
96
98
  end
97
99
  end
98
100
  end
@@ -11,9 +11,9 @@ module Bootsnap
11
11
  end
12
12
 
13
13
  module Kernel
14
- module_function
14
+ module_function # rubocop:disable Style/ModuleFunction
15
15
 
16
- alias_method :require_without_bootsnap, :require
16
+ alias_method(:require_without_bootsnap, :require)
17
17
 
18
18
  # Note that require registers to $LOADED_FEATURES while load does not.
19
19
  def require_with_bootsnap_lfi(path, resolved = nil)
@@ -25,18 +25,18 @@ module Kernel
25
25
  def require(path)
26
26
  return false if Bootsnap::LoadPathCache.loaded_features_index.key?(path)
27
27
 
28
- if resolved = Bootsnap::LoadPathCache.load_path_cache.find(path)
28
+ if (resolved = Bootsnap::LoadPathCache.load_path_cache.find(path))
29
29
  return require_with_bootsnap_lfi(path, resolved)
30
30
  end
31
31
 
32
- raise Bootsnap::LoadPathCache::CoreExt.make_load_error(path)
32
+ raise(Bootsnap::LoadPathCache::CoreExt.make_load_error(path))
33
33
  rescue Bootsnap::LoadPathCache::ReturnFalse
34
- return false
34
+ false
35
35
  rescue Bootsnap::LoadPathCache::FallbackScan
36
36
  require_with_bootsnap_lfi(path)
37
37
  end
38
38
 
39
- alias_method :require_relative_without_bootsnap, :require_relative
39
+ alias_method(:require_relative_without_bootsnap, :require_relative)
40
40
  def require_relative(path)
41
41
  realpath = Bootsnap::LoadPathCache.realpath_cache.call(
42
42
  caller_locations(1..1).first.absolute_path, path
@@ -44,9 +44,9 @@ module Kernel
44
44
  require(realpath)
45
45
  end
46
46
 
47
- alias_method :load_without_bootsnap, :load
47
+ alias_method(:load_without_bootsnap, :load)
48
48
  def load(path, wrap = false)
49
- if resolved = Bootsnap::LoadPathCache.load_path_cache.find(path)
49
+ if (resolved = Bootsnap::LoadPathCache.load_path_cache.find(path))
50
50
  return load_without_bootsnap(resolved, wrap)
51
51
  end
52
52
 
@@ -55,16 +55,16 @@ module Kernel
55
55
  return load_without_bootsnap(relative, wrap)
56
56
  end
57
57
 
58
- raise Bootsnap::LoadPathCache::CoreExt.make_load_error(path)
58
+ raise(Bootsnap::LoadPathCache::CoreExt.make_load_error(path))
59
59
  rescue Bootsnap::LoadPathCache::ReturnFalse
60
- return false
60
+ false
61
61
  rescue Bootsnap::LoadPathCache::FallbackScan
62
62
  load_without_bootsnap(path, wrap)
63
63
  end
64
64
  end
65
65
 
66
66
  class Module
67
- alias_method :autoload_without_bootsnap, :autoload
67
+ alias_method(:autoload_without_bootsnap, :autoload)
68
68
  def autoload(const, path)
69
69
  # NOTE: This may defeat LoadedFeaturesIndex, but it's not immediately
70
70
  # obvious how to make it work. This feels like a pretty niche case, unclear
@@ -75,7 +75,7 @@ class Module
75
75
  # since it's done in C-land.
76
76
  autoload_without_bootsnap(const, Bootsnap::LoadPathCache.load_path_cache.find(path) || path)
77
77
  rescue Bootsnap::LoadPathCache::ReturnFalse
78
- return false
78
+ false
79
79
  rescue Bootsnap::LoadPathCache::FallbackScan
80
80
  autoload_without_bootsnap(const, path)
81
81
  end
@@ -0,0 +1,7 @@
1
+ class << $LOADED_FEATURES
2
+ alias_method(:delete_without_bootsnap, :delete)
3
+ def delete(key)
4
+ Bootsnap::LoadPathCache.loaded_features_index.purge(key)
5
+ delete_without_bootsnap(key)
6
+ end
7
+ end
@@ -32,17 +32,29 @@ module Bootsnap
32
32
  # parallel the work done with ChangeObserver on $LOAD_PATH to mirror
33
33
  # updates to our @lfi.
34
34
  $LOADED_FEATURES.each do |feat|
35
+ hash = feat.hash
35
36
  $LOAD_PATH.each do |lpe|
36
37
  next unless feat.start_with?(lpe)
37
38
  # /a/b/lib/my/foo.rb
38
39
  # ^^^^^^^^^
39
40
  short = feat[(lpe.length + 1)..-1]
40
- @lfi[short] = true
41
- @lfi[strip_extension(short)] = true
41
+ stripped = strip_extension(short)
42
+ @lfi[short] = hash
43
+ @lfi[stripped] = hash
42
44
  end
43
45
  end
44
46
  end
45
47
 
48
+ # We've optimized for initialize and register to be fast, and purge to be tolerable.
49
+ # If access patterns make this not-okay, we can lazy-invert the LFI on
50
+ # first purge and work from there.
51
+ def purge(feature)
52
+ @mutex.synchronize do
53
+ feat_hash = feature.hash
54
+ @lfi.reject! { |_, hash| hash == feat_hash }
55
+ end
56
+ end
57
+
46
58
  def key?(feature)
47
59
  @mutex.synchronize { @lfi.key?(feature) }
48
60
  end
@@ -62,21 +74,30 @@ module Bootsnap
62
74
  # 2. Inspect $LOADED_FEATURES upon return from yield to find the matching
63
75
  # entry.
64
76
  def register(short, long = nil)
65
- ret = yield
77
+ if long.nil?
78
+ pat = %r{/#{Regexp.escape(short)}(\.[^/]+)?$}
79
+ len = $LOADED_FEATURES.size
80
+ ret = yield
81
+ long = $LOADED_FEATURES[len..-1].detect { |feat| feat =~ pat }
82
+ else
83
+ ret = yield
84
+ end
85
+
86
+ hash = long.hash
66
87
 
67
88
  # do we have 'bundler' or 'bundler.rb'?
68
89
  altname = if File.extname(short) != ''
69
90
  # strip the path from 'bundler.rb' -> 'bundler'
70
91
  strip_extension(short)
71
- elsif long && ext = File.extname(long)
92
+ elsif long && (ext = File.extname(long))
72
93
  # get the extension from the expanded path if given
73
94
  # 'bundler' + '.rb'
74
95
  short + ext
75
96
  end
76
97
 
77
98
  @mutex.synchronize do
78
- @lfi[short] = true
79
- (@lfi[altname] = true) if altname
99
+ @lfi[short] = hash
100
+ (@lfi[altname] = hash) if altname
80
101
  end
81
102
 
82
103
  ret
@@ -85,7 +106,7 @@ module Bootsnap
85
106
  private
86
107
 
87
108
  STRIP_EXTENSION = /\.[^.]*?$/
88
- private_constant :STRIP_EXTENSION
109
+ private_constant(:STRIP_EXTENSION)
89
110
 
90
111
  def strip_extension(f)
91
112
  f.sub(STRIP_EXTENSION, '')
@@ -1,4 +1,4 @@
1
- require_relative 'path_scanner'
1
+ require_relative('path_scanner')
2
2
 
3
3
  module Bootsnap
4
4
  module LoadPathCache
@@ -17,7 +17,7 @@ module Bootsnap
17
17
  stability == VOLATILE
18
18
  end
19
19
 
20
- attr_reader :path
20
+ attr_reader(:path)
21
21
 
22
22
  def initialize(path)
23
23
  @path = path.to_s
@@ -26,7 +26,7 @@ module Bootsnap
26
26
  # True if the path exists, but represents a non-directory object
27
27
  def non_directory?
28
28
  !File.stat(path).directory?
29
- rescue Errno::ENOENT
29
+ rescue Errno::ENOENT, Errno::ENOTDIR
30
30
  false
31
31
  end
32
32
 
@@ -76,8 +76,8 @@ module Bootsnap
76
76
  ["", *dirs].each do |dir|
77
77
  curr = begin
78
78
  File.mtime("#{path}/#{dir}").to_i
79
- rescue Errno::ENOENT
80
- -1
79
+ rescue Errno::ENOENT, Errno::ENOTDIR
80
+ -1
81
81
  end
82
82
  max = curr if curr > max
83
83
  end
@@ -1,4 +1,4 @@
1
- require_relative '../explicit_require'
1
+ require_relative('../explicit_require')
2
2
 
3
3
  module Bootsnap
4
4
  module LoadPathCache
@@ -7,8 +7,12 @@ module Bootsnap
7
7
  REQUIRABLE_EXTENSIONS = [DOT_RB] + DL_EXTENSIONS
8
8
  NORMALIZE_NATIVE_EXTENSIONS = !DL_EXTENSIONS.include?(LoadPathCache::DOT_SO)
9
9
  ALTERNATIVE_NATIVE_EXTENSIONS_PATTERN = /\.(o|bundle|dylib)\z/
10
- BUNDLE_PATH = Bootsnap.bundler? ?
11
- (Bundler.bundle_path.cleanpath.to_s << LoadPathCache::SLASH).freeze : ''.freeze
10
+
11
+ BUNDLE_PATH = if Bootsnap.bundler?
12
+ (Bundler.bundle_path.cleanpath.to_s << LoadPathCache::SLASH).freeze
13
+ else
14
+ ''.freeze
15
+ end
12
16
 
13
17
  def self.call(path)
14
18
  path = path.to_s
@@ -1,6 +1,6 @@
1
- require_relative '../explicit_require'
1
+ require_relative('../explicit_require')
2
2
 
3
- Bootsnap::ExplicitRequire.with_gems('msgpack') { require 'msgpack' }
3
+ Bootsnap::ExplicitRequire.with_gems('msgpack') { require('msgpack') }
4
4
  Bootsnap::ExplicitRequire.from_rubylibdir('fileutils')
5
5
 
6
6
  module Bootsnap
@@ -21,7 +21,7 @@ module Bootsnap
21
21
  end
22
22
 
23
23
  def fetch(key)
24
- raise SetOutsideTransactionNotAllowed unless @in_txn
24
+ raise(SetOutsideTransactionNotAllowed) unless @in_txn
25
25
  v = get(key)
26
26
  unless v
27
27
  @dirty = true
@@ -32,7 +32,7 @@ module Bootsnap
32
32
  end
33
33
 
34
34
  def set(key, value)
35
- raise SetOutsideTransactionNotAllowed unless @in_txn
35
+ raise(SetOutsideTransactionNotAllowed) unless @in_txn
36
36
  if value != @data[key]
37
37
  @dirty = true
38
38
  @data[key] = value
@@ -40,7 +40,7 @@ module Bootsnap
40
40
  end
41
41
 
42
42
  def transaction
43
- raise NestedTransactionError if @in_txn
43
+ raise(NestedTransactionError) if @in_txn
44
44
  @in_txn = true
45
45
  yield
46
46
  ensure
@@ -60,9 +60,9 @@ module Bootsnap
60
60
  def load_data
61
61
  @data = begin
62
62
  MessagePack.load(File.binread(@store_path))
63
- # handle malformed data due to upgrade incompatability
64
- rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
65
- {}
63
+ # handle malformed data due to upgrade incompatability
64
+ rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
65
+ {}
66
66
  end
67
67
  end
68
68
 
@@ -1,14 +1,8 @@
1
- require_relative '../bootsnap'
1
+ require_relative('../bootsnap')
2
2
 
3
3
  env = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || ENV['ENV']
4
4
  development_mode = ['', nil, 'development'].include?(env)
5
5
 
6
- # only enable on 'ruby' (MRI), POSIX (darwin, linux, *bsd), and >= 2.3.0
7
- enable_cc =
8
- RUBY_ENGINE == 'ruby' &&
9
- RUBY_PLATFORM =~ /darwin|linux|bsd/ &&
10
- Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.3.0")
11
-
12
6
  cache_dir = ENV['BOOTSNAP_CACHE_DIR']
13
7
  unless cache_dir
14
8
  config_dir_frame = caller.detect do |line|
@@ -16,11 +10,11 @@ unless cache_dir
16
10
  end
17
11
 
18
12
  unless config_dir_frame
19
- $stderr.puts "[bootsnap/setup] couldn't infer cache directory! Either:"
20
- $stderr.puts "[bootsnap/setup] 1. require bootsnap/setup from your application's config directory; or"
21
- $stderr.puts "[bootsnap/setup] 2. Define the environment variable BOOTSNAP_CACHE_DIR"
13
+ $stderr.puts("[bootsnap/setup] couldn't infer cache directory! Either:")
14
+ $stderr.puts("[bootsnap/setup] 1. require bootsnap/setup from your application's config directory; or")
15
+ $stderr.puts("[bootsnap/setup] 2. Define the environment variable BOOTSNAP_CACHE_DIR")
22
16
 
23
- raise "couldn't infer bootsnap cache directory"
17
+ raise("couldn't infer bootsnap cache directory")
24
18
  end
25
19
 
26
20
  path = config_dir_frame.split(/:\d+:/).first
@@ -36,6 +30,6 @@ Bootsnap.setup(
36
30
  load_path_cache: true,
37
31
  autoload_paths_cache: true, # assume rails. open to PRs to impl. detection
38
32
  disable_trace: false,
39
- compile_cache_iseq: enable_cc,
40
- compile_cache_yaml: enable_cc
33
+ compile_cache_iseq: true,
34
+ compile_cache_yaml: true,
41
35
  )
@@ -1,3 +1,3 @@
1
1
  module Bootsnap
2
- VERSION = "1.3.2"
2
+ VERSION = "1.4.0"
3
3
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootsnap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.4.0
5
5
  platform: java
6
6
  authors:
7
7
  - Burke Libbey
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-10 00:00:00.000000000 Z
11
+ date: 2019-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - "~>"
16
+ - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '1'
18
+ version: '0'
19
19
  name: bundler
20
20
  prerelease: false
21
21
  type: :development
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
@@ -112,8 +112,10 @@ files:
112
112
  - README.jp.md
113
113
  - README.md
114
114
  - Rakefile
115
+ - bin/ci
115
116
  - bin/console
116
117
  - bin/setup
118
+ - bin/test-minimal-support
117
119
  - bin/testunit
118
120
  - bootsnap.gemspec
119
121
  - dev.yml
@@ -131,6 +133,7 @@ files:
131
133
  - lib/bootsnap/load_path_cache/change_observer.rb
132
134
  - lib/bootsnap/load_path_cache/core_ext/active_support.rb
133
135
  - lib/bootsnap/load_path_cache/core_ext/kernel_require.rb
136
+ - lib/bootsnap/load_path_cache/core_ext/loaded_features.rb
134
137
  - lib/bootsnap/load_path_cache/loaded_features_index.rb
135
138
  - lib/bootsnap/load_path_cache/path.rb
136
139
  - lib/bootsnap/load_path_cache/path_scanner.rb
@@ -142,7 +145,10 @@ files:
142
145
  homepage: https://github.com/Shopify/bootsnap
143
146
  licenses:
144
147
  - MIT
145
- metadata: {}
148
+ metadata:
149
+ bug_tracker_uri: https://github.com/Shopify/bootsnap/issues
150
+ changelog_uri: https://github.com/Shopify/bootsnap/blob/master/CHANGELOG.md
151
+ source_code_uri: https://github.com/Shopify/bootsnap
146
152
  post_install_message:
147
153
  rdoc_options: []
148
154
  require_paths: