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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.github/CODEOWNERS +2 -0
  3. data/.github/probots.yml +2 -0
  4. data/.gitignore +17 -0
  5. data/.rubocop.yml +20 -0
  6. data/.travis.yml +21 -0
  7. data/CHANGELOG.md +122 -0
  8. data/CODE_OF_CONDUCT.md +74 -0
  9. data/CONTRIBUTING.md +21 -0
  10. data/Gemfile +9 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.jp.md +231 -0
  13. data/README.md +304 -0
  14. data/Rakefile +13 -0
  15. data/bin/ci +10 -0
  16. data/bin/console +15 -0
  17. data/bin/setup +8 -0
  18. data/bin/test-minimal-support +7 -0
  19. data/bin/testunit +8 -0
  20. data/bootsnap.gemspec +46 -0
  21. data/dev.yml +10 -0
  22. data/ext/bootsnap/bootsnap.c +829 -0
  23. data/ext/bootsnap/bootsnap.h +6 -0
  24. data/ext/bootsnap/extconf.rb +19 -0
  25. data/lib/bootsnap.rb +48 -0
  26. data/lib/bootsnap/bundler.rb +15 -0
  27. data/lib/bootsnap/compile_cache.rb +43 -0
  28. data/lib/bootsnap/compile_cache/iseq.rb +73 -0
  29. data/lib/bootsnap/compile_cache/yaml.rb +63 -0
  30. data/lib/bootsnap/explicit_require.rb +50 -0
  31. data/lib/bootsnap/load_path_cache.rb +78 -0
  32. data/lib/bootsnap/load_path_cache/cache.rb +208 -0
  33. data/lib/bootsnap/load_path_cache/change_observer.rb +63 -0
  34. data/lib/bootsnap/load_path_cache/core_ext/active_support.rb +107 -0
  35. data/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +93 -0
  36. data/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb +18 -0
  37. data/lib/bootsnap/load_path_cache/loaded_features_index.rb +148 -0
  38. data/lib/bootsnap/load_path_cache/path.rb +114 -0
  39. data/lib/bootsnap/load_path_cache/path_scanner.rb +50 -0
  40. data/lib/bootsnap/load_path_cache/realpath_cache.rb +32 -0
  41. data/lib/bootsnap/load_path_cache/store.rb +90 -0
  42. data/lib/bootsnap/setup.rb +39 -0
  43. data/lib/bootsnap/version.rb +4 -0
  44. data/shipit.rubygems.yml +0 -0
  45. 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
+ )
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ module Bootsnap
3
+ VERSION = "1.4.6"
4
+ end
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: []