bootsnap 1.4.5-java → 1.5.0-java

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 +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/README.md +15 -2
  4. data/exe/bootsnap +5 -0
  5. data/ext/bootsnap/bootsnap.c +91 -64
  6. data/ext/bootsnap/extconf.rb +1 -0
  7. data/lib/bootsnap.rb +2 -0
  8. data/lib/bootsnap/bundler.rb +1 -0
  9. data/lib/bootsnap/cli.rb +136 -0
  10. data/lib/bootsnap/compile_cache.rb +3 -2
  11. data/lib/bootsnap/compile_cache/iseq.rb +15 -8
  12. data/lib/bootsnap/compile_cache/yaml.rb +67 -38
  13. data/lib/bootsnap/explicit_require.rb +1 -0
  14. data/lib/bootsnap/load_path_cache.rb +1 -1
  15. data/lib/bootsnap/load_path_cache/cache.rb +8 -8
  16. data/lib/bootsnap/load_path_cache/change_observer.rb +2 -1
  17. data/lib/bootsnap/load_path_cache/core_ext/active_support.rb +1 -0
  18. data/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +18 -5
  19. data/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb +1 -0
  20. data/lib/bootsnap/load_path_cache/loaded_features_index.rb +33 -10
  21. data/lib/bootsnap/load_path_cache/path.rb +3 -2
  22. data/lib/bootsnap/load_path_cache/path_scanner.rb +39 -26
  23. data/lib/bootsnap/load_path_cache/realpath_cache.rb +5 -5
  24. data/lib/bootsnap/load_path_cache/store.rb +6 -5
  25. data/lib/bootsnap/setup.rb +1 -0
  26. data/lib/bootsnap/version.rb +2 -1
  27. metadata +14 -28
  28. data/.github/CODEOWNERS +0 -2
  29. data/.github/probots.yml +0 -2
  30. data/.gitignore +0 -17
  31. data/.rubocop.yml +0 -20
  32. data/.travis.yml +0 -21
  33. data/CODE_OF_CONDUCT.md +0 -74
  34. data/CONTRIBUTING.md +0 -21
  35. data/Gemfile +0 -8
  36. data/README.jp.md +0 -231
  37. data/Rakefile +0 -12
  38. data/bin/ci +0 -10
  39. data/bin/console +0 -14
  40. data/bin/setup +0 -8
  41. data/bin/test-minimal-support +0 -7
  42. data/bin/testunit +0 -8
  43. data/bootsnap.gemspec +0 -45
  44. data/dev.yml +0 -10
  45. data/shipit.rubygems.yml +0 -0
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require("mkmf")
2
3
  $CFLAGS << ' -O3 '
3
4
  $CFLAGS << ' -std=c99'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative('bootsnap/version')
2
4
  require_relative('bootsnap/bundler')
3
5
  require_relative('bootsnap/load_path_cache')
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Bootsnap
2
3
  extend(self)
3
4
 
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bootsnap'
4
+ require 'optparse'
5
+ require 'fileutils'
6
+
7
+ module Bootsnap
8
+ class CLI
9
+ unless Regexp.method_defined?(:match?)
10
+ module RegexpMatchBackport
11
+ refine Regepx do
12
+ def match?(string)
13
+ !!match(string)
14
+ end
15
+ end
16
+ end
17
+ using RegexpMatchBackport
18
+ end
19
+
20
+ attr_reader :cache_dir, :argv
21
+
22
+ attr_accessor :compile_gemfile, :exclude
23
+
24
+ def initialize(argv)
25
+ @argv = argv
26
+ self.cache_dir = 'tmp/cache'
27
+ self.compile_gemfile = false
28
+ self.exclude = nil
29
+ end
30
+
31
+ def precompile_command(*sources)
32
+ require 'bootsnap/compile_cache/iseq'
33
+
34
+ Bootsnap::CompileCache::ISeq.cache_dir = self.cache_dir
35
+
36
+ if compile_gemfile
37
+ sources += $LOAD_PATH
38
+ end
39
+
40
+ sources.map { |d| File.expand_path(d) }.each do |path|
41
+ if !exclude || !exclude.match?(path)
42
+ list_ruby_files(path).each do |ruby_file|
43
+ if !exclude || !exclude.match?(ruby_file)
44
+ CompileCache::ISeq.fetch(ruby_file, cache_dir: cache_dir)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ 0
50
+ end
51
+
52
+ dir_sort = begin
53
+ Dir['.', sort: false]
54
+ true
55
+ rescue ArgumentError, TypeError
56
+ false
57
+ end
58
+
59
+ if dir_sort
60
+ def list_ruby_files(path)
61
+ if File.directory?(path)
62
+ Dir[File.join(path, '**/*.rb'), sort: false]
63
+ elsif File.exist?(path)
64
+ [path]
65
+ else
66
+ []
67
+ end
68
+ end
69
+ else
70
+ def list_ruby_files(path)
71
+ if File.directory?(path)
72
+ Dir[File.join(path, '**/*.rb')]
73
+ elsif File.exist?(path)
74
+ [path]
75
+ else
76
+ []
77
+ end
78
+ end
79
+ end
80
+
81
+ def run
82
+ parser.parse!(argv)
83
+ command = argv.shift
84
+ method = "#{command}_command"
85
+ if respond_to?(method)
86
+ public_send(method, *argv)
87
+ else
88
+ invalid_usage!("Unknown command: #{command}")
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ def invalid_usage!(message)
95
+ STDERR.puts message
96
+ STDERR.puts
97
+ STDERR.puts parser
98
+ 1
99
+ end
100
+
101
+ def cache_dir=(dir)
102
+ @cache_dir = File.expand_path(File.join(dir, 'bootsnap-compile-cache'))
103
+ end
104
+
105
+ def parser
106
+ @parser ||= OptionParser.new do |opts|
107
+ opts.banner = "Usage: bootsnap COMMAND [ARGS]"
108
+ opts.separator ""
109
+ opts.separator "GLOBAL OPTIONS"
110
+ opts.separator ""
111
+
112
+ help = <<~EOS
113
+ Path to the bootsnap cache directory. Defaults to tmp/cache
114
+ EOS
115
+ opts.on('--cache-dir DIR', help.strip) do |dir|
116
+ self.cache_dir = dir
117
+ end
118
+
119
+ opts.separator ""
120
+ opts.separator "COMMANDS"
121
+ opts.separator ""
122
+ opts.separator " precompile [DIRECTORIES...]: Precompile all .rb files in the passed directories"
123
+
124
+ help = <<~EOS
125
+ Precompile the gems in Gemfile
126
+ EOS
127
+ opts.on('--gemfile', help) { self.compile_gemfile = true }
128
+
129
+ help = <<~EOS
130
+ Path pattern to not precompile. e.g. --exclude 'aws-sdk|google-api'
131
+ EOS
132
+ opts.on('--exclude PATTERN', help) { |pattern| self.exclude = Regexp.new(pattern) }
133
+ end
134
+ end
135
+ end
136
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Bootsnap
2
3
  module CompileCache
3
4
  Error = Class.new(StandardError)
@@ -33,9 +34,9 @@ module Bootsnap
33
34
  end
34
35
 
35
36
  def self.supported?
36
- # only enable on 'ruby' (MRI), POSIX (darwin, linux, *bsd), and >= 2.3.0
37
+ # only enable on 'ruby' (MRI), POSIX (darwin, linux, *bsd), Windows (RubyInstaller2) and >= 2.3.0
37
38
  RUBY_ENGINE == 'ruby' &&
38
- RUBY_PLATFORM =~ /darwin|linux|bsd/ &&
39
+ RUBY_PLATFORM =~ /darwin|linux|bsd|mswin|mingw|cygwin/ &&
39
40
  Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.3.0")
40
41
  end
41
42
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require('bootsnap/bootsnap')
2
3
  require('zlib')
3
4
 
@@ -8,13 +9,13 @@ module Bootsnap
8
9
  attr_accessor(:cache_dir)
9
10
  end
10
11
 
11
- def self.input_to_storage(_, path)
12
+ def self.input_to_storage(_, path, _args)
12
13
  RubyVM::InstructionSequence.compile_file(path).to_binary
13
14
  rescue SyntaxError
14
15
  raise(Uncompilable, 'syntax error')
15
16
  end
16
17
 
17
- def self.storage_to_output(binary)
18
+ def self.storage_to_output(binary, _args)
18
19
  RubyVM::InstructionSequence.load_from_binary(binary)
19
20
  rescue RuntimeError => e
20
21
  if e.message == 'broken binary format'
@@ -25,7 +26,16 @@ module Bootsnap
25
26
  end
26
27
  end
27
28
 
28
- def self.input_to_output(_)
29
+ def self.fetch(path, cache_dir: ISeq.cache_dir)
30
+ Bootsnap::CompileCache::Native.fetch(
31
+ cache_dir,
32
+ path.to_s,
33
+ Bootsnap::CompileCache::ISeq,
34
+ nil,
35
+ )
36
+ end
37
+
38
+ def self.input_to_output(_, _)
29
39
  nil # ruby handles this
30
40
  end
31
41
 
@@ -34,11 +44,7 @@ module Bootsnap
34
44
  # Having coverage enabled prevents iseq dumping/loading.
35
45
  return nil if defined?(Coverage) && Bootsnap::CompileCache::Native.coverage_running?
36
46
 
37
- Bootsnap::CompileCache::Native.fetch(
38
- Bootsnap::CompileCache::ISeq.cache_dir,
39
- path.to_s,
40
- Bootsnap::CompileCache::ISeq
41
- )
47
+ Bootsnap::CompileCache::ISeq.fetch(path.to_s)
42
48
  rescue Errno::EACCES
43
49
  Bootsnap::CompileCache.permission_error(path)
44
50
  rescue RuntimeError => e
@@ -59,6 +65,7 @@ module Bootsnap
59
65
  crc = Zlib.crc32(option.inspect)
60
66
  Bootsnap::CompileCache::Native.compile_option_crc32 = crc
61
67
  end
68
+ compile_option_updated
62
69
 
63
70
  def self.install!(cache_dir)
64
71
  Bootsnap::CompileCache::ISeq.cache_dir = cache_dir
@@ -1,59 +1,88 @@
1
+ # frozen_string_literal: true
1
2
  require('bootsnap/bootsnap')
2
3
 
3
4
  module Bootsnap
4
5
  module CompileCache
5
6
  module YAML
6
7
  class << self
7
- attr_accessor(:msgpack_factory)
8
- end
8
+ attr_accessor(:msgpack_factory, :cache_dir, :supported_options)
9
9
 
10
- def self.input_to_storage(contents, _)
11
- raise(Uncompilable) if contents.index("!ruby/object")
12
- obj = ::YAML.load(contents)
13
- msgpack_factory.packer.write(obj).to_s
14
- rescue NoMethodError, RangeError
15
- # if the object included things that we can't serialize, fall back to
16
- # Marshal. It's a bit slower, but can encode anything yaml can.
17
- # NoMethodError is unexpected types; RangeError is Bignums
18
- Marshal.dump(obj)
19
- end
10
+ def input_to_storage(contents, _, kwargs)
11
+ raise(Uncompilable) if contents.index("!ruby/object")
12
+ obj = ::YAML.load(contents, **(kwargs || {}))
13
+ msgpack_factory.dump(obj)
14
+ rescue NoMethodError, RangeError
15
+ # if the object included things that we can't serialize, fall back to
16
+ # Marshal. It's a bit slower, but can encode anything yaml can.
17
+ # NoMethodError is unexpected types; RangeError is Bignums
18
+ Marshal.dump(obj)
19
+ end
20
+
21
+ def storage_to_output(data, kwargs)
22
+ # This could have a meaning in messagepack, and we're being a little lazy
23
+ # about it. -- but a leading 0x04 would indicate the contents of the YAML
24
+ # is a positive integer, which is rare, to say the least.
25
+ if data[0] == 0x04.chr && data[1] == 0x08.chr
26
+ Marshal.load(data)
27
+ else
28
+ msgpack_factory.load(data, **(kwargs || {}))
29
+ end
30
+ end
20
31
 
21
- def self.storage_to_output(data)
22
- # This could have a meaning in messagepack, and we're being a little lazy
23
- # about it. -- but a leading 0x04 would indicate the contents of the YAML
24
- # is a positive integer, which is rare, to say the least.
25
- if data[0] == 0x04.chr && data[1] == 0x08.chr
26
- Marshal.load(data)
27
- else
28
- msgpack_factory.unpacker.feed(data).read
32
+ def input_to_output(data, kwargs)
33
+ ::YAML.load(data, **(kwargs || {}))
29
34
  end
30
- end
31
35
 
32
- def self.input_to_output(data)
33
- ::YAML.load(data)
36
+ def install!(cache_dir)
37
+ self.cache_dir = cache_dir
38
+ init!
39
+ ::YAML.singleton_class.prepend(Patch)
40
+ end
41
+
42
+ def init!
43
+ require('yaml')
44
+ require('msgpack')
45
+
46
+ # MessagePack serializes symbols as strings by default.
47
+ # We want them to roundtrip cleanly, so we use a custom factory.
48
+ # see: https://github.com/msgpack/msgpack-ruby/pull/122
49
+ factory = MessagePack::Factory.new
50
+ factory.register_type(0x00, Symbol)
51
+ self.msgpack_factory = factory
52
+
53
+ self.supported_options = []
54
+ params = ::YAML.method(:load).parameters
55
+ if params.include?([:key, :symbolize_names])
56
+ self.supported_options << :symbolize_names
57
+ end
58
+ if params.include?([:key, :freeze])
59
+ if factory.load(factory.dump('yaml'), freeze: true).frozen?
60
+ self.supported_options << :freeze
61
+ end
62
+ end
63
+ self.supported_options.freeze
64
+ end
34
65
  end
35
66
 
36
- def self.install!(cache_dir)
37
- require('yaml')
38
- require('msgpack')
67
+ module Patch
68
+ extend self
39
69
 
40
- # MessagePack serializes symbols as strings by default.
41
- # We want them to roundtrip cleanly, so we use a custom factory.
42
- # see: https://github.com/msgpack/msgpack-ruby/pull/122
43
- factory = MessagePack::Factory.new
44
- factory.register_type(0x00, Symbol)
45
- Bootsnap::CompileCache::YAML.msgpack_factory = factory
70
+ def load_file(path, *args)
71
+ return super if args.size > 1
72
+ if kwargs = args.first
73
+ return super unless kwargs.is_a?(Hash)
74
+ return super unless (kwargs.keys - ::Bootsnap::CompileCache::YAML.supported_options).empty?
75
+ end
46
76
 
47
- klass = class << ::YAML; self; end
48
- klass.send(:define_method, :load_file) do |path|
49
77
  begin
50
- Bootsnap::CompileCache::Native.fetch(
51
- cache_dir,
78
+ ::Bootsnap::CompileCache::Native.fetch(
79
+ Bootsnap::CompileCache::YAML.cache_dir,
52
80
  path,
53
- Bootsnap::CompileCache::YAML
81
+ ::Bootsnap::CompileCache::YAML,
82
+ kwargs,
54
83
  )
55
84
  rescue Errno::EACCES
56
- Bootsnap::CompileCache.permission_error(path)
85
+ ::Bootsnap::CompileCache.permission_error(path)
57
86
  end
58
87
  end
59
88
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Bootsnap
2
3
  module ExplicitRequire
3
4
  ARCHDIR = RbConfig::CONFIG['archdir']
@@ -61,7 +61,7 @@ module Bootsnap
61
61
 
62
62
  def supported?
63
63
  RUBY_ENGINE == 'ruby' &&
64
- RUBY_PLATFORM =~ /darwin|linux|bsd/
64
+ RUBY_PLATFORM =~ /darwin|linux|bsd|mswin|mingw|cygwin/
65
65
  end
66
66
  end
67
67
  end
@@ -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
@@ -67,7 +67,7 @@ module Bootsnap
67
67
  # native dynamic extension, e.g. .bundle or .so), we know it was a
68
68
  # failure and there's nothing more we can do to find the file.
69
69
  # no extension, .rb, (.bundle or .so)
70
- when '', *CACHED_EXTENSIONS # rubocop:disable Performance/CaseWhenSplat
70
+ when '', *CACHED_EXTENSIONS
71
71
  nil
72
72
  # Ruby allows specifying native extensions as '.so' even when DLEXT
73
73
  # is '.bundle'. This is where we handle that case.
@@ -144,7 +144,7 @@ module Bootsnap
144
144
  expanded_path = p.expanded_path
145
145
  entries, dirs = p.entries_and_dirs(@store)
146
146
  # push -> low precedence -> set only if unset
147
- dirs.each { |dir| @dirs[dir] ||= path }
147
+ dirs.each { |dir| @dirs[dir] ||= path }
148
148
  entries.each { |rel| @index[rel] ||= expanded_path }
149
149
  end
150
150
  end
@@ -178,25 +178,25 @@ module Bootsnap
178
178
 
179
179
  if DLEXT2
180
180
  def search_index(f)
181
- try_index(f + DOT_RB) || try_index(f + DLEXT) || try_index(f + DLEXT2) || 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 + DOT_RB) || try_ext(f + DLEXT) || try_ext(f + DLEXT2) || 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 + DOT_RB) || try_index(f + DLEXT) || 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 + DOT_RB) || try_ext(f + DLEXT) || 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 + '/' + f
199
+ "#{p}/#{f}"
200
200
  end
201
201
  end
202
202
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Bootsnap
2
3
  module LoadPathCache
3
4
  module ChangeObserver
@@ -25,7 +26,7 @@ module Bootsnap
25
26
  super
26
27
  end
27
28
 
28
- # uniq! keeps the first occurance of each path, otherwise preserving
29
+ # uniq! keeps the first occurrence of each path, otherwise preserving
29
30
  # order, preserving the effective load path
30
31
  def uniq!(*args)
31
32
  ret = super
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Bootsnap
2
3
  module LoadPathCache
3
4
  module CoreExt