Hello community,
here is the log from the commit of package rubygem-bootsnap for openSUSE:Factory checked in at 2019-04-01 12:37:02
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-bootsnap (Old)
and /work/SRC/openSUSE:Factory/.rubygem-bootsnap.new.25356 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-bootsnap"
Mon Apr 1 12:37:02 2019 rev:2 rq:689708 version:1.4.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-bootsnap/rubygem-bootsnap.changes 2019-02-11 21:26:02.451059389 +0100
+++ /work/SRC/openSUSE:Factory/.rubygem-bootsnap.new.25356/rubygem-bootsnap.changes 2019-04-01 12:37:05.773877808 +0200
@@ -1,0 +2,32 @@
+Fri Mar 29 05:56:31 UTC 2019 - Stephan Kulow
+
+- updated to version 1.4.2
+ see installed CHANGELOG.md
+
+ # 1.4.2
+
+ * Fix bug when removing features loaded by relative path from `$LOADED_FEATURES`
+ * Fix bug with propagation of `NameError` up from nested calls to `require`
+
+-------------------------------------------------------------------
+Sat Mar 2 15:05:33 UTC 2019 - Stephan Kulow
+
+- updated to version 1.4.1
+ see installed CHANGELOG.md
+
+ # 1.4.1
+
+ * Don't register change observers to frozen objects.
+
+ # 1.4.0
+
+ * When running in development mode, always fall back to a full path scan on LoadError, making
+ bootsnap more able to detect newly-created files. (#230)
+ * Respect `$LOADED_FEATURES.delete` in order to support code reloading, for integration with
+ Zeitwerk. (#230)
+ * Minor performance improvement: flow-control exceptions no longer generate backtraces.
+ * Better support for requiring from environments where some features are not supported (especially
+ JRuby). (#226)k
+ * More robust handling of OS errors when creating files. (#225)
+
+-------------------------------------------------------------------
Old:
----
bootsnap-1.3.2.gem
New:
----
bootsnap-1.4.2.gem
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ rubygem-bootsnap.spec ++++++
--- /var/tmp/diff_new_pack.wAgJDk/_old 2019-04-01 12:37:06.309878070 +0200
+++ /var/tmp/diff_new_pack.wAgJDk/_new 2019-04-01 12:37:06.313878072 +0200
@@ -1,7 +1,7 @@
#
# spec file for package rubygem-bootsnap
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -12,7 +12,7 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
@@ -24,14 +24,14 @@
#
Name: rubygem-bootsnap
-Version: 1.3.2
+Version: 1.4.2
Release: 0
%define mod_name bootsnap
%define mod_full_name %{mod_name}-%{version}
BuildRoot: %{_tmppath}/%{name}-%{version}-build
-BuildRequires: ruby-macros >= 5
BuildRequires: %{rubydevel >= 2.0.0}
BuildRequires: %{rubygem gem2rpm}
+BuildRequires: ruby-macros >= 5
Url: https://github.com/Shopify/bootsnap
Source: https://rubygems.org/gems/%{mod_full_name}.gem
Source1: gem2rpm.yml
++++++ bootsnap-1.3.2.gem -> bootsnap-1.4.2.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.github/CODEOWNERS new/.github/CODEOWNERS
--- old/.github/CODEOWNERS 1970-01-01 01:00:00.000000000 +0100
+++ new/.github/CODEOWNERS 2019-03-26 16:12:36.000000000 +0100
@@ -0,0 +1,2 @@
+# mvm:maintainer
+* @burke
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.github/probots.yml new/.github/probots.yml
--- old/.github/probots.yml 1970-01-01 01:00:00.000000000 +0100
+++ new/.github/probots.yml 2019-03-26 16:12:36.000000000 +0100
@@ -0,0 +1,2 @@
+enabled:
+ - cla
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.travis.yml new/.travis.yml
--- old/.travis.yml 2018-09-10 20:40:32.000000000 +0200
+++ new/.travis.yml 2019-03-26 16:12:36.000000000 +0100
@@ -8,6 +8,14 @@
rvm:
- ruby-2.4
- ruby-2.5
+ - ruby-head
-before_script: rake
-script: bundle exec bin/testunit
+matrix:
+ allow_failures:
+ - rvm: ruby-head
+ include:
+ - rvm: jruby
+ os: linux
+ env: MINIMAL_SUPPORT=1
+
+script: bin/ci
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/CHANGELOG.md new/CHANGELOG.md
--- old/CHANGELOG.md 2018-09-10 20:40:32.000000000 +0200
+++ new/CHANGELOG.md 2019-03-26 16:12:36.000000000 +0100
@@ -1,3 +1,23 @@
+# 1.4.2
+
+* Fix bug when removing features loaded by relative path from `$LOADED_FEATURES`
+* Fix bug with propagation of `NameError` up from nested calls to `require`
+
+# 1.4.1
+
+* Don't register change observers to frozen objects.
+
+# 1.4.0
+
+* When running in development mode, always fall back to a full path scan on LoadError, making
+ bootsnap more able to detect newly-created files. (#230)
+* Respect `$LOADED_FEATURES.delete` in order to support code reloading, for integration with
+ Zeitwerk. (#230)
+* Minor performance improvement: flow-control exceptions no longer generate backtraces.
+* Better support for requiring from environments where some features are not supported (especially
+ JRuby). (#226)k
+* More robust handling of OS errors when creating files. (#225)
+
# 1.3.2
* Fix Spring + Bootsnap incompatibility when there are files with similar names.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/README.jp.md new/README.jp.md
--- old/README.jp.md 2018-09-10 20:40:32.000000000 +0200
+++ new/README.jp.md 2019-03-26 16:12:36.000000000 +0100
@@ -12,7 +12,7 @@
## 使用方法
-この gem は MacOS と Linux で作動します。まずは、`bootsnap` を `Gemfile` に追加します:
+この gem は macOS と Linux で作動します。まずは、`bootsnap` を `Gemfile` に追加します:
```ruby
gem 'bootsnap', require: false
@@ -24,6 +24,8 @@
require 'bootsnap/setup'
```
+単に `gem 'bootsnap', require: 'bootsnap/setup'` と指定することも技術的には可能ですが、最大限のパフォーマンス改善を得るためには Bootsnap をできるだけ早く読み込むことが重要です。
+
この require の仕組みは[こちら](https://github.com/Shopify/bootsnap/blob/master/lib/bootsnap/setup.rb)で確認できます。
Rails を使用していない場合、または、より多くの設定を変更したい場合は、以下のコードを `require 'bundler/setup'` の直後に追加してください(早く読み込まれるほど、より多くのものを最適化することができます)。
@@ -67,7 +69,7 @@
_(このライブラリは [bootscale](https://github.com/byroot/bootscale) という別のライブラリを元に開発されました)_
Bootsnap の初期化時、あるいはパス(例えば、`$LOAD_PATH`)の変更時に、`Bootsnap::LoadPathCache` がキャッシュから必要なエントリーのリストを読み込みます。または、必要に応じてフルスキャンを実行し結果をキャッシュします。
-その後、たとえば `require 'foo'` を評価する場合, Ruby は `$LOAD_PATH` `['x', 'y', ...]` のすべてのエントリーを繰り返し評価することで `x/foo.rb`, `y/foo.rb` などを探索します。これに対して Bootsnap は、キャッシュされた reuiqre 可能なファイルと `$LOAD_PATH` を見ることで、Rubyが最終的に選択するであろうパスで置き換えます。
+その後、たとえば `require 'foo'` を評価する場合, Ruby は `$LOAD_PATH` `['x', 'y', ...]` のすべてのエントリーを繰り返し評価することで `x/foo.rb`, `y/foo.rb` などを探索します。これに対して Bootsnap は、キャッシュされた require 可能なファイルと `$LOAD_PATH` を見ることで、Rubyが最終的に選択するであろうパスで置き換えます。
この動作によって生成された syscall を見ると、最終的な結果は以前なら次のようになります。
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/README.md new/README.md
--- old/README.md 2018-09-10 20:40:32.000000000 +0200
+++ new/README.md 2019-03-26 16:12:36.000000000 +0100
@@ -4,9 +4,14 @@
to optimize and cache expensive computations. See [How Does This Work](#how-does-this-work).
#### Performance
-- [Discourse](https://github.com/discourse/discourse) reports a boot time reduction of approximately 50%, from roughly 6 to 3 seconds on one machine;
+
+- [Discourse](https://github.com/discourse/discourse) reports a boot time reduction of approximately
+ 50%, from roughly 6 to 3 seconds on one machine;
- One of our smaller internal apps also sees a reduction of 50%, from 3.6 to 1.8 seconds;
-- The core Shopify platform -- a rather large monolithic application -- boots about 75% faster, dropping from around 25s to 6.5s.
+- The core Shopify platform -- a rather large monolithic application -- boots about 75% faster,
+ dropping from around 25s to 6.5s.
+* In Shopify core (a large app), about 25% of this gain can be attributed to `compile_cache_*`
+ features; 75% to path caching, and ~1% to `disable_trace`. This is fairly representative.
## Usage
@@ -24,6 +29,14 @@
require 'bootsnap/setup'
```
+Note that bootsnap writes to `tmp/cache`, and that directory *must* be writable. Rails will fail to
+boot if it is not. If this is unacceptable (e.g. you are running in a read-only container and
+unwilling to mount in a writable tmpdir), you should remove this line or wrap it in a conditional.
+
+**Note also that bootsnap will never clean up its own cache: this is left up to you. Depending on your
+deployment strategy, you may need to periodically purge `tmp/cache/bootsnap*`. If you notice deploys
+getting progressively slower, this is almost certainly the cause.**
+
It's technically possible to simply specify `gem 'bootsnap', require: 'bootsnap/setup'`, but it's
important to load Bootsnap as early as possible to get maximum performance improvement.
@@ -41,12 +54,14 @@
development_mode: env == 'development', # Current working environment, e.g. RACK_ENV, RAILS_ENV, etc
load_path_cache: true, # Optimize the LOAD_PATH with a cache
autoload_paths_cache: true, # Optimize ActiveSupport autoloads with cache
- disable_trace: true, # (Alpha) Set `RubyVM::InstructionSequence.compile_option = { trace_instruction: false }`
+ disable_trace: true, # Set `RubyVM::InstructionSequence.compile_option = { trace_instruction: false }`
compile_cache_iseq: true, # Compile Ruby code into ISeq cache, breaks coverage reporting.
compile_cache_yaml: true # Compile YAML into a cache
)
```
+**Note that `disable_trace` will break debuggers and tracing.**
+
**Protip:** You can replace `require 'bootsnap'` with `BootLib::Require.from_gem('bootsnap',
'bootsnap')` using [this trick](https://github.com/Shopify/bootsnap/wiki/Bootlib::Require). This
will help optimize boot time further if you have an extremely large `$LOAD_PATH`.
@@ -278,3 +293,12 @@
```
# (nothing!)
```
+
+## When not to use Bootsnap
+
+*Alternative engines*: Bootsnap is pretty reliant on MRI features, and parts are disabled entirely on alternative ruby
+engines.
+
+*Non-local filesystems*: Bootsnap depends on `tmp/cache` (or whatever you set its cache directory
+to) being on a relatively fast filesystem. If you put it on a network mount, bootsnap is very likely
+to slow your application down quite a lot.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Rakefile new/Rakefile
--- old/Rakefile 2018-09-10 20:40:32.000000000 +0200
+++ new/Rakefile 2019-03-26 16:12:36.000000000 +0100
@@ -1,5 +1,5 @@
-require 'rake/extensiontask'
-require 'bundler/gem_tasks'
+require('rake/extensiontask')
+require('bundler/gem_tasks')
gemspec = Gem::Specification.load('bootsnap.gemspec')
Rake::ExtensionTask.new do |ext|
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bin/ci new/bin/ci
--- old/bin/ci 1970-01-01 01:00:00.000000000 +0100
+++ new/bin/ci 2019-03-26 16:12:36.000000000 +0100
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+set -euxo pipefail
+
+if [[ "${MINIMAL_SUPPORT-0}" -eq 1 ]]; then
+ exec bin/test-minimal-support
+else
+ rake
+ exec bin/testunit
+fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bin/console new/bin/console
--- old/bin/console 2018-09-10 20:40:32.000000000 +0200
+++ new/bin/console 2019-03-26 16:12:36.000000000 +0100
@@ -1,7 +1,7 @@
#!/usr/bin/env ruby
-require "bundler/setup"
-require "bootsnap"
+require("bundler/setup")
+require("bootsnap")
# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@
# require "pry"
# Pry.start
-require "irb"
+require("irb")
IRB.start(__FILE__)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bin/test-minimal-support new/bin/test-minimal-support
--- old/bin/test-minimal-support 1970-01-01 01:00:00.000000000 +0100
+++ new/bin/test-minimal-support 2019-03-26 16:12:36.000000000 +0100
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+set -euxo pipefail
+
+cd test/minimal_support
+bundle
+BOOTSNAP_CACHE_DIR=/tmp bundle exec ruby -w -I ../../lib bootsnap_setup.rb
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bootsnap.gemspec new/bootsnap.gemspec
--- old/bootsnap.gemspec 2018-09-10 20:40:32.000000000 +0200
+++ new/bootsnap.gemspec 2019-03-26 16:12:36.000000000 +0100
@@ -1,7 +1,7 @@
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
-require 'bootsnap/version'
+require('bootsnap/version')
Gem::Specification.new do |spec|
spec.name = "bootsnap"
@@ -15,10 +15,16 @@
spec.description = spec.summary
spec.homepage = "https://github.com/Shopify/bootsnap"
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
+ spec.metadata = {
+ 'bug_tracker_uri' => 'https://github.com/Shopify/bootsnap/issues',
+ 'changelog_uri' => 'https://github.com/Shopify/bootsnap/blob/master/CHANGELOG.md',
+ 'source_code_uri' => 'https://github.com/Shopify/bootsnap',
+ }
+
+ spec.files = %x(git ls-files -z).split("\x0").reject do |f|
f.match(%r{^(test|spec|features)/})
end
- spec.require_paths = ["lib"]
+ spec.require_paths = %w(lib)
spec.required_ruby_version = '>= 2.0.0'
@@ -29,11 +35,11 @@
spec.extensions = ['ext/bootsnap/extconf.rb']
end
- spec.add_development_dependency "bundler", '~> 1'
- spec.add_development_dependency 'rake', '~> 10.0'
- spec.add_development_dependency 'rake-compiler', '~> 0'
- spec.add_development_dependency "minitest", "~> 5.0"
- spec.add_development_dependency "mocha", "~> 1.2"
+ spec.add_development_dependency("bundler")
+ spec.add_development_dependency('rake', '~> 10.0')
+ spec.add_development_dependency('rake-compiler', '~> 0')
+ spec.add_development_dependency("minitest", "~> 5.0")
+ spec.add_development_dependency("mocha", "~> 1.2")
- spec.add_runtime_dependency "msgpack", "~> 1.0"
+ spec.add_runtime_dependency("msgpack", "~> 1.0")
end
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dev.yml new/dev.yml
--- old/dev.yml 2018-09-10 20:40:32.000000000 +0200
+++ new/dev.yml 2019-03-26 16:12:36.000000000 +0100
@@ -2,7 +2,7 @@
BOOTSNAP_PEDANTIC: '1'
up:
- - ruby: 2.3.3
+ - ruby: 2.6.0
- bundler
commands:
build: rake compile
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ext/bootsnap/bootsnap.c new/ext/bootsnap/bootsnap.c
--- old/ext/bootsnap/bootsnap.c 2018-09-10 20:40:32.000000000 +0200
+++ new/ext/bootsnap/bootsnap.c 2019-03-26 16:12:36.000000000 +0100
@@ -468,21 +468,21 @@
atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data, char ** errno_provenance)
{
char template[MAX_CACHEPATH_SIZE + 20];
- char * dest;
char * tmp_path;
int fd, ret;
ssize_t nwrite;
- dest = strncpy(template, path, MAX_CACHEPATH_SIZE);
- strcat(dest, ".tmp.XXXXXX");
+ tmp_path = strncpy(template, path, MAX_CACHEPATH_SIZE);
+ strcat(tmp_path, ".tmp.XXXXXX");
- tmp_path = mktemp(template);
- fd = open(tmp_path, O_WRONLY | O_CREAT, 0664);
+ // mkstemp modifies the template to be the actual created path
+ fd = mkstemp(tmp_path);
if (fd < 0) {
- if (mkpath(path, 0775) < 0) {
+ if (mkpath(tmp_path, 0775) < 0) {
*errno_provenance = (char *)"bs_fetch:atomic_write_cache_file:mkpath";
return -1;
}
+ close(fd);
fd = open(tmp_path, O_WRONLY | O_CREAT, 0664);
if (fd < 0) {
*errno_provenance = (char *)"bs_fetch:atomic_write_cache_file:open";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ext/bootsnap/extconf.rb new/ext/bootsnap/extconf.rb
--- old/ext/bootsnap/extconf.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/ext/bootsnap/extconf.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,4 +1,4 @@
-require "mkmf"
+require("mkmf")
$CFLAGS << ' -O3 '
$CFLAGS << ' -std=c99'
@@ -12,6 +12,7 @@
$CFLAGS << ' -Wno-unused-parameter' # VALUE self has to be there but we don't care what it is.
$CFLAGS << ' -Wno-keyword-macro' # hiding return
+ $CFLAGS << ' -Wno-gcc-compat' # ruby.h 2.6.0 on macos 10.14, dunno
end
create_makefile("bootsnap/bootsnap")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/bundler.rb new/lib/bootsnap/bundler.rb
--- old/lib/bootsnap/bundler.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/bundler.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,11 +1,11 @@
module Bootsnap
- module_function
+ extend(self)
def bundler?
return false unless defined?(::Bundler)
# Bundler environment variable
- ['BUNDLE_BIN_PATH', 'BUNDLE_GEMFILE'].each do |current|
+ %w(BUNDLE_BIN_PATH BUNDLE_GEMFILE).each do |current|
return true if ENV.key?(current)
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/compile_cache/iseq.rb new/lib/bootsnap/compile_cache/iseq.rb
--- old/lib/bootsnap/compile_cache/iseq.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/compile_cache/iseq.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,25 +1,25 @@
-require 'bootsnap/bootsnap'
-require 'zlib'
+require('bootsnap/bootsnap')
+require('zlib')
module Bootsnap
module CompileCache
module ISeq
class << self
- attr_accessor :cache_dir
+ attr_accessor(:cache_dir)
end
def self.input_to_storage(_, path)
RubyVM::InstructionSequence.compile_file(path).to_binary
rescue SyntaxError
- raise Uncompilable, 'syntax error'
+ raise(Uncompilable, 'syntax error')
end
def self.storage_to_output(binary)
RubyVM::InstructionSequence.load_from_binary(binary)
rescue RuntimeError => e
if e.message == 'broken binary format'
- STDERR.puts "[Bootsnap::CompileCache] warning: rejecting broken binary"
- return nil
+ STDERR.puts("[Bootsnap::CompileCache] warning: rejecting broken binary")
+ nil
else
raise
end
@@ -39,9 +39,11 @@
path.to_s,
Bootsnap::CompileCache::ISeq
)
+ rescue Errno::EACCES
+ Bootsnap::CompileCache.permission_error(path)
rescue RuntimeError => e
if e.message =~ /unmatched platform/
- puts "unmatched platform for file #{path}"
+ puts("unmatched platform for file #{path}")
end
raise
end
@@ -62,7 +64,7 @@
Bootsnap::CompileCache::ISeq.cache_dir = cache_dir
Bootsnap::CompileCache::ISeq.compile_option_updated
class << RubyVM::InstructionSequence
- prepend InstructionSequenceMixin
+ prepend(InstructionSequenceMixin)
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/compile_cache/yaml.rb new/lib/bootsnap/compile_cache/yaml.rb
--- old/lib/bootsnap/compile_cache/yaml.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/compile_cache/yaml.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,21 +1,21 @@
-require 'bootsnap/bootsnap'
+require('bootsnap/bootsnap')
module Bootsnap
module CompileCache
module YAML
class << self
- attr_accessor :msgpack_factory
+ attr_accessor(:msgpack_factory)
end
def self.input_to_storage(contents, _)
- raise Uncompilable if contents.index("!ruby/object")
+ raise(Uncompilable) if contents.index("!ruby/object")
obj = ::YAML.load(contents)
msgpack_factory.packer.write(obj).to_s
rescue NoMethodError, RangeError
# if the object included things that we can't serialize, fall back to
# Marshal. It's a bit slower, but can encode anything yaml can.
# NoMethodError is unexpected types; RangeError is Bignums
- return Marshal.dump(obj)
+ Marshal.dump(obj)
end
def self.storage_to_output(data)
@@ -34,8 +34,8 @@
end
def self.install!(cache_dir)
- require 'yaml'
- require 'msgpack'
+ require('yaml')
+ require('msgpack')
# MessagePack serializes symbols as strings by default.
# We want them to roundtrip cleanly, so we use a custom factory.
@@ -46,11 +46,15 @@
klass = class << ::YAML; self; end
klass.send(:define_method, :load_file) do |path|
- Bootsnap::CompileCache::Native.fetch(
- cache_dir,
- path,
- Bootsnap::CompileCache::YAML
- )
+ begin
+ Bootsnap::CompileCache::Native.fetch(
+ cache_dir,
+ path,
+ Bootsnap::CompileCache::YAML
+ )
+ rescue Errno::EACCES
+ Bootsnap::CompileCache.permission_error(path)
+ end
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/compile_cache.rb new/lib/bootsnap/compile_cache.rb
--- old/lib/bootsnap/compile_cache.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/compile_cache.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,15 +1,42 @@
module Bootsnap
module CompileCache
+ Error = Class.new(StandardError)
+ PermissionError = Class.new(Error)
+
def self.setup(cache_dir:, iseq:, yaml:)
if iseq
- require_relative 'compile_cache/iseq'
- Bootsnap::CompileCache::ISeq.install!(cache_dir)
+ if supported?
+ require_relative('compile_cache/iseq')
+ Bootsnap::CompileCache::ISeq.install!(cache_dir)
+ elsif $VERBOSE
+ warn("[bootsnap/setup] bytecode caching is not supported on this implementation of Ruby")
+ end
end
if yaml
- require_relative 'compile_cache/yaml'
- Bootsnap::CompileCache::YAML.install!(cache_dir)
+ if supported?
+ require_relative('compile_cache/yaml')
+ Bootsnap::CompileCache::YAML.install!(cache_dir)
+ elsif $VERBOSE
+ warn("[bootsnap/setup] YAML parsing caching is not supported on this implementation of Ruby")
+ end
end
end
+
+ def self.permission_error(path)
+ cpath = Bootsnap::CompileCache::ISeq.cache_dir
+ raise(
+ PermissionError,
+ "bootsnap doesn't have permission to write cache entries in '#{cpath}' " \
+ "(or, less likely, doesn't have permisison to read '#{path}')",
+ )
+ end
+
+ def self.supported?
+ # only enable on 'ruby' (MRI), POSIX (darwin, linux, *bsd), and >= 2.3.0
+ RUBY_ENGINE == 'ruby' &&
+ RUBY_PLATFORM =~ /darwin|linux|bsd/ &&
+ Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.3.0")
+ end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/explicit_require.rb new/lib/bootsnap/explicit_require.rb
--- old/lib/bootsnap/explicit_require.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/explicit_require.rb 2019-03-26 16:12:36.000000000 +0100
@@ -5,7 +5,7 @@
DLEXT = RbConfig::CONFIG['DLEXT']
def self.from_self(feature)
- require_relative "../#{feature}"
+ require_relative("../#{feature}")
end
def self.from_rubylibdir(feature)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/load_path_cache/cache.rb new/lib/bootsnap/load_path_cache/cache.rb
--- old/lib/bootsnap/load_path_cache/cache.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/load_path_cache/cache.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,4 +1,6 @@
-require_relative '../explicit_require'
+# frozen_string_literal: true
+
+require_relative('../explicit_require')
module Bootsnap
module LoadPathCache
@@ -46,7 +48,7 @@
reinitialize if (@has_relative_paths && dir_changed?) || stale?
feature = feature.to_s
return feature if absolute_path?(feature)
- return File.expand_path(feature) if feature.start_with?('./')
+ return expand_path(feature) if feature.start_with?('./')
@mutex.synchronize do
x = search_index(feature)
return x if x
@@ -56,7 +58,7 @@
# returns false as if it were already loaded; however, there is no
# file to find on disk. We've pre-built a list of these, and we
# return false if any of them is loaded.
- raise LoadPathCache::ReturnFalse if BUILTIN_FEATURES.key?(feature)
+ raise(LoadPathCache::ReturnFalse, '', []) if BUILTIN_FEATURES.key?(feature)
# The feature wasn't found on our preliminary search through the index.
# We resolve this differently depending on what the extension was.
@@ -73,14 +75,21 @@
x = search_index(feature[0..-4] + DLEXT)
return x if x
if DLEXT2
- search_index(feature[0..-4] + DLEXT2)
+ x = search_index(feature[0..-4] + DLEXT2)
+ return x if x
end
else
# other, unknown extension. For example, `.rake`. Since we haven't
# cached these, we legitimately need to run the load path search.
- raise LoadPathCache::FallbackScan
+ raise(LoadPathCache::FallbackScan, '', [])
end
end
+
+ # In development mode, we don't want to confidently return failures for
+ # cases where the file doesn't appear to be on the load path. We should
+ # be able to detect newly-created files without rebooting the
+ # application.
+ raise(LoadPathCache::FallbackScan, '', []) if @development_mode
end
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
@@ -155,6 +164,10 @@
end
end
+ def expand_path(feature)
+ maybe_append_extension(File.expand_path(feature))
+ end
+
def stale?
@development_mode && @generated_at + AGE_THRESHOLD < now
end
@@ -167,17 +180,29 @@
def search_index(f)
try_index(f + DOT_RB) || try_index(f + DLEXT) || try_index(f + DLEXT2) || try_index(f)
end
+
+ def maybe_append_extension(f)
+ try_ext(f + DOT_RB) || try_ext(f + DLEXT) || try_ext(f + DLEXT2) || f
+ end
else
def search_index(f)
try_index(f + DOT_RB) || try_index(f + DLEXT) || try_index(f)
end
+
+ def maybe_append_extension(f)
+ try_ext(f + DOT_RB) || try_ext(f + DLEXT) || f
+ end
end
def try_index(f)
- if p = @index[f]
+ if (p = @index[f])
p + '/' + f
end
end
+
+ def try_ext(f)
+ f if File.exist?(f)
+ end
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/load_path_cache/change_observer.rb new/lib/bootsnap/load_path_cache/change_observer.rb
--- old/lib/bootsnap/load_path_cache/change_observer.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/load_path_cache/change_observer.rb 2019-03-26 16:12:36.000000000 +0100
@@ -53,6 +53,7 @@
end
def self.register(observer, arr)
+ return if arr.frozen? # can't register observer, but no need to.
arr.instance_variable_set(:@lpc_observer, observer)
arr.extend(ArrayMixin)
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/load_path_cache/core_ext/active_support.rb new/lib/bootsnap/load_path_cache/core_ext/active_support.rb
--- old/lib/bootsnap/load_path_cache/core_ext/active_support.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/load_path_cache/core_ext/active_support.rb 2019-03-26 16:12:36.000000000 +0100
@@ -30,6 +30,8 @@
Bootsnap::LoadPathCache.autoload_paths_cache.find(path)
rescue Bootsnap::LoadPathCache::ReturnFalse
nil # doesn't really apply here
+ rescue Bootsnap::LoadPathCache::FallbackScan
+ nil # doesn't really apply here
end
end
@@ -58,19 +60,22 @@
super
end
rescue NameError => e
+ raise(e) if e.instance_variable_defined?(Bootsnap::LoadPathCache::ERROR_TAG_IVAR)
+ e.instance_variable_set(Bootsnap::LoadPathCache::ERROR_TAG_IVAR, true)
+
# This function can end up called recursively, we only want to
# retry at the top-level.
- raise if Thread.current[:without_bootsnap_retry]
+ raise(e) if Thread.current[:without_bootsnap_retry]
# If we already had cache disabled, there's no use retrying
- raise if Thread.current[:without_bootsnap_cache]
+ raise(e) if Thread.current[:without_bootsnap_cache]
# NoMethodError is a NameError, but we only want to handle actual
# NameError instances.
- raise unless e.class == NameError
+ raise(e) unless e.class == NameError
# We can only confidently handle cases when *this* constant fails
# to load, not other constants referred to by it.
- raise unless e.name == const_name
+ raise(e) unless e.name == const_name
# If the constant was actually loaded, something else went wrong?
- raise if from_mod.const_defined?(const_name)
+ raise(e) if from_mod.const_defined?(const_name)
CoreExt::ActiveSupport.without_bootsnap_cache { super }
end
@@ -78,9 +83,12 @@
# reiterate it with version polymorphism here...
def depend_on(*)
super
- rescue LoadError
+ rescue LoadError => e
+ raise(e) if e.instance_variable_defined?(Bootsnap::LoadPathCache::ERROR_TAG_IVAR)
+ e.instance_variable_set(Bootsnap::LoadPathCache::ERROR_TAG_IVAR, true)
+
# If we already had cache disabled, there's no use retrying
- raise if Thread.current[:without_bootsnap_cache]
+ raise(e) if Thread.current[:without_bootsnap_cache]
CoreExt::ActiveSupport.without_bootsnap_cache { super }
end
end
@@ -92,7 +100,7 @@
module ActiveSupport
module Dependencies
class << self
- prepend Bootsnap::LoadPathCache::CoreExt::ActiveSupport::ClassMethods
+ prepend(Bootsnap::LoadPathCache::CoreExt::ActiveSupport::ClassMethods)
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb new/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb
--- old/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb 2019-03-26 16:12:36.000000000 +0100
@@ -3,6 +3,7 @@
module CoreExt
def self.make_load_error(path)
err = LoadError.new("cannot load such file -- #{path}")
+ err.instance_variable_set(Bootsnap::LoadPathCache::ERROR_TAG_IVAR, true)
err.define_singleton_method(:path) { path }
err
end
@@ -11,9 +12,9 @@
end
module Kernel
- module_function
+ module_function # rubocop:disable Style/ModuleFunction
- alias_method :require_without_bootsnap, :require
+ alias_method(:require_without_bootsnap, :require)
# Note that require registers to $LOADED_FEATURES while load does not.
def require_with_bootsnap_lfi(path, resolved = nil)
@@ -25,18 +26,21 @@
def require(path)
return false if Bootsnap::LoadPathCache.loaded_features_index.key?(path)
- if resolved = Bootsnap::LoadPathCache.load_path_cache.find(path)
+ if (resolved = Bootsnap::LoadPathCache.load_path_cache.find(path))
return require_with_bootsnap_lfi(path, resolved)
end
- raise Bootsnap::LoadPathCache::CoreExt.make_load_error(path)
+ raise(Bootsnap::LoadPathCache::CoreExt.make_load_error(path))
+ rescue LoadError => e
+ e.instance_variable_set(Bootsnap::LoadPathCache::ERROR_TAG_IVAR, true)
+ raise(e)
rescue Bootsnap::LoadPathCache::ReturnFalse
- return false
+ false
rescue Bootsnap::LoadPathCache::FallbackScan
require_with_bootsnap_lfi(path)
end
- alias_method :require_relative_without_bootsnap, :require_relative
+ alias_method(:require_relative_without_bootsnap, :require_relative)
def require_relative(path)
realpath = Bootsnap::LoadPathCache.realpath_cache.call(
caller_locations(1..1).first.absolute_path, path
@@ -44,9 +48,9 @@
require(realpath)
end
- alias_method :load_without_bootsnap, :load
+ alias_method(:load_without_bootsnap, :load)
def load(path, wrap = false)
- if resolved = Bootsnap::LoadPathCache.load_path_cache.find(path)
+ if (resolved = Bootsnap::LoadPathCache.load_path_cache.find(path))
return load_without_bootsnap(resolved, wrap)
end
@@ -55,16 +59,19 @@
return load_without_bootsnap(relative, wrap)
end
- raise Bootsnap::LoadPathCache::CoreExt.make_load_error(path)
+ raise(Bootsnap::LoadPathCache::CoreExt.make_load_error(path))
+ rescue LoadError => e
+ e.instance_variable_set(Bootsnap::LoadPathCache::ERROR_TAG_IVAR, true)
+ raise(e)
rescue Bootsnap::LoadPathCache::ReturnFalse
- return false
+ false
rescue Bootsnap::LoadPathCache::FallbackScan
load_without_bootsnap(path, wrap)
end
end
class Module
- alias_method :autoload_without_bootsnap, :autoload
+ alias_method(:autoload_without_bootsnap, :autoload)
def autoload(const, path)
# NOTE: This may defeat LoadedFeaturesIndex, but it's not immediately
# obvious how to make it work. This feels like a pretty niche case, unclear
@@ -74,8 +81,11 @@
# added to $LOADED_FEATURES and won't be able to hook that modification
# since it's done in C-land.
autoload_without_bootsnap(const, Bootsnap::LoadPathCache.load_path_cache.find(path) || path)
+ rescue LoadError => e
+ e.instance_variable_set(Bootsnap::LoadPathCache::ERROR_TAG_IVAR, true)
+ raise(e)
rescue Bootsnap::LoadPathCache::ReturnFalse
- return false
+ false
rescue Bootsnap::LoadPathCache::FallbackScan
autoload_without_bootsnap(const, path)
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb new/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb
--- old/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb 1970-01-01 01:00:00.000000000 +0100
+++ new/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb 2019-03-26 16:12:36.000000000 +0100
@@ -0,0 +1,17 @@
+class << $LOADED_FEATURES
+ alias_method(:delete_without_bootsnap, :delete)
+ def delete(key)
+ Bootsnap::LoadPathCache.loaded_features_index.purge(key)
+ delete_without_bootsnap(key)
+ end
+
+ alias_method(:reject_without_bootsnap!, :reject!)
+ def reject!(&block)
+ backup = dup
+
+ # FIXME: if no block is passed we'd need to return a decorated iterator
+ reject_without_bootsnap!(&block)
+
+ Bootsnap::LoadPathCache.loaded_features_index.purge_multi(backup - self)
+ end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/load_path_cache/loaded_features_index.rb new/lib/bootsnap/load_path_cache/loaded_features_index.rb
--- old/lib/bootsnap/load_path_cache/loaded_features_index.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/load_path_cache/loaded_features_index.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bootsnap
module LoadPathCache
# LoadedFeaturesIndex partially mirrors an internal structure in ruby that
@@ -32,17 +34,36 @@
# parallel the work done with ChangeObserver on $LOAD_PATH to mirror
# updates to our @lfi.
$LOADED_FEATURES.each do |feat|
+ hash = feat.hash
$LOAD_PATH.each do |lpe|
next unless feat.start_with?(lpe)
# /a/b/lib/my/foo.rb
# ^^^^^^^^^
short = feat[(lpe.length + 1)..-1]
- @lfi[short] = true
- @lfi[strip_extension(short)] = true
+ stripped = strip_extension(short)
+ @lfi[short] = hash
+ @lfi[stripped] = hash
end
end
end
+ # We've optimized for initialize and register to be fast, and purge to be tolerable.
+ # If access patterns make this not-okay, we can lazy-invert the LFI on
+ # first purge and work from there.
+ def purge(feature)
+ @mutex.synchronize do
+ feat_hash = feature.hash
+ @lfi.reject! { |_, hash| hash == feat_hash }
+ end
+ end
+
+ def purge_multi(features)
+ rejected_hashes = features.map(&:hash).to_set
+ @mutex.synchronize do
+ @lfi.reject! { |_, hash| rejected_hashes.include?(hash) }
+ end
+ end
+
def key?(feature)
@mutex.synchronize { @lfi.key?(feature) }
end
@@ -62,21 +83,30 @@
# 2. Inspect $LOADED_FEATURES upon return from yield to find the matching
# entry.
def register(short, long = nil)
- ret = yield
+ if long.nil?
+ pat = %r{/#{Regexp.escape(short)}(\.[^/]+)?$}
+ len = $LOADED_FEATURES.size
+ ret = yield
+ long = $LOADED_FEATURES[len..-1].detect { |feat| feat =~ pat }
+ else
+ ret = yield
+ end
+
+ hash = long.hash
# do we have 'bundler' or 'bundler.rb'?
altname = if File.extname(short) != ''
# strip the path from 'bundler.rb' -> 'bundler'
strip_extension(short)
- elsif long && ext = File.extname(long)
+ elsif long && (ext = File.extname(long))
# get the extension from the expanded path if given
# 'bundler' + '.rb'
short + ext
end
@mutex.synchronize do
- @lfi[short] = true
- (@lfi[altname] = true) if altname
+ @lfi[short] = hash
+ (@lfi[altname] = hash) if altname
end
ret
@@ -85,7 +115,7 @@
private
STRIP_EXTENSION = /\.[^.]*?$/
- private_constant :STRIP_EXTENSION
+ private_constant(:STRIP_EXTENSION)
def strip_extension(f)
f.sub(STRIP_EXTENSION, '')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/load_path_cache/path.rb new/lib/bootsnap/load_path_cache/path.rb
--- old/lib/bootsnap/load_path_cache/path.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/load_path_cache/path.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,4 +1,4 @@
-require_relative 'path_scanner'
+require_relative('path_scanner')
module Bootsnap
module LoadPathCache
@@ -17,7 +17,7 @@
stability == VOLATILE
end
- attr_reader :path
+ attr_reader(:path)
def initialize(path)
@path = path.to_s
@@ -26,7 +26,7 @@
# True if the path exists, but represents a non-directory object
def non_directory?
!File.stat(path).directory?
- rescue Errno::ENOENT
+ rescue Errno::ENOENT, Errno::ENOTDIR
false
end
@@ -76,8 +76,8 @@
["", *dirs].each do |dir|
curr = begin
File.mtime("#{path}/#{dir}").to_i
- rescue Errno::ENOENT
- -1
+ rescue Errno::ENOENT, Errno::ENOTDIR
+ -1
end
max = curr if curr > max
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/load_path_cache/path_scanner.rb new/lib/bootsnap/load_path_cache/path_scanner.rb
--- old/lib/bootsnap/load_path_cache/path_scanner.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/load_path_cache/path_scanner.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,4 +1,6 @@
-require_relative '../explicit_require'
+# frozen_string_literal: true
+
+require_relative('../explicit_require')
module Bootsnap
module LoadPathCache
@@ -7,8 +9,12 @@
REQUIRABLE_EXTENSIONS = [DOT_RB] + DL_EXTENSIONS
NORMALIZE_NATIVE_EXTENSIONS = !DL_EXTENSIONS.include?(LoadPathCache::DOT_SO)
ALTERNATIVE_NATIVE_EXTENSIONS_PATTERN = /\.(o|bundle|dylib)\z/
- BUNDLE_PATH = Bootsnap.bundler? ?
- (Bundler.bundle_path.cleanpath.to_s << LoadPathCache::SLASH).freeze : ''.freeze
+
+ BUNDLE_PATH = if Bootsnap.bundler?
+ (Bundler.bundle_path.cleanpath.to_s << LoadPathCache::SLASH).freeze
+ else
+ ''
+ end
def self.call(path)
path = path.to_s
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/load_path_cache/store.rb new/lib/bootsnap/load_path_cache/store.rb
--- old/lib/bootsnap/load_path_cache/store.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/load_path_cache/store.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,6 +1,6 @@
-require_relative '../explicit_require'
+require_relative('../explicit_require')
-Bootsnap::ExplicitRequire.with_gems('msgpack') { require 'msgpack' }
+Bootsnap::ExplicitRequire.with_gems('msgpack') { require('msgpack') }
Bootsnap::ExplicitRequire.from_rubylibdir('fileutils')
module Bootsnap
@@ -21,7 +21,7 @@
end
def fetch(key)
- raise SetOutsideTransactionNotAllowed unless @in_txn
+ raise(SetOutsideTransactionNotAllowed) unless @in_txn
v = get(key)
unless v
@dirty = true
@@ -32,7 +32,7 @@
end
def set(key, value)
- raise SetOutsideTransactionNotAllowed unless @in_txn
+ raise(SetOutsideTransactionNotAllowed) unless @in_txn
if value != @data[key]
@dirty = true
@data[key] = value
@@ -40,7 +40,7 @@
end
def transaction
- raise NestedTransactionError if @in_txn
+ raise(NestedTransactionError) if @in_txn
@in_txn = true
yield
ensure
@@ -60,9 +60,11 @@
def load_data
@data = begin
MessagePack.load(File.binread(@store_path))
- # handle malformed data due to upgrade incompatability
+ # handle malformed data due to upgrade incompatability
rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
{}
+ rescue ArgumentError => e
+ e.message =~ /negative array size/ ? {} : raise
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/load_path_cache.rb new/lib/bootsnap/load_path_cache.rb
--- old/lib/bootsnap/load_path_cache.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/load_path_cache.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bootsnap
module LoadPathCache
ReturnFalse = Class.new(StandardError)
@@ -7,6 +9,11 @@
DOT_SO = '.so'
SLASH = '/'
+ # If a NameError happens several levels deep, don't re-handle it
+ # all the way up the chain: mark it once and bubble it up without
+ # more retries.
+ ERROR_TAG_IVAR = :@__bootsnap_rescued
+
DL_EXTENSIONS = ::RbConfig::CONFIG
.values_at('DLEXT', 'DLEXT2')
.reject { |ext| !ext || ext.empty? }
@@ -21,38 +28,51 @@
CACHED_EXTENSIONS = DLEXT2 ? [DOT_RB, DLEXT, DLEXT2] : [DOT_RB, DLEXT]
class << self
- attr_reader :load_path_cache, :autoload_paths_cache,
- :loaded_features_index, :realpath_cache
+ attr_reader(:load_path_cache, :autoload_paths_cache,
+ :loaded_features_index, :realpath_cache)
def setup(cache_path:, development_mode:, active_support: true)
+ unless supported?
+ warn("[bootsnap/setup] Load path caching is not supported on this implementation of Ruby") if $VERBOSE
+ return
+ end
+
store = Store.new(cache_path)
@loaded_features_index = LoadedFeaturesIndex.new
@realpath_cache = RealpathCache.new
@load_path_cache = Cache.new(store, $LOAD_PATH, development_mode: development_mode)
- require_relative 'load_path_cache/core_ext/kernel_require'
+ require_relative('load_path_cache/core_ext/kernel_require')
+ require_relative('load_path_cache/core_ext/loaded_features')
if active_support
# this should happen after setting up the initial cache because it
# loads a lot of code. It's better to do after +require+ is optimized.
- require 'active_support/dependencies'
+ require('active_support/dependencies')
@autoload_paths_cache = Cache.new(
store,
::ActiveSupport::Dependencies.autoload_paths,
development_mode: development_mode
)
- require_relative 'load_path_cache/core_ext/active_support'
+ require_relative('load_path_cache/core_ext/active_support')
end
end
+
+ def supported?
+ RUBY_ENGINE == 'ruby' &&
+ RUBY_PLATFORM =~ /darwin|linux|bsd/
+ end
end
end
end
-require_relative 'load_path_cache/path_scanner'
-require_relative 'load_path_cache/path'
-require_relative 'load_path_cache/cache'
-require_relative 'load_path_cache/store'
-require_relative 'load_path_cache/change_observer'
-require_relative 'load_path_cache/loaded_features_index'
-require_relative 'load_path_cache/realpath_cache'
+if Bootsnap::LoadPathCache.supported?
+ require_relative('load_path_cache/path_scanner')
+ require_relative('load_path_cache/path')
+ require_relative('load_path_cache/cache')
+ require_relative('load_path_cache/store')
+ require_relative('load_path_cache/change_observer')
+ require_relative('load_path_cache/loaded_features_index')
+ require_relative('load_path_cache/realpath_cache')
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/setup.rb new/lib/bootsnap/setup.rb
--- old/lib/bootsnap/setup.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/setup.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,14 +1,8 @@
-require_relative '../bootsnap'
+require_relative('../bootsnap')
env = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || ENV['ENV']
development_mode = ['', nil, 'development'].include?(env)
-# only enable on 'ruby' (MRI), POSIX (darwin, linux, *bsd), and >= 2.3.0
-enable_cc =
- RUBY_ENGINE == 'ruby' &&
- RUBY_PLATFORM =~ /darwin|linux|bsd/ &&
- Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.3.0")
-
cache_dir = ENV['BOOTSNAP_CACHE_DIR']
unless cache_dir
config_dir_frame = caller.detect do |line|
@@ -16,11 +10,11 @@
end
unless config_dir_frame
- $stderr.puts "[bootsnap/setup] couldn't infer cache directory! Either:"
- $stderr.puts "[bootsnap/setup] 1. require bootsnap/setup from your application's config directory; or"
- $stderr.puts "[bootsnap/setup] 2. Define the environment variable BOOTSNAP_CACHE_DIR"
+ $stderr.puts("[bootsnap/setup] couldn't infer cache directory! Either:")
+ $stderr.puts("[bootsnap/setup] 1. require bootsnap/setup from your application's config directory; or")
+ $stderr.puts("[bootsnap/setup] 2. Define the environment variable BOOTSNAP_CACHE_DIR")
- raise "couldn't infer bootsnap cache directory"
+ raise("couldn't infer bootsnap cache directory")
end
path = config_dir_frame.split(/:\d+:/).first
@@ -36,6 +30,6 @@
load_path_cache: true,
autoload_paths_cache: true, # assume rails. open to PRs to impl. detection
disable_trace: false,
- compile_cache_iseq: enable_cc,
- compile_cache_yaml: enable_cc
+ compile_cache_iseq: true,
+ compile_cache_yaml: true,
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap/version.rb new/lib/bootsnap/version.rb
--- old/lib/bootsnap/version.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap/version.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,3 +1,3 @@
module Bootsnap
- VERSION = "1.3.2"
+ VERSION = "1.4.2"
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/bootsnap.rb new/lib/bootsnap.rb
--- old/lib/bootsnap.rb 2018-09-10 20:40:32.000000000 +0200
+++ new/lib/bootsnap.rb 2019-03-26 16:12:36.000000000 +0100
@@ -1,7 +1,7 @@
-require_relative 'bootsnap/version'
-require_relative 'bootsnap/bundler'
-require_relative 'bootsnap/load_path_cache'
-require_relative 'bootsnap/compile_cache'
+require_relative('bootsnap/version')
+require_relative('bootsnap/bundler')
+require_relative('bootsnap/load_path_cache')
+require_relative('bootsnap/compile_cache')
module Bootsnap
InvalidConfiguration = Class.new(StandardError)
@@ -16,7 +16,7 @@
compile_cache_yaml: true
)
if autoload_paths_cache && !load_path_cache
- raise InvalidConfiguration, "feature 'autoload_paths_cache' depends on feature 'load_path_cache'"
+ raise(InvalidConfiguration, "feature 'autoload_paths_cache' depends on feature 'load_path_cache'")
end
setup_disable_trace if disable_trace
@@ -36,7 +36,10 @@
def self.setup_disable_trace
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0')
- 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")
+ 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",
+ )
else
RubyVM::InstructionSequence.compile_option = { trace_instruction: false }
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata
--- old/metadata 2018-09-10 20:40:32.000000000 +0200
+++ new/metadata 2019-03-26 16:12:36.000000000 +0100
@@ -1,29 +1,29 @@
--- !ruby/object:Gem::Specification
name: bootsnap
version: !ruby/object:Gem::Version
- version: 1.3.2
+ version: 1.4.2
platform: ruby
authors:
- Burke Libbey
autorequire:
bindir: bin
cert_chain: []
-date: 2018-09-10 00:00:00.000000000 Z
+date: 2019-03-26 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
name: bundler
requirement: !ruby/object:Gem::Requirement
requirements:
- - - "~>"
+ - - ">="
- !ruby/object:Gem::Version
- version: '1'
+ version: '0'
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - - "~>"
+ - - ">="
- !ruby/object:Gem::Version
- version: '1'
+ version: '0'
- !ruby/object:Gem::Dependency
name: rake
requirement: !ruby/object:Gem::Requirement
@@ -102,6 +102,8 @@
- ext/bootsnap/extconf.rb
extra_rdoc_files: []
files:
+- ".github/CODEOWNERS"
+- ".github/probots.yml"
- ".gitignore"
- ".rubocop.yml"
- ".travis.yml"
@@ -113,8 +115,10 @@
- README.jp.md
- README.md
- Rakefile
+- bin/ci
- bin/console
- bin/setup
+- bin/test-minimal-support
- bin/testunit
- bootsnap.gemspec
- dev.yml
@@ -132,6 +136,7 @@
- lib/bootsnap/load_path_cache/change_observer.rb
- lib/bootsnap/load_path_cache/core_ext/active_support.rb
- lib/bootsnap/load_path_cache/core_ext/kernel_require.rb
+- lib/bootsnap/load_path_cache/core_ext/loaded_features.rb
- lib/bootsnap/load_path_cache/loaded_features_index.rb
- lib/bootsnap/load_path_cache/path.rb
- lib/bootsnap/load_path_cache/path_scanner.rb
@@ -143,7 +148,10 @@
homepage: https://github.com/Shopify/bootsnap
licenses:
- MIT
-metadata: {}
+metadata:
+ bug_tracker_uri: https://github.com/Shopify/bootsnap/issues
+ changelog_uri: https://github.com/Shopify/bootsnap/blob/master/CHANGELOG.md
+ source_code_uri: https://github.com/Shopify/bootsnap
post_install_message:
rdoc_options: []
require_paths:
@@ -160,7 +168,7 @@
version: '0'
requirements: []
rubyforge_project:
-rubygems_version: 2.6.14
+rubygems_version: 2.7.6
signing_key:
specification_version: 4
summary: Boot large ruby/rails apps faster
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shipit.rubygems.yml new/shipit.rubygems.yml
--- old/shipit.rubygems.yml 2018-09-10 20:40:32.000000000 +0200
+++ new/shipit.rubygems.yml 2019-03-26 16:12:36.000000000 +0100
@@ -1,4 +0,0 @@
-dependencies:
- bundler:
- without:
- - development