piko-lite-gem 0.0.1
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/bootsnap-1.24.6/CHANGELOG.md +473 -0
- data/bootsnap-1.24.6/LICENSE.txt +22 -0
- data/bootsnap-1.24.6/README.md +391 -0
- data/bootsnap-1.24.6/exe/bootsnap +5 -0
- data/bootsnap-1.24.6/ext/bootsnap/bootsnap.c +1235 -0
- data/bootsnap-1.24.6/ext/bootsnap/extconf.rb +34 -0
- data/bootsnap-1.24.6/lib/bootsnap/bundler.rb +16 -0
- data/bootsnap-1.24.6/lib/bootsnap/cli/worker_pool.rb +208 -0
- data/bootsnap-1.24.6/lib/bootsnap/cli.rb +258 -0
- data/bootsnap-1.24.6/lib/bootsnap/compile_cache/iseq.rb +229 -0
- data/bootsnap-1.24.6/lib/bootsnap/compile_cache/ruby_bug_22023_canary.rb +1 -0
- data/bootsnap-1.24.6/lib/bootsnap/compile_cache/yaml.rb +344 -0
- data/bootsnap-1.24.6/lib/bootsnap/compile_cache.rb +47 -0
- data/bootsnap-1.24.6/lib/bootsnap/explicit_require.rb +56 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/cache.rb +241 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/change_observer.rb +84 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +42 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb +19 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/loaded_features_index.rb +159 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/path.rb +143 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/path_scanner.rb +127 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/store.rb +132 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache.rb +80 -0
- data/bootsnap-1.24.6/lib/bootsnap/rake.rb +14 -0
- data/bootsnap-1.24.6/lib/bootsnap/setup.rb +5 -0
- data/bootsnap-1.24.6/lib/bootsnap/version.rb +5 -0
- data/bootsnap-1.24.6/lib/bootsnap.rb +350 -0
- data/piko-lite-gem.gemspec +12 -0
- metadata +69 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../explicit_require"
|
|
4
|
+
|
|
5
|
+
module Bootsnap
|
|
6
|
+
module LoadPathCache
|
|
7
|
+
module PathScanner
|
|
8
|
+
REQUIRABLE_EXTENSIONS = [DOT_RB] + DL_EXTENSIONS
|
|
9
|
+
|
|
10
|
+
BUNDLE_PATH = if Bootsnap.bundler?
|
|
11
|
+
(Bundler.bundle_path.cleanpath.to_s << LoadPathCache::SLASH).freeze
|
|
12
|
+
else
|
|
13
|
+
""
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
@ignored_directories = %w(node_modules)
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
attr_accessor :ignored_directories
|
|
20
|
+
|
|
21
|
+
def ruby_call(root_path)
|
|
22
|
+
root_path, contains_bundle_path, ignored_abs_paths, ignored_dir_names = prepare_scan(root_path)
|
|
23
|
+
return [] unless File.directory?(root_path)
|
|
24
|
+
|
|
25
|
+
requirables = []
|
|
26
|
+
walk(root_path, nil, ignored_abs_paths, ignored_dir_names) do |relative_path, absolute_path, is_directory|
|
|
27
|
+
if is_directory
|
|
28
|
+
!contains_bundle_path || !absolute_path.start_with?(BUNDLE_PATH)
|
|
29
|
+
elsif relative_path.end_with?(*REQUIRABLE_EXTENSIONS)
|
|
30
|
+
requirables << relative_path.freeze
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
requirables
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
if RUBY_ENGINE == "ruby" && RUBY_PLATFORM.match?(/darwin|linux|bsd|mswin|mingw|cygwin/)
|
|
37
|
+
require "bootsnap/bootsnap"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if defined?(Native.scan_dir)
|
|
41
|
+
def native_call(root_path)
|
|
42
|
+
# NOTE: if https://bugs.ruby-lang.org/issues/21800 is accepted we should be able
|
|
43
|
+
# to have similar performance with pure Ruby
|
|
44
|
+
root_path, contains_bundle_path, ignored_abs_paths, ignored_dir_names = prepare_scan(root_path)
|
|
45
|
+
|
|
46
|
+
all_requirables, queue = Native.scan_dir(root_path)
|
|
47
|
+
all_requirables.each(&:freeze)
|
|
48
|
+
|
|
49
|
+
queue.reject! do |dir|
|
|
50
|
+
if ignored_dir_names&.include?(dir)
|
|
51
|
+
true
|
|
52
|
+
elsif ignored_abs_paths || contains_bundle_path
|
|
53
|
+
absolute_dir = File.join(root_path, dir)
|
|
54
|
+
ignored_abs_paths&.include?(absolute_dir) ||
|
|
55
|
+
(contains_bundle_path && absolute_dir.start_with?(BUNDLE_PATH))
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
while (relative_path = queue.pop)
|
|
60
|
+
absolute_base = File.join(root_path, relative_path)
|
|
61
|
+
requirables, dirs = Native.scan_dir(absolute_base)
|
|
62
|
+
dirs.reject! do |dir|
|
|
63
|
+
if ignored_dir_names&.include?(dir)
|
|
64
|
+
true
|
|
65
|
+
elsif ignored_abs_paths || contains_bundle_path
|
|
66
|
+
absolute_dir = File.join(absolute_base, dir)
|
|
67
|
+
ignored_abs_paths&.include?(absolute_dir) ||
|
|
68
|
+
(contains_bundle_path && absolute_dir.start_with?(BUNDLE_PATH))
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
dirs.map! { |f| File.join(relative_path, f).freeze }
|
|
72
|
+
requirables.map! { |f| File.join(relative_path, f).freeze }
|
|
73
|
+
|
|
74
|
+
all_requirables.concat(requirables)
|
|
75
|
+
queue.concat(dirs)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
all_requirables
|
|
79
|
+
end
|
|
80
|
+
alias_method :call, :native_call
|
|
81
|
+
else
|
|
82
|
+
alias_method :call, :ruby_call
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def prepare_scan(root_path)
|
|
88
|
+
root_path = File.expand_path(root_path.to_s).freeze
|
|
89
|
+
|
|
90
|
+
# If the bundle path is a descendent of this path, we do additional
|
|
91
|
+
# checks to prevent recursing into the bundle path as we recurse
|
|
92
|
+
# through this path. We don't want to scan the bundle path because
|
|
93
|
+
# anything useful in it will be present on other load path items.
|
|
94
|
+
#
|
|
95
|
+
# This can happen if, for example, the user adds '.' to the load path,
|
|
96
|
+
# and the bundle path is '.bundle'.
|
|
97
|
+
contains_bundle_path = BUNDLE_PATH.start_with?(root_path)
|
|
98
|
+
|
|
99
|
+
ignored_abs_paths, ignored_dir_names = ignored_directories.partition { |p| File.absolute_path?(p) }
|
|
100
|
+
ignored_abs_paths = nil if ignored_abs_paths.empty?
|
|
101
|
+
ignored_dir_names = nil if ignored_dir_names.empty?
|
|
102
|
+
|
|
103
|
+
[root_path, contains_bundle_path, ignored_abs_paths, ignored_dir_names]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def walk(absolute_dir_path, relative_dir_path, ignored_abs_paths, ignored_dir_names, &block)
|
|
107
|
+
Dir.foreach(absolute_dir_path) do |name|
|
|
108
|
+
next if name.start_with?(".")
|
|
109
|
+
|
|
110
|
+
relative_path = relative_dir_path ? File.join(relative_dir_path, name) : name
|
|
111
|
+
|
|
112
|
+
absolute_path = File.join(absolute_dir_path, name)
|
|
113
|
+
if File.directory?(absolute_path)
|
|
114
|
+
next if ignored_dir_names&.include?(name) || ignored_abs_paths&.include?(absolute_path)
|
|
115
|
+
|
|
116
|
+
if yield relative_path, absolute_path, true
|
|
117
|
+
walk(absolute_path, relative_path, ignored_abs_paths, ignored_dir_names, &block)
|
|
118
|
+
end
|
|
119
|
+
else
|
|
120
|
+
yield relative_path, absolute_path, false
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../explicit_require"
|
|
4
|
+
|
|
5
|
+
Bootsnap::ExplicitRequire.with_gems("msgpack") { require "msgpack" }
|
|
6
|
+
|
|
7
|
+
module Bootsnap
|
|
8
|
+
module LoadPathCache
|
|
9
|
+
class Store
|
|
10
|
+
VERSION_KEY = "__bootsnap_ruby_version__"
|
|
11
|
+
CURRENT_VERSION = "#{VERSION}-#{RUBY_REVISION}-#{RUBY_PLATFORM}".freeze # rubocop:disable Style/RedundantFreeze
|
|
12
|
+
|
|
13
|
+
NestedTransactionError = Class.new(StandardError)
|
|
14
|
+
SetOutsideTransactionNotAllowed = Class.new(StandardError)
|
|
15
|
+
|
|
16
|
+
def initialize(store_path, readonly: false)
|
|
17
|
+
@store_path = store_path
|
|
18
|
+
@txn_mutex = Mutex.new
|
|
19
|
+
@dirty = false
|
|
20
|
+
@readonly = readonly
|
|
21
|
+
load_data
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def get(key)
|
|
25
|
+
@data[key]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def fetch(key)
|
|
29
|
+
raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
|
|
30
|
+
|
|
31
|
+
v = get(key)
|
|
32
|
+
unless v
|
|
33
|
+
v = yield
|
|
34
|
+
mark_for_mutation!
|
|
35
|
+
@data[key] = v
|
|
36
|
+
end
|
|
37
|
+
v
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def set(key, value)
|
|
41
|
+
raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
|
|
42
|
+
|
|
43
|
+
if value != @data[key]
|
|
44
|
+
mark_for_mutation!
|
|
45
|
+
@data[key] = value
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def transaction
|
|
50
|
+
raise(NestedTransactionError) if @txn_mutex.owned?
|
|
51
|
+
|
|
52
|
+
@txn_mutex.synchronize do
|
|
53
|
+
yield
|
|
54
|
+
ensure
|
|
55
|
+
commit_transaction
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def mark_for_mutation!
|
|
62
|
+
@dirty = true
|
|
63
|
+
@data = @data.dup if @data.frozen?
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def commit_transaction
|
|
67
|
+
if @dirty && !@readonly
|
|
68
|
+
dump_data
|
|
69
|
+
@dirty = false
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def load_data
|
|
74
|
+
@data = begin
|
|
75
|
+
data = File.open(@store_path, encoding: Encoding::BINARY) do |io|
|
|
76
|
+
MessagePack.load(io, freeze: true)
|
|
77
|
+
end
|
|
78
|
+
if data.is_a?(Hash) && data[VERSION_KEY] == CURRENT_VERSION
|
|
79
|
+
data
|
|
80
|
+
else
|
|
81
|
+
default_data
|
|
82
|
+
end
|
|
83
|
+
# handle malformed data due to upgrade incompatibility
|
|
84
|
+
rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
|
|
85
|
+
default_data
|
|
86
|
+
rescue ArgumentError => error
|
|
87
|
+
if error.message.include?("negative array size")
|
|
88
|
+
default_data
|
|
89
|
+
else
|
|
90
|
+
raise
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def dump_data
|
|
96
|
+
# Change contents atomically so other processes can't get invalid
|
|
97
|
+
# caches if they read at an inopportune time.
|
|
98
|
+
tmp = "#{@store_path}.#{Process.pid}.#{(rand * 100_000).to_i}.tmp"
|
|
99
|
+
mkdir_p(File.dirname(tmp))
|
|
100
|
+
exclusive_write = File::Constants::CREAT | File::Constants::EXCL | File::Constants::WRONLY
|
|
101
|
+
# `encoding:` looks redundant wrt `binwrite`, but necessary on windows
|
|
102
|
+
# because binary is part of mode.
|
|
103
|
+
File.open(tmp, mode: exclusive_write, encoding: Encoding::BINARY) do |io|
|
|
104
|
+
MessagePack.dump(@data, io)
|
|
105
|
+
end
|
|
106
|
+
File.rename(tmp, @store_path)
|
|
107
|
+
rescue Errno::EEXIST
|
|
108
|
+
retry
|
|
109
|
+
rescue SystemCallError
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def default_data
|
|
113
|
+
{VERSION_KEY => CURRENT_VERSION}
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def mkdir_p(path)
|
|
117
|
+
stack = []
|
|
118
|
+
until File.directory?(path)
|
|
119
|
+
stack.push path
|
|
120
|
+
path = File.dirname(path)
|
|
121
|
+
end
|
|
122
|
+
stack.reverse_each do |dir|
|
|
123
|
+
Dir.mkdir(dir)
|
|
124
|
+
rescue SystemCallError
|
|
125
|
+
# Check for broken symlinks. Calling File.realpath will raise Errno::ENOENT if that is the case
|
|
126
|
+
File.realpath(dir) if File.symlink?(dir)
|
|
127
|
+
raise unless File.directory?(dir)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Bootsnap
|
|
4
|
+
module LoadPathCache
|
|
5
|
+
FALLBACK_SCAN = BasicObject.new
|
|
6
|
+
|
|
7
|
+
DOT_RB = ".rb"
|
|
8
|
+
DOT_SO = ".so"
|
|
9
|
+
SLASH = "/"
|
|
10
|
+
|
|
11
|
+
DL_EXTENSIONS = ::RbConfig::CONFIG
|
|
12
|
+
.values_at("DLEXT", "DLEXT2")
|
|
13
|
+
.reject { |ext| !ext || ext.empty? }
|
|
14
|
+
.map { |ext| ".#{ext}" }
|
|
15
|
+
.freeze
|
|
16
|
+
DLEXT = DL_EXTENSIONS[0]
|
|
17
|
+
# This is nil on linux and darwin, but I think it's '.o' on some other
|
|
18
|
+
# platform. I'm not really sure which, but it seems better to replicate
|
|
19
|
+
# ruby's semantics as faithfully as possible.
|
|
20
|
+
DLEXT2 = DL_EXTENSIONS[1]
|
|
21
|
+
|
|
22
|
+
CACHED_EXTENSIONS = DLEXT2 ? [DOT_RB, DLEXT, DLEXT2] : [DOT_RB, DLEXT]
|
|
23
|
+
|
|
24
|
+
@enabled = false
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
attr_reader(:load_path_cache, :loaded_features_index, :enabled)
|
|
28
|
+
alias_method :enabled?, :enabled
|
|
29
|
+
remove_method(:enabled)
|
|
30
|
+
|
|
31
|
+
def setup(cache_path:, development_mode:, ignore_directories:, readonly: false)
|
|
32
|
+
unless supported?
|
|
33
|
+
warn("[bootsnap/setup] Load path caching is not supported on this implementation of Ruby") if $VERBOSE
|
|
34
|
+
return
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
store = Store.new(cache_path, readonly: readonly)
|
|
38
|
+
|
|
39
|
+
@loaded_features_index = LoadedFeaturesIndex.new
|
|
40
|
+
|
|
41
|
+
PathScanner.ignored_directories = ignore_directories if ignore_directories
|
|
42
|
+
@load_path_cache = Cache.new(store, $LOAD_PATH, development_mode: development_mode)
|
|
43
|
+
@enabled = true
|
|
44
|
+
require_relative "load_path_cache/core_ext/kernel_require"
|
|
45
|
+
require_relative "load_path_cache/core_ext/loaded_features"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def unload!
|
|
49
|
+
@enabled = false
|
|
50
|
+
@loaded_features_index = nil
|
|
51
|
+
@realpath_cache = nil
|
|
52
|
+
@load_path_cache = nil
|
|
53
|
+
ChangeObserver.unregister($LOAD_PATH) if supported?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def supported?
|
|
57
|
+
if RUBY_PLATFORM.match?(/darwin|linux|bsd|mswin|mingw|cygwin/)
|
|
58
|
+
case RUBY_ENGINE
|
|
59
|
+
when "truffleruby"
|
|
60
|
+
# https://github.com/oracle/truffleruby/issues/3131
|
|
61
|
+
RUBY_ENGINE_VERSION >= "23.1.0"
|
|
62
|
+
when "ruby"
|
|
63
|
+
true
|
|
64
|
+
else
|
|
65
|
+
false
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
if Bootsnap::LoadPathCache.supported?
|
|
74
|
+
require_relative "load_path_cache/path_scanner"
|
|
75
|
+
require_relative "load_path_cache/path"
|
|
76
|
+
require_relative "load_path_cache/cache"
|
|
77
|
+
require_relative "load_path_cache/store"
|
|
78
|
+
require_relative "load_path_cache/change_observer"
|
|
79
|
+
require_relative "load_path_cache/loaded_features_index"
|
|
80
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bootsnap"
|
|
4
|
+
require "rake/clean"
|
|
5
|
+
|
|
6
|
+
# Typically, should have been set up prior to requiring rake integration.
|
|
7
|
+
# But allow for a streamlined ::default_setup
|
|
8
|
+
require "bootsnap/setup" if Bootsnap.cache_dir.nil?
|
|
9
|
+
|
|
10
|
+
if Bootsnap.cache_dir
|
|
11
|
+
CLEAN.include Bootsnap.cache_dir
|
|
12
|
+
else
|
|
13
|
+
abort "Bootsnap must be set-up prior to rake integration"
|
|
14
|
+
end
|