bootsnap 1.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/CODEOWNERS +2 -0
- data/.github/probots.yml +2 -0
- data/.gitignore +17 -0
- data/.rubocop.yml +20 -0
- data/.travis.yml +21 -0
- data/CHANGELOG.md +122 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +21 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +21 -0
- data/README.jp.md +231 -0
- data/README.md +304 -0
- data/Rakefile +13 -0
- data/bin/ci +10 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/bin/test-minimal-support +7 -0
- data/bin/testunit +8 -0
- data/bootsnap.gemspec +46 -0
- data/dev.yml +10 -0
- data/ext/bootsnap/bootsnap.c +829 -0
- data/ext/bootsnap/bootsnap.h +6 -0
- data/ext/bootsnap/extconf.rb +19 -0
- data/lib/bootsnap.rb +48 -0
- data/lib/bootsnap/bundler.rb +15 -0
- data/lib/bootsnap/compile_cache.rb +43 -0
- data/lib/bootsnap/compile_cache/iseq.rb +73 -0
- data/lib/bootsnap/compile_cache/yaml.rb +63 -0
- data/lib/bootsnap/explicit_require.rb +50 -0
- data/lib/bootsnap/load_path_cache.rb +78 -0
- data/lib/bootsnap/load_path_cache/cache.rb +208 -0
- data/lib/bootsnap/load_path_cache/change_observer.rb +63 -0
- data/lib/bootsnap/load_path_cache/core_ext/active_support.rb +107 -0
- data/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +93 -0
- data/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb +18 -0
- data/lib/bootsnap/load_path_cache/loaded_features_index.rb +148 -0
- data/lib/bootsnap/load_path_cache/path.rb +114 -0
- data/lib/bootsnap/load_path_cache/path_scanner.rb +50 -0
- data/lib/bootsnap/load_path_cache/realpath_cache.rb +32 -0
- data/lib/bootsnap/load_path_cache/store.rb +90 -0
- data/lib/bootsnap/setup.rb +39 -0
- data/lib/bootsnap/version.rb +4 -0
- data/shipit.rubygems.yml +0 -0
- metadata +174 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative('../explicit_require')
|
4
|
+
|
5
|
+
module Bootsnap
|
6
|
+
module LoadPathCache
|
7
|
+
module PathScanner
|
8
|
+
ALL_FILES = "/{,**/*/**/}*"
|
9
|
+
REQUIRABLE_EXTENSIONS = [DOT_RB] + DL_EXTENSIONS
|
10
|
+
NORMALIZE_NATIVE_EXTENSIONS = !DL_EXTENSIONS.include?(LoadPathCache::DOT_SO)
|
11
|
+
ALTERNATIVE_NATIVE_EXTENSIONS_PATTERN = /\.(o|bundle|dylib)\z/
|
12
|
+
|
13
|
+
BUNDLE_PATH = if Bootsnap.bundler?
|
14
|
+
(Bundler.bundle_path.cleanpath.to_s << LoadPathCache::SLASH).freeze
|
15
|
+
else
|
16
|
+
''
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.call(path)
|
20
|
+
path = path.to_s
|
21
|
+
|
22
|
+
relative_slice = (path.size + 1)..-1
|
23
|
+
# If the bundle path is a descendent of this path, we do additional
|
24
|
+
# checks to prevent recursing into the bundle path as we recurse
|
25
|
+
# through this path. We don't want to scan the bundle path because
|
26
|
+
# anything useful in it will be present on other load path items.
|
27
|
+
#
|
28
|
+
# This can happen if, for example, the user adds '.' to the load path,
|
29
|
+
# and the bundle path is '.bundle'.
|
30
|
+
contains_bundle_path = BUNDLE_PATH.start_with?(path)
|
31
|
+
|
32
|
+
dirs = []
|
33
|
+
requirables = []
|
34
|
+
|
35
|
+
Dir.glob(path + ALL_FILES).each do |absolute_path|
|
36
|
+
next if contains_bundle_path && absolute_path.start_with?(BUNDLE_PATH)
|
37
|
+
relative_path = absolute_path.slice(relative_slice)
|
38
|
+
|
39
|
+
if File.directory?(absolute_path)
|
40
|
+
dirs << relative_path
|
41
|
+
elsif REQUIRABLE_EXTENSIONS.include?(File.extname(relative_path))
|
42
|
+
requirables << relative_path
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
[requirables, dirs]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bootsnap
|
4
|
+
module LoadPathCache
|
5
|
+
class RealpathCache
|
6
|
+
def initialize
|
7
|
+
@cache = Hash.new { |h, k| h[k] = realpath(*k) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(*key)
|
11
|
+
@cache[key]
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def realpath(caller_location, path)
|
17
|
+
base = File.dirname(caller_location)
|
18
|
+
file = find_file(File.expand_path(path, base))
|
19
|
+
dir = File.dirname(file)
|
20
|
+
File.join(dir, File.basename(file))
|
21
|
+
end
|
22
|
+
|
23
|
+
def find_file(name)
|
24
|
+
['', *CACHED_EXTENSIONS].each do |ext|
|
25
|
+
filename = "#{name}#{ext}"
|
26
|
+
return File.realpath(filename) if File.exist?(filename)
|
27
|
+
end
|
28
|
+
name
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative('../explicit_require')
|
3
|
+
|
4
|
+
Bootsnap::ExplicitRequire.with_gems('msgpack') { require('msgpack') }
|
5
|
+
Bootsnap::ExplicitRequire.from_rubylibdir('fileutils')
|
6
|
+
|
7
|
+
module Bootsnap
|
8
|
+
module LoadPathCache
|
9
|
+
class Store
|
10
|
+
NestedTransactionError = Class.new(StandardError)
|
11
|
+
SetOutsideTransactionNotAllowed = Class.new(StandardError)
|
12
|
+
|
13
|
+
def initialize(store_path)
|
14
|
+
@store_path = store_path
|
15
|
+
# TODO: Remove conditional once Ruby 2.2 support is dropped.
|
16
|
+
@txn_mutex = defined?(::Mutex) ? ::Mutex.new : ::Thread::Mutex.new
|
17
|
+
@dirty = false
|
18
|
+
load_data
|
19
|
+
end
|
20
|
+
|
21
|
+
def get(key)
|
22
|
+
@data[key]
|
23
|
+
end
|
24
|
+
|
25
|
+
def fetch(key)
|
26
|
+
raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
|
27
|
+
v = get(key)
|
28
|
+
unless v
|
29
|
+
@dirty = true
|
30
|
+
v = yield
|
31
|
+
@data[key] = v
|
32
|
+
end
|
33
|
+
v
|
34
|
+
end
|
35
|
+
|
36
|
+
def set(key, value)
|
37
|
+
raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
|
38
|
+
if value != @data[key]
|
39
|
+
@dirty = true
|
40
|
+
@data[key] = value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def transaction
|
45
|
+
raise(NestedTransactionError) if @txn_mutex.owned?
|
46
|
+
@txn_mutex.synchronize do
|
47
|
+
begin
|
48
|
+
yield
|
49
|
+
ensure
|
50
|
+
commit_transaction
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def commit_transaction
|
58
|
+
if @dirty
|
59
|
+
dump_data
|
60
|
+
@dirty = false
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def load_data
|
65
|
+
@data = begin
|
66
|
+
MessagePack.load(File.binread(@store_path))
|
67
|
+
# handle malformed data due to upgrade incompatability
|
68
|
+
rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
|
69
|
+
{}
|
70
|
+
rescue ArgumentError => e
|
71
|
+
e.message =~ /negative array size/ ? {} : raise
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def dump_data
|
76
|
+
# Change contents atomically so other processes can't get invalid
|
77
|
+
# caches if they read at an inopportune time.
|
78
|
+
tmp = "#{@store_path}.#{Process.pid}.#{(rand * 100000).to_i}.tmp"
|
79
|
+
FileUtils.mkpath(File.dirname(tmp))
|
80
|
+
exclusive_write = File::Constants::CREAT | File::Constants::EXCL | File::Constants::WRONLY
|
81
|
+
# `encoding:` looks redundant wrt `binwrite`, but necessary on windows
|
82
|
+
# because binary is part of mode.
|
83
|
+
File.binwrite(tmp, MessagePack.dump(@data), mode: exclusive_write, encoding: Encoding::BINARY)
|
84
|
+
FileUtils.mv(tmp, @store_path)
|
85
|
+
rescue Errno::EEXIST
|
86
|
+
retry
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative('../bootsnap')
|
3
|
+
|
4
|
+
env = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || ENV['ENV']
|
5
|
+
development_mode = ['', nil, 'development'].include?(env)
|
6
|
+
|
7
|
+
cache_dir = ENV['BOOTSNAP_CACHE_DIR']
|
8
|
+
unless cache_dir
|
9
|
+
config_dir_frame = caller.detect do |line|
|
10
|
+
line.include?('/config/')
|
11
|
+
end
|
12
|
+
|
13
|
+
unless config_dir_frame
|
14
|
+
$stderr.puts("[bootsnap/setup] couldn't infer cache directory! Either:")
|
15
|
+
$stderr.puts("[bootsnap/setup] 1. require bootsnap/setup from your application's config directory; or")
|
16
|
+
$stderr.puts("[bootsnap/setup] 2. Define the environment variable BOOTSNAP_CACHE_DIR")
|
17
|
+
|
18
|
+
raise("couldn't infer bootsnap cache directory")
|
19
|
+
end
|
20
|
+
|
21
|
+
path = config_dir_frame.split(/:\d+:/).first
|
22
|
+
path = File.dirname(path) until File.basename(path) == 'config'
|
23
|
+
app_root = File.dirname(path)
|
24
|
+
|
25
|
+
cache_dir = File.join(app_root, 'tmp', 'cache')
|
26
|
+
end
|
27
|
+
|
28
|
+
ruby_version = Gem::Version.new(RUBY_VERSION)
|
29
|
+
iseq_cache_enabled = ruby_version < Gem::Version.new('2.5.0') || ruby_version >= Gem::Version.new('2.6.0')
|
30
|
+
|
31
|
+
Bootsnap.setup(
|
32
|
+
cache_dir: cache_dir,
|
33
|
+
development_mode: development_mode,
|
34
|
+
load_path_cache: true,
|
35
|
+
autoload_paths_cache: true, # assume rails. open to PRs to impl. detection
|
36
|
+
disable_trace: false,
|
37
|
+
compile_cache_iseq: iseq_cache_enabled,
|
38
|
+
compile_cache_yaml: true,
|
39
|
+
)
|
data/shipit.rubygems.yml
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bootsnap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.4.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Burke Libbey
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-02-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake-compiler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mocha
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.2'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.2'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: msgpack
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.0'
|
97
|
+
description: Boot large ruby/rails apps faster
|
98
|
+
email:
|
99
|
+
- burke.libbey@shopify.com
|
100
|
+
executables: []
|
101
|
+
extensions:
|
102
|
+
- ext/bootsnap/extconf.rb
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- ".github/CODEOWNERS"
|
106
|
+
- ".github/probots.yml"
|
107
|
+
- ".gitignore"
|
108
|
+
- ".rubocop.yml"
|
109
|
+
- ".travis.yml"
|
110
|
+
- CHANGELOG.md
|
111
|
+
- CODE_OF_CONDUCT.md
|
112
|
+
- CONTRIBUTING.md
|
113
|
+
- Gemfile
|
114
|
+
- LICENSE.txt
|
115
|
+
- README.jp.md
|
116
|
+
- README.md
|
117
|
+
- Rakefile
|
118
|
+
- bin/ci
|
119
|
+
- bin/console
|
120
|
+
- bin/setup
|
121
|
+
- bin/test-minimal-support
|
122
|
+
- bin/testunit
|
123
|
+
- bootsnap.gemspec
|
124
|
+
- dev.yml
|
125
|
+
- ext/bootsnap/bootsnap.c
|
126
|
+
- ext/bootsnap/bootsnap.h
|
127
|
+
- ext/bootsnap/extconf.rb
|
128
|
+
- lib/bootsnap.rb
|
129
|
+
- lib/bootsnap/bundler.rb
|
130
|
+
- lib/bootsnap/compile_cache.rb
|
131
|
+
- lib/bootsnap/compile_cache/iseq.rb
|
132
|
+
- lib/bootsnap/compile_cache/yaml.rb
|
133
|
+
- lib/bootsnap/explicit_require.rb
|
134
|
+
- lib/bootsnap/load_path_cache.rb
|
135
|
+
- lib/bootsnap/load_path_cache/cache.rb
|
136
|
+
- lib/bootsnap/load_path_cache/change_observer.rb
|
137
|
+
- lib/bootsnap/load_path_cache/core_ext/active_support.rb
|
138
|
+
- lib/bootsnap/load_path_cache/core_ext/kernel_require.rb
|
139
|
+
- lib/bootsnap/load_path_cache/core_ext/loaded_features.rb
|
140
|
+
- lib/bootsnap/load_path_cache/loaded_features_index.rb
|
141
|
+
- lib/bootsnap/load_path_cache/path.rb
|
142
|
+
- lib/bootsnap/load_path_cache/path_scanner.rb
|
143
|
+
- lib/bootsnap/load_path_cache/realpath_cache.rb
|
144
|
+
- lib/bootsnap/load_path_cache/store.rb
|
145
|
+
- lib/bootsnap/setup.rb
|
146
|
+
- lib/bootsnap/version.rb
|
147
|
+
- shipit.rubygems.yml
|
148
|
+
homepage: https://github.com/Shopify/bootsnap
|
149
|
+
licenses:
|
150
|
+
- MIT
|
151
|
+
metadata:
|
152
|
+
bug_tracker_uri: https://github.com/Shopify/bootsnap/issues
|
153
|
+
changelog_uri: https://github.com/Shopify/bootsnap/blob/master/CHANGELOG.md
|
154
|
+
source_code_uri: https://github.com/Shopify/bootsnap
|
155
|
+
post_install_message:
|
156
|
+
rdoc_options: []
|
157
|
+
require_paths:
|
158
|
+
- lib
|
159
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: 2.3.0
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
requirements: []
|
170
|
+
rubygems_version: 3.0.6
|
171
|
+
signing_key:
|
172
|
+
specification_version: 4
|
173
|
+
summary: Boot large ruby/rails apps faster
|
174
|
+
test_files: []
|