bootsnap 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rubocop.yml +7 -0
- data/CONTRIBUTING.md +21 -0
- data/Gemfile +4 -0
- data/README.md +49 -0
- data/Rakefile +11 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/testunit +8 -0
- data/bootsnap.gemspec +34 -0
- data/dev.yml +5 -0
- data/ext/bootsnap/bootsnap.c +542 -0
- data/ext/bootsnap/bootsnap.h +10 -0
- data/ext/bootsnap/crc32.c +16 -0
- data/ext/bootsnap/extconf.rb +7 -0
- data/lib/bootsnap.rb +38 -0
- data/lib/bootsnap/compile_cache.rb +16 -0
- data/lib/bootsnap/compile_cache/iseq.rb +74 -0
- data/lib/bootsnap/compile_cache/yaml.rb +54 -0
- data/lib/bootsnap/explicit_require.rb +44 -0
- data/lib/bootsnap/load_path_cache.rb +52 -0
- data/lib/bootsnap/load_path_cache/cache.rb +150 -0
- data/lib/bootsnap/load_path_cache/change_observer.rb +56 -0
- data/lib/bootsnap/load_path_cache/core_ext/active_support.rb +68 -0
- data/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +88 -0
- data/lib/bootsnap/load_path_cache/path.rb +93 -0
- data/lib/bootsnap/load_path_cache/path_scanner.rb +44 -0
- data/lib/bootsnap/load_path_cache/store.rb +77 -0
- data/lib/bootsnap/version.rb +3 -0
- metadata +172 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
module Bootsnap
|
2
|
+
module LoadPathCache
|
3
|
+
module ChangeObserver
|
4
|
+
def self.register(observer, arr)
|
5
|
+
# Re-overriding these methods on an array that already has them would
|
6
|
+
# cause StackOverflowErrors
|
7
|
+
return if arr.respond_to?(:push_without_lpc)
|
8
|
+
|
9
|
+
# For each method that adds items to one end or another of the array
|
10
|
+
# (<<, push, unshift, concat), override that method to also notify the
|
11
|
+
# observer of the change.
|
12
|
+
sc = arr.singleton_class
|
13
|
+
sc.send(:alias_method, :shovel_without_lpc, :<<)
|
14
|
+
arr.define_singleton_method(:<<) do |entry|
|
15
|
+
observer.push_paths(self, entry)
|
16
|
+
shovel_without_lpc(entry)
|
17
|
+
end
|
18
|
+
|
19
|
+
sc.send(:alias_method, :push_without_lpc, :push)
|
20
|
+
arr.define_singleton_method(:push) do |*entries|
|
21
|
+
observer.push_paths(self, *entries)
|
22
|
+
push_without_lpc(*entries)
|
23
|
+
end
|
24
|
+
|
25
|
+
sc.send(:alias_method, :unshift_without_lpc, :unshift)
|
26
|
+
arr.define_singleton_method(:unshift) do |*entries|
|
27
|
+
observer.unshift_paths(self, *entries)
|
28
|
+
unshift_without_lpc(*entries)
|
29
|
+
end
|
30
|
+
|
31
|
+
sc.send(:alias_method, :concat_without_lpc, :concat)
|
32
|
+
arr.define_singleton_method(:concat) do |entries|
|
33
|
+
observer.push_paths(self, *entries)
|
34
|
+
concat_without_lpc(entries)
|
35
|
+
end
|
36
|
+
|
37
|
+
# For each method that modifies the array more aggressively, override
|
38
|
+
# the method to also have the observer completely reconstruct its state
|
39
|
+
# after the modification. Many of these could be made to modify the
|
40
|
+
# internal state of the LoadPathCache::Cache more efficiently, but the
|
41
|
+
# accounting cost would be greater than the hit from these, since we
|
42
|
+
# actively discourage calling them.
|
43
|
+
%i(
|
44
|
+
collect! compact! delete delete_at delete_if fill flatten! insert map!
|
45
|
+
reject! reverse! select! shuffle! shift slice! sort! sort_by!
|
46
|
+
).each do |meth|
|
47
|
+
sc.send(:alias_method, :"#{meth}_without_lpc", meth)
|
48
|
+
arr.define_singleton_method(meth) do |*a|
|
49
|
+
send(:"#{meth}_without_lpc", *a)
|
50
|
+
observer.reinitialize
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Bootsnap
|
2
|
+
module LoadPathCache
|
3
|
+
module CoreExt
|
4
|
+
module ActiveSupport
|
5
|
+
def self.with_bootsnap_fallback(error)
|
6
|
+
yield
|
7
|
+
rescue error
|
8
|
+
without_bootsnap_cache { yield }
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.without_bootsnap_cache
|
12
|
+
prev = Thread.current[:without_bootsnap_cache] || false
|
13
|
+
Thread.current[:without_bootsnap_cache] = true
|
14
|
+
yield
|
15
|
+
ensure
|
16
|
+
Thread.current[:without_bootsnap_cache] = prev
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
def autoload_paths=(o)
|
21
|
+
r = super
|
22
|
+
Bootsnap::LoadPathCache.autoload_paths_cache.reinitialize(o)
|
23
|
+
r
|
24
|
+
end
|
25
|
+
|
26
|
+
def search_for_file(path)
|
27
|
+
return super if Thread.current[:without_bootsnap_cache]
|
28
|
+
begin
|
29
|
+
Bootsnap::LoadPathCache.autoload_paths_cache.find(path)
|
30
|
+
rescue Bootsnap::LoadPathCache::ReturnFalse
|
31
|
+
nil # doesn't really apply here
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def autoloadable_module?(path_suffix)
|
36
|
+
Bootsnap::LoadPathCache.autoload_paths_cache.has_dir?(path_suffix)
|
37
|
+
end
|
38
|
+
|
39
|
+
def remove_constant(const)
|
40
|
+
CoreExt::ActiveSupport.without_bootsnap_cache { super }
|
41
|
+
end
|
42
|
+
|
43
|
+
# If we can't find a constant using the patched implementation of
|
44
|
+
# search_for_file, try again with the default implementation.
|
45
|
+
#
|
46
|
+
# These methods call search_for_file, and we want to modify its
|
47
|
+
# behaviour. The gymnastics here are a bit awkward, but it prevents
|
48
|
+
# 200+ lines of monkeypatches.
|
49
|
+
def load_missing_constant(from_mod, const_name)
|
50
|
+
CoreExt::ActiveSupport.with_bootsnap_fallback(NameError) { super }
|
51
|
+
end
|
52
|
+
|
53
|
+
def depend_on(file_name, message = "No such file to load -- %s.rb")
|
54
|
+
CoreExt::ActiveSupport.with_bootsnap_fallback(LoadError) { super }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module ActiveSupport
|
63
|
+
module Dependencies
|
64
|
+
class << self
|
65
|
+
prepend Bootsnap::LoadPathCache::CoreExt::ActiveSupport::ClassMethods
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Bootsnap
|
2
|
+
module LoadPathCache
|
3
|
+
module CoreExt
|
4
|
+
def self.make_load_error(path)
|
5
|
+
err = LoadError.new("cannot load such file -- #{path}")
|
6
|
+
err.define_singleton_method(:path) { path }
|
7
|
+
err
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Kernel
|
14
|
+
alias_method :require_without_cache, :require
|
15
|
+
def require(path)
|
16
|
+
if resolved = Bootsnap::LoadPathCache.load_path_cache.find(path)
|
17
|
+
require_without_cache(resolved)
|
18
|
+
else
|
19
|
+
raise Bootsnap::LoadPathCache::CoreExt.make_load_error(path)
|
20
|
+
end
|
21
|
+
rescue Bootsnap::LoadPathCache::ReturnFalse
|
22
|
+
return false
|
23
|
+
rescue Bootsnap::LoadPathCache::FallbackScan
|
24
|
+
require_without_cache(path)
|
25
|
+
end
|
26
|
+
|
27
|
+
alias_method :load_without_cache, :load
|
28
|
+
def load(path, wrap = false)
|
29
|
+
if resolved = Bootsnap::LoadPathCache.load_path_cache.find(path)
|
30
|
+
load_without_cache(resolved, wrap)
|
31
|
+
else
|
32
|
+
# load also allows relative paths from pwd even when not in $:
|
33
|
+
relative = File.expand_path(path)
|
34
|
+
if File.exist?(File.expand_path(path))
|
35
|
+
return load_without_cache(relative, wrap)
|
36
|
+
end
|
37
|
+
raise Bootsnap::LoadPathCache::CoreExt.make_load_error(path)
|
38
|
+
end
|
39
|
+
rescue Bootsnap::LoadPathCache::ReturnFalse
|
40
|
+
return false
|
41
|
+
rescue Bootsnap::LoadPathCache::FallbackScan
|
42
|
+
load_without_cache(path, wrap)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class << Kernel
|
47
|
+
alias_method :require_without_cache, :require
|
48
|
+
def require(path)
|
49
|
+
if resolved = Bootsnap::LoadPathCache.load_path_cache.find(path)
|
50
|
+
require_without_cache(resolved)
|
51
|
+
else
|
52
|
+
raise Bootsnap::LoadPathCache::CoreExt.make_load_error(path)
|
53
|
+
end
|
54
|
+
rescue Bootsnap::LoadPathCache::ReturnFalse
|
55
|
+
return false
|
56
|
+
rescue Bootsnap::LoadPathCache::FallbackScan
|
57
|
+
require_without_cache(path)
|
58
|
+
end
|
59
|
+
|
60
|
+
alias_method :load_without_cache, :load
|
61
|
+
def load(path, wrap = false)
|
62
|
+
if resolved = Bootsnap::LoadPathCache.load_path_cache.find(path)
|
63
|
+
load_without_cache(resolved, wrap)
|
64
|
+
else
|
65
|
+
# load also allows relative paths from pwd even when not in $:
|
66
|
+
relative = File.expand_path(path)
|
67
|
+
if File.exist?(relative)
|
68
|
+
return load_without_cache(relative, wrap)
|
69
|
+
end
|
70
|
+
raise Bootsnap::LoadPathCache::CoreExt.make_load_error(path)
|
71
|
+
end
|
72
|
+
rescue Bootsnap::LoadPathCache::ReturnFalse
|
73
|
+
return false
|
74
|
+
rescue Bootsnap::LoadPathCache::FallbackScan
|
75
|
+
load_without_cache(path, wrap)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class Module
|
80
|
+
alias_method :autoload_without_cache, :autoload
|
81
|
+
def autoload(const, path)
|
82
|
+
autoload_without_cache(const, Bootsnap::LoadPathCache.load_path_cache.find(path) || path)
|
83
|
+
rescue Bootsnap::LoadPathCache::ReturnFalse
|
84
|
+
return false
|
85
|
+
rescue Bootsnap::LoadPathCache::FallbackScan
|
86
|
+
autoload_without_cache(const, path)
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require_relative 'path_scanner'
|
2
|
+
|
3
|
+
module Bootsnap
|
4
|
+
module LoadPathCache
|
5
|
+
class Path
|
6
|
+
# A path is considered 'stable' if it is part of a Gem.path or the ruby
|
7
|
+
# distribution. When adding or removing files in these paths, the cache
|
8
|
+
# must be cleared before the change will be noticed.
|
9
|
+
def stable?
|
10
|
+
stability == STABLE
|
11
|
+
end
|
12
|
+
|
13
|
+
# A path is considered volatile if it doesn't live under a Gem.path or
|
14
|
+
# the ruby distribution root. These paths are scanned for new additions
|
15
|
+
# more frequently.
|
16
|
+
def volatile?
|
17
|
+
stability == VOLATILE
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :path
|
21
|
+
|
22
|
+
def initialize(path)
|
23
|
+
@path = path
|
24
|
+
end
|
25
|
+
|
26
|
+
# Return a list of all the requirable files and all of the subdirectories
|
27
|
+
# of this +Path+.
|
28
|
+
def entries_and_dirs(store)
|
29
|
+
if stable?
|
30
|
+
# the cached_mtime field is unused for 'stable' paths, but is
|
31
|
+
# set to zero anyway, just in case we change the stability heuristics.
|
32
|
+
_, entries, dirs = store.get(path)
|
33
|
+
return [entries, dirs] if entries # cache hit
|
34
|
+
entries, dirs = scan!
|
35
|
+
store.set(path, [0, entries, dirs])
|
36
|
+
return [entries, dirs]
|
37
|
+
end
|
38
|
+
|
39
|
+
cached_mtime, entries, dirs = store.get(path)
|
40
|
+
|
41
|
+
current_mtime = latest_mtime(path, dirs || [])
|
42
|
+
return [[], []] if current_mtime == -1 # path does not exist
|
43
|
+
return [entries, dirs] if cached_mtime == current_mtime
|
44
|
+
|
45
|
+
entries, dirs = scan!
|
46
|
+
store.set(path, [current_mtime, entries, dirs])
|
47
|
+
[entries, dirs]
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def scan! # (expensive) returns [entries, dirs]
|
53
|
+
PathScanner.call(path)
|
54
|
+
end
|
55
|
+
|
56
|
+
# last time a directory was modified in this subtree. +dirs+ should be a
|
57
|
+
# list of relative paths to directories under +path+. e.g. for /a/b and
|
58
|
+
# /a/b/c, pass ('/a/b', ['c'])
|
59
|
+
def latest_mtime(path, dirs)
|
60
|
+
max = -1
|
61
|
+
["", *dirs].each do |dir|
|
62
|
+
curr = begin
|
63
|
+
File.mtime("#{path}/#{dir}").to_i
|
64
|
+
rescue Errno::ENOENT
|
65
|
+
-1
|
66
|
+
end
|
67
|
+
max = curr if curr > max
|
68
|
+
end
|
69
|
+
max
|
70
|
+
end
|
71
|
+
|
72
|
+
# a Path can be either stable of volatile, depending on how frequently we
|
73
|
+
# expect its contents may change. Stable paths aren't rescanned nearly as
|
74
|
+
# often.
|
75
|
+
STABLE = :stable
|
76
|
+
VOLATILE = :volatile
|
77
|
+
|
78
|
+
RUBY_PREFIX = RbConfig::CONFIG['prefix']
|
79
|
+
|
80
|
+
def stability
|
81
|
+
@stability ||= begin
|
82
|
+
if Gem.path.detect { |p| path.start_with?(p) }
|
83
|
+
STABLE
|
84
|
+
elsif path.start_with?(RUBY_PREFIX)
|
85
|
+
STABLE
|
86
|
+
else
|
87
|
+
VOLATILE
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require_relative '../load_path_cache'
|
2
|
+
|
3
|
+
module Bootsnap
|
4
|
+
module LoadPathCache
|
5
|
+
module PathScanner
|
6
|
+
RelativePathNotSupported = Class.new(StandardError)
|
7
|
+
|
8
|
+
REQUIRABLES_AND_DIRS = "/**/*{#{DOT_RB},#{DL_EXTENSIONS.join(',')},/}"
|
9
|
+
IS_DIR = %r{(.*)/\z}
|
10
|
+
NORMALIZE_NATIVE_EXTENSIONS = !DL_EXTENSIONS.include?(LoadPathCache::DOT_SO)
|
11
|
+
ALTERNATIVE_NATIVE_EXTENSIONS_PATTERN = /\.(o|bundle|dylib)\z/
|
12
|
+
BUNDLE_PATH = (Bundler.bundle_path.cleanpath.to_s << LoadPathCache::SLASH).freeze
|
13
|
+
|
14
|
+
def self.call(path)
|
15
|
+
raise RelativePathNotSupported unless path.start_with?(SLASH)
|
16
|
+
|
17
|
+
relative_slice = (path.size + 1)..-1
|
18
|
+
# If the bundle path is a descendent of this path, we do additional
|
19
|
+
# checks to prevent recursing into the bundle path as we recurse
|
20
|
+
# through this path. We don't want to scan the bundle path because
|
21
|
+
# anything useful in it will be present on other load path items.
|
22
|
+
#
|
23
|
+
# This can happen if, for example, the user adds '.' to the load path,
|
24
|
+
# and the bundle path is '.bundle'.
|
25
|
+
contains_bundle_path = BUNDLE_PATH.start_with?(path)
|
26
|
+
|
27
|
+
dirs = []
|
28
|
+
requirables = []
|
29
|
+
|
30
|
+
Dir.glob(path + REQUIRABLES_AND_DIRS).each do |absolute_path|
|
31
|
+
next if contains_bundle_path && absolute_path.start_with?(BUNDLE_PATH)
|
32
|
+
relative_path = absolute_path.slice!(relative_slice)
|
33
|
+
|
34
|
+
if md = relative_path.match(IS_DIR)
|
35
|
+
dirs << md[1]
|
36
|
+
else
|
37
|
+
requirables << relative_path
|
38
|
+
end
|
39
|
+
end
|
40
|
+
[requirables, dirs]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require_relative '../explicit_require'
|
2
|
+
|
3
|
+
Bootsnap::ExplicitRequire.with_gems('snappy') { require 'snappy' }
|
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
|
+
load_data
|
16
|
+
end
|
17
|
+
|
18
|
+
def get(key)
|
19
|
+
@data[key]
|
20
|
+
end
|
21
|
+
|
22
|
+
def fetch(key)
|
23
|
+
raise SetOutsideTransactionNotAllowed unless @in_txn
|
24
|
+
v = get(key)
|
25
|
+
unless v
|
26
|
+
@dirty = true
|
27
|
+
v = yield
|
28
|
+
@data[key] = v
|
29
|
+
end
|
30
|
+
v
|
31
|
+
end
|
32
|
+
|
33
|
+
def set(key, value)
|
34
|
+
raise SetOutsideTransactionNotAllowed unless @in_txn
|
35
|
+
if value != @data[key]
|
36
|
+
@dirty = true
|
37
|
+
@data[key] = value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def transaction
|
42
|
+
raise NestedTransactionError if @in_txn
|
43
|
+
@in_txn = true
|
44
|
+
yield
|
45
|
+
ensure
|
46
|
+
commit_transaction
|
47
|
+
@in_txn = false
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def commit_transaction
|
53
|
+
if @dirty
|
54
|
+
dump_data
|
55
|
+
@dirty = false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def load_data
|
60
|
+
@data = begin
|
61
|
+
MessagePack.load(Snappy.inflate(File.binread(@store_path)))
|
62
|
+
rescue Errno::ENOENT, Snappy::Error
|
63
|
+
{}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def dump_data
|
68
|
+
# Change contents atomically so other processes can't get invalid
|
69
|
+
# caches if they read at an inopportune time.
|
70
|
+
tmp = "#{@store_path}.#{(rand * 100000).to_i}.tmp"
|
71
|
+
FileUtils.mkpath(File.dirname(tmp))
|
72
|
+
File.binwrite(tmp, Snappy.deflate(MessagePack.dump(@data)))
|
73
|
+
FileUtils.mv(tmp, @store_path)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
metadata
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bootsnap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Burke Libbey
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-03-31 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
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: snappy
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.0.15
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.0.15
|
111
|
+
description: wip.
|
112
|
+
email:
|
113
|
+
- burke.libbey@shopify.com
|
114
|
+
executables: []
|
115
|
+
extensions:
|
116
|
+
- ext/bootsnap/extconf.rb
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- ".gitignore"
|
120
|
+
- ".rubocop.yml"
|
121
|
+
- CONTRIBUTING.md
|
122
|
+
- Gemfile
|
123
|
+
- README.md
|
124
|
+
- Rakefile
|
125
|
+
- bin/console
|
126
|
+
- bin/setup
|
127
|
+
- bin/testunit
|
128
|
+
- bootsnap.gemspec
|
129
|
+
- dev.yml
|
130
|
+
- ext/bootsnap/bootsnap.c
|
131
|
+
- ext/bootsnap/bootsnap.h
|
132
|
+
- ext/bootsnap/crc32.c
|
133
|
+
- ext/bootsnap/extconf.rb
|
134
|
+
- lib/bootsnap.rb
|
135
|
+
- lib/bootsnap/compile_cache.rb
|
136
|
+
- lib/bootsnap/compile_cache/iseq.rb
|
137
|
+
- lib/bootsnap/compile_cache/yaml.rb
|
138
|
+
- lib/bootsnap/explicit_require.rb
|
139
|
+
- lib/bootsnap/load_path_cache.rb
|
140
|
+
- lib/bootsnap/load_path_cache/cache.rb
|
141
|
+
- lib/bootsnap/load_path_cache/change_observer.rb
|
142
|
+
- lib/bootsnap/load_path_cache/core_ext/active_support.rb
|
143
|
+
- lib/bootsnap/load_path_cache/core_ext/kernel_require.rb
|
144
|
+
- lib/bootsnap/load_path_cache/path.rb
|
145
|
+
- lib/bootsnap/load_path_cache/path_scanner.rb
|
146
|
+
- lib/bootsnap/load_path_cache/store.rb
|
147
|
+
- lib/bootsnap/version.rb
|
148
|
+
homepage: https://github.com/Shopify/bootsnap
|
149
|
+
licenses:
|
150
|
+
- MIT
|
151
|
+
metadata: {}
|
152
|
+
post_install_message:
|
153
|
+
rdoc_options: []
|
154
|
+
require_paths:
|
155
|
+
- lib
|
156
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
requirements: []
|
167
|
+
rubyforge_project:
|
168
|
+
rubygems_version: 2.6.10
|
169
|
+
signing_key:
|
170
|
+
specification_version: 4
|
171
|
+
summary: wip
|
172
|
+
test_files: []
|