bootsnap 1.4.6 → 1.4.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.travis.yml +7 -3
- data/CHANGELOG.md +19 -0
- data/Rakefile +5 -1
- data/bin/ci +1 -2
- data/bootsnap.gemspec +1 -1
- data/ext/bootsnap/bootsnap.c +22 -13
- data/lib/bootsnap.rb +1 -0
- data/lib/bootsnap/load_path_cache/cache.rb +6 -6
- data/lib/bootsnap/load_path_cache/change_observer.rb +1 -1
- data/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +1 -1
- data/lib/bootsnap/load_path_cache/loaded_features_index.rb +2 -2
- data/lib/bootsnap/load_path_cache/path.rb +2 -2
- data/lib/bootsnap/load_path_cache/path_scanner.rb +39 -26
- data/lib/bootsnap/load_path_cache/realpath_cache.rb +5 -5
- data/lib/bootsnap/load_path_cache/store.rb +1 -1
- data/lib/bootsnap/version.rb +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3678f8871286d394bbfc31303d0123aae9374370aeda42701336206293447f9a
|
4
|
+
data.tar.gz: 88a8005d7a4fac49b6a1dde52e2d2ec891fd5fa35766cdfb46f52c83cf441b25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1025b1d2a7b60083e6e7bf460cf4aae1ad1c6b2376e024fae199ea0728837b897f417e89b30fcfb3a7fb3260993846566df0537523ee8f703f7bc7d5c1590ace
|
7
|
+
data.tar.gz: 64686090f0dcf1c8835b59690e700b0abd394edf399733cd2ca53d952bdd5f1cc3109d381bac8079f3e64e9c9e12913e132e1fdf07ea3262891914cef4f9c299
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
@@ -6,8 +6,10 @@ os:
|
|
6
6
|
- osx
|
7
7
|
|
8
8
|
rvm:
|
9
|
-
-
|
10
|
-
-
|
9
|
+
- '2.4'
|
10
|
+
- '2.5'
|
11
|
+
- '2.6'
|
12
|
+
- '2.7'
|
11
13
|
- ruby-head
|
12
14
|
|
13
15
|
matrix:
|
@@ -17,5 +19,7 @@ matrix:
|
|
17
19
|
- rvm: jruby
|
18
20
|
os: linux
|
19
21
|
env: MINIMAL_SUPPORT=1
|
20
|
-
|
22
|
+
- rvm: truffleruby
|
23
|
+
os: linux
|
24
|
+
env: MINIMAL_SUPPORT=1
|
21
25
|
script: bin/ci
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
# 1.4.7
|
2
|
+
|
3
|
+
* Various performance enhancements
|
4
|
+
* Fix race condition in heavy concurrent load scenarios that would cause bootsnap to raise
|
5
|
+
|
6
|
+
# 1.4.6
|
7
|
+
|
8
|
+
* Fix bug that was erroneously considering that files containing `.` in the names were being
|
9
|
+
required if a different file with the same name was already being required
|
10
|
+
|
11
|
+
Example:
|
12
|
+
|
13
|
+
require 'foo'
|
14
|
+
require 'foo.en'
|
15
|
+
|
16
|
+
Before bootsnap was considering `foo.en` to be the same file as `foo`
|
17
|
+
|
18
|
+
* Use glibc as part of the ruby_platform cache key
|
19
|
+
|
1
20
|
# 1.4.5
|
2
21
|
|
3
22
|
* MRI 2.7 support
|
data/Rakefile
CHANGED
data/bin/ci
CHANGED
data/bootsnap.gemspec
CHANGED
@@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
|
|
37
37
|
end
|
38
38
|
|
39
39
|
spec.add_development_dependency("bundler")
|
40
|
-
spec.add_development_dependency('rake'
|
40
|
+
spec.add_development_dependency('rake')
|
41
41
|
spec.add_development_dependency('rake-compiler', '~> 0')
|
42
42
|
spec.add_development_dependency("minitest", "~> 5.0")
|
43
43
|
spec.add_development_dependency("mocha", "~> 1.2")
|
data/ext/bootsnap/bootsnap.c
CHANGED
@@ -32,6 +32,8 @@
|
|
32
32
|
|
33
33
|
#define KEY_SIZE 64
|
34
34
|
|
35
|
+
#define MAX_CREATE_TEMPFILE_ATTEMPT 3
|
36
|
+
|
35
37
|
/*
|
36
38
|
* An instance of this key is written as the first 64 bytes of each cache file.
|
37
39
|
* The mtime and size members track whether the file contents have changed, and
|
@@ -499,25 +501,32 @@ atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data, cons
|
|
499
501
|
{
|
500
502
|
char template[MAX_CACHEPATH_SIZE + 20];
|
501
503
|
char * tmp_path;
|
502
|
-
int fd, ret;
|
504
|
+
int fd, ret, attempt;
|
503
505
|
ssize_t nwrite;
|
504
506
|
|
505
|
-
|
506
|
-
|
507
|
+
for (attempt = 0; attempt < MAX_CREATE_TEMPFILE_ATTEMPT; ++attempt) {
|
508
|
+
tmp_path = strncpy(template, path, MAX_CACHEPATH_SIZE);
|
509
|
+
strcat(tmp_path, ".tmp.XXXXXX");
|
507
510
|
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
511
|
+
// mkstemp modifies the template to be the actual created path
|
512
|
+
fd = mkstemp(tmp_path);
|
513
|
+
if (fd > 0) break;
|
514
|
+
|
515
|
+
if (attempt == 0 && mkpath(tmp_path, 0775) < 0) {
|
512
516
|
*errno_provenance = "bs_fetch:atomic_write_cache_file:mkpath";
|
513
517
|
return -1;
|
514
518
|
}
|
515
|
-
fd = open(tmp_path, O_WRONLY | O_CREAT, 0664);
|
516
|
-
if (fd < 0) {
|
517
|
-
*errno_provenance = "bs_fetch:atomic_write_cache_file:open";
|
518
|
-
return -1;
|
519
|
-
}
|
520
519
|
}
|
520
|
+
if (fd < 0) {
|
521
|
+
*errno_provenance = "bs_fetch:atomic_write_cache_file:mkstemp";
|
522
|
+
return -1;
|
523
|
+
}
|
524
|
+
|
525
|
+
if (chmod(tmp_path, 0644) < 0) {
|
526
|
+
*errno_provenance = "bs_fetch:atomic_write_cache_file:chmod";
|
527
|
+
return -1;
|
528
|
+
}
|
529
|
+
|
521
530
|
#ifdef _WIN32
|
522
531
|
setmode(fd, O_BINARY);
|
523
532
|
#endif
|
@@ -800,7 +809,7 @@ try_input_to_storage(VALUE arg)
|
|
800
809
|
}
|
801
810
|
|
802
811
|
static VALUE
|
803
|
-
rescue_input_to_storage(VALUE arg)
|
812
|
+
rescue_input_to_storage(VALUE arg, VALUE e)
|
804
813
|
{
|
805
814
|
return uncompilable;
|
806
815
|
}
|
data/lib/bootsnap.rb
CHANGED
@@ -46,7 +46,7 @@ module Bootsnap
|
|
46
46
|
# loadpath.
|
47
47
|
def find(feature)
|
48
48
|
reinitialize if (@has_relative_paths && dir_changed?) || stale?
|
49
|
-
feature = feature.to_s
|
49
|
+
feature = feature.to_s.freeze
|
50
50
|
return feature if absolute_path?(feature)
|
51
51
|
return expand_path(feature) if feature.start_with?('./')
|
52
52
|
@mutex.synchronize do
|
@@ -178,25 +178,25 @@ module Bootsnap
|
|
178
178
|
|
179
179
|
if DLEXT2
|
180
180
|
def search_index(f)
|
181
|
-
try_index(f
|
181
|
+
try_index("#{f}#{DOT_RB}") || try_index("#{f}#{DLEXT}") || try_index("#{f}#{DLEXT2}") || try_index(f)
|
182
182
|
end
|
183
183
|
|
184
184
|
def maybe_append_extension(f)
|
185
|
-
try_ext(f
|
185
|
+
try_ext("#{f}#{DOT_RB}") || try_ext("#{f}#{DLEXT}") || try_ext("#{f}#{DLEXT2}") || f
|
186
186
|
end
|
187
187
|
else
|
188
188
|
def search_index(f)
|
189
|
-
try_index(f
|
189
|
+
try_index("#{f}#{DOT_RB}") || try_index("#{f}#{DLEXT}") || try_index(f)
|
190
190
|
end
|
191
191
|
|
192
192
|
def maybe_append_extension(f)
|
193
|
-
try_ext(f
|
193
|
+
try_ext("#{f}#{DOT_RB}") || try_ext("#{f}#{DLEXT}") || f
|
194
194
|
end
|
195
195
|
end
|
196
196
|
|
197
197
|
def try_index(f)
|
198
198
|
if (p = @index[f])
|
199
|
-
p
|
199
|
+
"#{p}/#{f}"
|
200
200
|
end
|
201
201
|
end
|
202
202
|
|
@@ -26,7 +26,7 @@ module Bootsnap
|
|
26
26
|
super
|
27
27
|
end
|
28
28
|
|
29
|
-
# uniq! keeps the first
|
29
|
+
# uniq! keeps the first occurrence of each path, otherwise preserving
|
30
30
|
# order, preserving the effective load path
|
31
31
|
def uniq!(*args)
|
32
32
|
ret = super
|
@@ -56,7 +56,7 @@ module Kernel
|
|
56
56
|
end
|
57
57
|
|
58
58
|
# load also allows relative paths from pwd even when not in $:
|
59
|
-
if File.exist?(relative = File.expand_path(path))
|
59
|
+
if File.exist?(relative = File.expand_path(path).freeze)
|
60
60
|
return load_without_bootsnap(relative, wrap)
|
61
61
|
end
|
62
62
|
|
@@ -99,7 +99,7 @@ module Bootsnap
|
|
99
99
|
altname = if extension_elidable?(short)
|
100
100
|
# Strip the extension off, e.g. 'bundler.rb' -> 'bundler'.
|
101
101
|
strip_extension_if_elidable(short)
|
102
|
-
elsif long && (ext = File.extname(long))
|
102
|
+
elsif long && (ext = File.extname(long.freeze))
|
103
103
|
# We already know the extension of the actual file this
|
104
104
|
# resolves to, so put that back on.
|
105
105
|
short + ext
|
@@ -129,7 +129,7 @@ module Bootsnap
|
|
129
129
|
# to name files in a way that assumes otherwise.
|
130
130
|
# (E.g. It's unlikely that someone will know that their code
|
131
131
|
# will _never_ run on MacOS, and therefore think they can get away
|
132
|
-
# with
|
132
|
+
# with calling a Ruby file 'x.dylib.rb' and then requiring it as 'x.dylib'.)
|
133
133
|
#
|
134
134
|
# See <https://ruby-doc.org/core-2.6.4/Kernel.html#method-i-require>.
|
135
135
|
def extension_elidable?(f)
|
@@ -21,7 +21,7 @@ module Bootsnap
|
|
21
21
|
attr_reader(:path)
|
22
22
|
|
23
23
|
def initialize(path)
|
24
|
-
@path = path.to_s
|
24
|
+
@path = path.to_s.freeze
|
25
25
|
end
|
26
26
|
|
27
27
|
# True if the path exists, but represents a non-directory object
|
@@ -60,7 +60,7 @@ module Bootsnap
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def expanded_path
|
63
|
-
File.expand_path(path)
|
63
|
+
File.expand_path(path).freeze
|
64
64
|
end
|
65
65
|
|
66
66
|
private
|
@@ -5,7 +5,6 @@ require_relative('../explicit_require')
|
|
5
5
|
module Bootsnap
|
6
6
|
module LoadPathCache
|
7
7
|
module PathScanner
|
8
|
-
ALL_FILES = "/{,**/*/**/}*"
|
9
8
|
REQUIRABLE_EXTENSIONS = [DOT_RB] + DL_EXTENSIONS
|
10
9
|
NORMALIZE_NATIVE_EXTENSIONS = !DL_EXTENSIONS.include?(LoadPathCache::DOT_SO)
|
11
10
|
ALTERNATIVE_NATIVE_EXTENSIONS_PATTERN = /\.(o|bundle|dylib)\z/
|
@@ -16,34 +15,48 @@ module Bootsnap
|
|
16
15
|
''
|
17
16
|
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
requirables << relative_path
|
18
|
+
class << self
|
19
|
+
def call(path)
|
20
|
+
path = File.expand_path(path.to_s).freeze
|
21
|
+
return [[], []] unless File.directory?(path)
|
22
|
+
|
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
|
+
walk(path, nil) do |relative_path, absolute_path, is_directory|
|
35
|
+
if is_directory
|
36
|
+
dirs << relative_path
|
37
|
+
!contains_bundle_path || !absolute_path.start_with?(BUNDLE_PATH)
|
38
|
+
elsif relative_path.end_with?(*REQUIRABLE_EXTENSIONS)
|
39
|
+
requirables << relative_path
|
40
|
+
end
|
43
41
|
end
|
42
|
+
[requirables, dirs]
|
44
43
|
end
|
45
44
|
|
46
|
-
|
45
|
+
def walk(absolute_dir_path, relative_dir_path, &block)
|
46
|
+
Dir.foreach(absolute_dir_path) do |name|
|
47
|
+
next if name.start_with?('.')
|
48
|
+
relative_path = relative_dir_path ? "#{relative_dir_path}/#{name}" : name.freeze
|
49
|
+
|
50
|
+
absolute_path = "#{absolute_dir_path}/#{name}"
|
51
|
+
if File.directory?(absolute_path)
|
52
|
+
if yield relative_path, absolute_path, true
|
53
|
+
walk(absolute_path, relative_path, &block)
|
54
|
+
end
|
55
|
+
else
|
56
|
+
yield relative_path, absolute_path, false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
47
60
|
end
|
48
61
|
end
|
49
62
|
end
|
@@ -15,15 +15,15 @@ module Bootsnap
|
|
15
15
|
|
16
16
|
def realpath(caller_location, path)
|
17
17
|
base = File.dirname(caller_location)
|
18
|
-
|
19
|
-
|
20
|
-
File.join(dir, File.basename(file))
|
18
|
+
abspath = File.expand_path(path, base).freeze
|
19
|
+
find_file(abspath)
|
21
20
|
end
|
22
21
|
|
23
22
|
def find_file(name)
|
24
|
-
|
23
|
+
return File.realpath(name).freeze if File.exist?(name)
|
24
|
+
CACHED_EXTENSIONS.each do |ext|
|
25
25
|
filename = "#{name}#{ext}"
|
26
|
-
return File.realpath(filename) if File.exist?(filename)
|
26
|
+
return File.realpath(filename).freeze if File.exist?(filename)
|
27
27
|
end
|
28
28
|
name
|
29
29
|
end
|
@@ -64,7 +64,7 @@ module Bootsnap
|
|
64
64
|
def load_data
|
65
65
|
@data = begin
|
66
66
|
MessagePack.load(File.binread(@store_path))
|
67
|
-
# handle malformed data due to upgrade
|
67
|
+
# handle malformed data due to upgrade incompatibility
|
68
68
|
rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
|
69
69
|
{}
|
70
70
|
rescue ArgumentError => e
|
data/lib/bootsnap/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bootsnap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Burke Libbey
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake-compiler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -167,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
167
|
- !ruby/object:Gem::Version
|
168
168
|
version: '0'
|
169
169
|
requirements: []
|
170
|
-
rubygems_version: 3.0.
|
170
|
+
rubygems_version: 3.0.2
|
171
171
|
signing_key:
|
172
172
|
specification_version: 4
|
173
173
|
summary: Boot large ruby/rails apps faster
|