bootsnap 1.1.8-java → 1.6.0

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.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +103 -0
  3. data/README.md +47 -6
  4. data/exe/bootsnap +5 -0
  5. data/ext/bootsnap/bootsnap.c +217 -88
  6. data/ext/bootsnap/extconf.rb +3 -1
  7. data/lib/bootsnap.rb +17 -8
  8. data/lib/bootsnap/bundler.rb +6 -3
  9. data/lib/bootsnap/cli.rb +246 -0
  10. data/lib/bootsnap/cli/worker_pool.rb +131 -0
  11. data/lib/bootsnap/compile_cache.rb +32 -4
  12. data/lib/bootsnap/compile_cache/iseq.rb +32 -15
  13. data/lib/bootsnap/compile_cache/yaml.rb +94 -40
  14. data/lib/bootsnap/explicit_require.rb +2 -1
  15. data/lib/bootsnap/load_path_cache.rb +35 -9
  16. data/lib/bootsnap/load_path_cache/cache.rb +48 -29
  17. data/lib/bootsnap/load_path_cache/change_observer.rb +36 -29
  18. data/lib/bootsnap/load_path_cache/core_ext/active_support.rb +39 -7
  19. data/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +70 -53
  20. data/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb +18 -0
  21. data/lib/bootsnap/load_path_cache/loaded_features_index.rb +148 -0
  22. data/lib/bootsnap/load_path_cache/path.rb +8 -7
  23. data/lib/bootsnap/load_path_cache/path_scanner.rb +50 -39
  24. data/lib/bootsnap/load_path_cache/realpath_cache.rb +32 -0
  25. data/lib/bootsnap/load_path_cache/store.rb +20 -14
  26. data/lib/bootsnap/setup.rb +11 -13
  27. data/lib/bootsnap/version.rb +2 -1
  28. metadata +44 -45
  29. data/.gitignore +0 -17
  30. data/.rubocop.yml +0 -20
  31. data/.travis.yml +0 -4
  32. data/CODE_OF_CONDUCT.md +0 -74
  33. data/CONTRIBUTING.md +0 -21
  34. data/Gemfile +0 -8
  35. data/Rakefile +0 -11
  36. data/bin/console +0 -14
  37. data/bin/setup +0 -8
  38. data/bin/testunit +0 -8
  39. data/bootsnap.gemspec +0 -39
  40. data/dev.yml +0 -10
@@ -1,4 +1,5 @@
1
- require_relative 'path_scanner'
1
+ # frozen_string_literal: true
2
+ require_relative('path_scanner')
2
3
 
3
4
  module Bootsnap
4
5
  module LoadPathCache
@@ -17,16 +18,16 @@ module Bootsnap
17
18
  stability == VOLATILE
18
19
  end
19
20
 
20
- attr_reader :path
21
+ attr_reader(:path)
21
22
 
22
23
  def initialize(path)
23
- @path = path.to_s
24
+ @path = path.to_s.freeze
24
25
  end
25
26
 
26
27
  # True if the path exists, but represents a non-directory object
27
28
  def non_directory?
28
29
  !File.stat(path).directory?
29
- rescue Errno::ENOENT
30
+ rescue Errno::ENOENT, Errno::ENOTDIR
30
31
  false
31
32
  end
32
33
 
@@ -59,7 +60,7 @@ module Bootsnap
59
60
  end
60
61
 
61
62
  def expanded_path
62
- File.expand_path(path)
63
+ File.expand_path(path).freeze
63
64
  end
64
65
 
65
66
  private
@@ -76,8 +77,8 @@ module Bootsnap
76
77
  ["", *dirs].each do |dir|
77
78
  curr = begin
78
79
  File.mtime("#{path}/#{dir}").to_i
79
- rescue Errno::ENOENT
80
- -1
80
+ rescue Errno::ENOENT, Errno::ENOTDIR
81
+ -1
81
82
  end
82
83
  max = curr if curr > max
83
84
  end
@@ -1,51 +1,62 @@
1
- require_relative '../explicit_require'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative('../explicit_require')
2
4
 
3
5
  module Bootsnap
4
6
  module LoadPathCache
5
7
  module PathScanner
6
- # Glob pattern to find requirable files and subdirectories in given path.
7
- # It expands to:
8
- #
9
- # * `/*{.rb,.so,/}` - It matches requirable files, directories and
10
- # symlinks to directories at given path.
11
- # * `/*/**/*{.rb,.so,/}` - It matches requirable files and
12
- # subdirectories in any (even symlinked) directory at given path at
13
- # any directory tree depth.
14
- #
15
- REQUIRABLES_AND_DIRS = "/{,*/**/}*{#{DOT_RB},#{DL_EXTENSIONS.join(',')},/}"
8
+ REQUIRABLE_EXTENSIONS = [DOT_RB] + DL_EXTENSIONS
16
9
  NORMALIZE_NATIVE_EXTENSIONS = !DL_EXTENSIONS.include?(LoadPathCache::DOT_SO)
17
10
  ALTERNATIVE_NATIVE_EXTENSIONS_PATTERN = /\.(o|bundle|dylib)\z/
18
- BUNDLE_PATH = Bootsnap.bundler? ?
19
- (Bundler.bundle_path.cleanpath.to_s << LoadPathCache::SLASH).freeze : ''.freeze
20
-
21
- def self.call(path)
22
- path = path.to_s
23
-
24
- relative_slice = (path.size + 1)..-1
25
- # If the bundle path is a descendent of this path, we do additional
26
- # checks to prevent recursing into the bundle path as we recurse
27
- # through this path. We don't want to scan the bundle path because
28
- # anything useful in it will be present on other load path items.
29
- #
30
- # This can happen if, for example, the user adds '.' to the load path,
31
- # and the bundle path is '.bundle'.
32
- contains_bundle_path = BUNDLE_PATH.start_with?(path)
33
-
34
- dirs = []
35
- requirables = []
36
-
37
- Dir.glob(path + REQUIRABLES_AND_DIRS).each do |absolute_path|
38
- next if contains_bundle_path && absolute_path.start_with?(BUNDLE_PATH)
39
- relative_path = absolute_path.slice!(relative_slice)
40
-
41
- if relative_path.end_with?('/')
42
- dirs << relative_path[0..-2]
43
- else
44
- requirables << relative_path
11
+
12
+ BUNDLE_PATH = if Bootsnap.bundler?
13
+ (Bundler.bundle_path.cleanpath.to_s << LoadPathCache::SLASH).freeze
14
+ else
15
+ ''
16
+ end
17
+
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
45
41
  end
42
+ [requirables, dirs]
46
43
  end
47
44
 
48
- [requirables, dirs]
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
49
60
  end
50
61
  end
51
62
  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
+ abspath = File.expand_path(path, base).freeze
19
+ find_file(abspath)
20
+ end
21
+
22
+ def find_file(name)
23
+ return File.realpath(name).freeze if File.exist?(name)
24
+ CACHED_EXTENSIONS.each do |ext|
25
+ filename = "#{name}#{ext}"
26
+ return File.realpath(filename).freeze if File.exist?(filename)
27
+ end
28
+ name
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,6 +1,7 @@
1
- require_relative '../explicit_require'
1
+ # frozen_string_literal: true
2
+ require_relative('../explicit_require')
2
3
 
3
- Bootsnap::ExplicitRequire.with_gems('msgpack') { require 'msgpack' }
4
+ Bootsnap::ExplicitRequire.with_gems('msgpack') { require('msgpack') }
4
5
  Bootsnap::ExplicitRequire.from_rubylibdir('fileutils')
5
6
 
6
7
  module Bootsnap
@@ -11,7 +12,8 @@ module Bootsnap
11
12
 
12
13
  def initialize(store_path)
13
14
  @store_path = store_path
14
- @in_txn = false
15
+ # TODO: Remove conditional once Ruby 2.2 support is dropped.
16
+ @txn_mutex = defined?(::Mutex) ? ::Mutex.new : ::Thread::Mutex.new
15
17
  @dirty = false
16
18
  load_data
17
19
  end
@@ -21,7 +23,7 @@ module Bootsnap
21
23
  end
22
24
 
23
25
  def fetch(key)
24
- raise SetOutsideTransactionNotAllowed unless @in_txn
26
+ raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
25
27
  v = get(key)
26
28
  unless v
27
29
  @dirty = true
@@ -32,7 +34,7 @@ module Bootsnap
32
34
  end
33
35
 
34
36
  def set(key, value)
35
- raise SetOutsideTransactionNotAllowed unless @in_txn
37
+ raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
36
38
  if value != @data[key]
37
39
  @dirty = true
38
40
  @data[key] = value
@@ -40,12 +42,14 @@ module Bootsnap
40
42
  end
41
43
 
42
44
  def transaction
43
- raise NestedTransactionError if @in_txn
44
- @in_txn = true
45
- yield
46
- ensure
47
- commit_transaction
48
- @in_txn = false
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
49
53
  end
50
54
 
51
55
  private
@@ -60,9 +64,11 @@ module Bootsnap
60
64
  def load_data
61
65
  @data = begin
62
66
  MessagePack.load(File.binread(@store_path))
63
- # handle malformed data due to upgrade incompatability
64
- rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
65
- {}
67
+ # handle malformed data due to upgrade incompatibility
68
+ rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
69
+ {}
70
+ rescue ArgumentError => e
71
+ e.message =~ /negative array size/ ? {} : raise
66
72
  end
67
73
  end
68
74
 
@@ -1,14 +1,9 @@
1
- require_relative '../bootsnap'
1
+ # frozen_string_literal: true
2
+ require_relative('../bootsnap')
2
3
 
3
4
  env = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || ENV['ENV']
4
5
  development_mode = ['', nil, 'development'].include?(env)
5
6
 
6
- # only enable on 'ruby' (MRI), POSIX (darin, 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
7
  cache_dir = ENV['BOOTSNAP_CACHE_DIR']
13
8
  unless cache_dir
14
9
  config_dir_frame = caller.detect do |line|
@@ -16,11 +11,11 @@ unless cache_dir
16
11
  end
17
12
 
18
13
  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"
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")
22
17
 
23
- raise "couldn't infer bootsnap cache directory"
18
+ raise("couldn't infer bootsnap cache directory")
24
19
  end
25
20
 
26
21
  path = config_dir_frame.split(/:\d+:/).first
@@ -30,12 +25,15 @@ unless cache_dir
30
25
  cache_dir = File.join(app_root, 'tmp', 'cache')
31
26
  end
32
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
+
33
31
  Bootsnap.setup(
34
32
  cache_dir: cache_dir,
35
33
  development_mode: development_mode,
36
34
  load_path_cache: true,
37
35
  autoload_paths_cache: true, # assume rails. open to PRs to impl. detection
38
36
  disable_trace: false,
39
- compile_cache_iseq: enable_cc,
40
- compile_cache_yaml: enable_cc
37
+ compile_cache_iseq: iseq_cache_enabled,
38
+ compile_cache_yaml: true,
41
39
  )
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Bootsnap
2
- VERSION = "1.1.8"
3
+ VERSION = "1.6.0"
3
4
  end
metadata CHANGED
@@ -1,94 +1,94 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootsnap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.8
5
- platform: java
4
+ version: 1.6.0
5
+ platform: ruby
6
6
  authors:
7
7
  - Burke Libbey
8
- autorequire:
9
- bindir: bin
8
+ autorequire:
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2018-01-05 00:00:00.000000000 Z
11
+ date: 2021-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
+ name: bundler
14
15
  requirement: !ruby/object:Gem::Requirement
15
16
  requirements:
16
- - - "~>"
17
+ - - ">="
17
18
  - !ruby/object:Gem::Version
18
- version: '1'
19
- name: bundler
20
- prerelease: false
19
+ version: '0'
21
20
  type: :development
21
+ prerelease: false
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
+ name: rake
28
29
  requirement: !ruby/object:Gem::Requirement
29
30
  requirements:
30
- - - "~>"
31
+ - - ">="
31
32
  - !ruby/object:Gem::Version
32
- version: '10.0'
33
- name: rake
34
- prerelease: false
33
+ version: '0'
35
34
  type: :development
35
+ prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
+ name: rake-compiler
42
43
  requirement: !ruby/object:Gem::Requirement
43
44
  requirements:
44
45
  - - "~>"
45
46
  - !ruby/object:Gem::Version
46
47
  version: '0'
47
- name: rake-compiler
48
- prerelease: false
49
48
  type: :development
49
+ prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
+ name: minitest
56
57
  requirement: !ruby/object:Gem::Requirement
57
58
  requirements:
58
59
  - - "~>"
59
60
  - !ruby/object:Gem::Version
60
61
  version: '5.0'
61
- name: minitest
62
- prerelease: false
63
62
  type: :development
63
+ prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '5.0'
69
69
  - !ruby/object:Gem::Dependency
70
+ name: mocha
70
71
  requirement: !ruby/object:Gem::Requirement
71
72
  requirements:
72
73
  - - "~>"
73
74
  - !ruby/object:Gem::Version
74
75
  version: '1.2'
75
- name: mocha
76
- prerelease: false
77
76
  type: :development
77
+ prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '1.2'
83
83
  - !ruby/object:Gem::Dependency
84
+ name: msgpack
84
85
  requirement: !ruby/object:Gem::Requirement
85
86
  requirements:
86
87
  - - "~>"
87
88
  - !ruby/object:Gem::Version
88
89
  version: '1.0'
89
- name: msgpack
90
- prerelease: false
91
90
  type: :runtime
91
+ prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
@@ -97,30 +97,23 @@ dependencies:
97
97
  description: Boot large ruby/rails apps faster
98
98
  email:
99
99
  - burke.libbey@shopify.com
100
- executables: []
101
- extensions: []
100
+ executables:
101
+ - bootsnap
102
+ extensions:
103
+ - ext/bootsnap/extconf.rb
102
104
  extra_rdoc_files: []
103
105
  files:
104
- - ".gitignore"
105
- - ".rubocop.yml"
106
- - ".travis.yml"
107
106
  - CHANGELOG.md
108
- - CODE_OF_CONDUCT.md
109
- - CONTRIBUTING.md
110
- - Gemfile
111
107
  - LICENSE.txt
112
108
  - README.md
113
- - Rakefile
114
- - bin/console
115
- - bin/setup
116
- - bin/testunit
117
- - bootsnap.gemspec
118
- - dev.yml
109
+ - exe/bootsnap
119
110
  - ext/bootsnap/bootsnap.c
120
111
  - ext/bootsnap/bootsnap.h
121
112
  - ext/bootsnap/extconf.rb
122
113
  - lib/bootsnap.rb
123
114
  - lib/bootsnap/bundler.rb
115
+ - lib/bootsnap/cli.rb
116
+ - lib/bootsnap/cli/worker_pool.rb
124
117
  - lib/bootsnap/compile_cache.rb
125
118
  - lib/bootsnap/compile_cache/iseq.rb
126
119
  - lib/bootsnap/compile_cache/yaml.rb
@@ -130,16 +123,23 @@ files:
130
123
  - lib/bootsnap/load_path_cache/change_observer.rb
131
124
  - lib/bootsnap/load_path_cache/core_ext/active_support.rb
132
125
  - lib/bootsnap/load_path_cache/core_ext/kernel_require.rb
126
+ - lib/bootsnap/load_path_cache/core_ext/loaded_features.rb
127
+ - lib/bootsnap/load_path_cache/loaded_features_index.rb
133
128
  - lib/bootsnap/load_path_cache/path.rb
134
129
  - lib/bootsnap/load_path_cache/path_scanner.rb
130
+ - lib/bootsnap/load_path_cache/realpath_cache.rb
135
131
  - lib/bootsnap/load_path_cache/store.rb
136
132
  - lib/bootsnap/setup.rb
137
133
  - lib/bootsnap/version.rb
138
134
  homepage: https://github.com/Shopify/bootsnap
139
135
  licenses:
140
136
  - MIT
141
- metadata: {}
142
- post_install_message:
137
+ metadata:
138
+ bug_tracker_uri: https://github.com/Shopify/bootsnap/issues
139
+ changelog_uri: https://github.com/Shopify/bootsnap/blob/master/CHANGELOG.md
140
+ source_code_uri: https://github.com/Shopify/bootsnap
141
+ allowed_push_host: https://rubygems.org
142
+ post_install_message:
143
143
  rdoc_options: []
144
144
  require_paths:
145
145
  - lib
@@ -147,16 +147,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
147
147
  requirements:
148
148
  - - ">="
149
149
  - !ruby/object:Gem::Version
150
- version: 2.0.0
150
+ version: 2.3.0
151
151
  required_rubygems_version: !ruby/object:Gem::Requirement
152
152
  requirements:
153
153
  - - ">="
154
154
  - !ruby/object:Gem::Version
155
155
  version: '0'
156
156
  requirements: []
157
- rubyforge_project:
158
- rubygems_version: 2.4.8
159
- signing_key:
157
+ rubygems_version: 3.0.3
158
+ signing_key:
160
159
  specification_version: 4
161
160
  summary: Boot large ruby/rails apps faster
162
161
  test_files: []