bootsnap 1.9.4 → 1.10.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7602567343afc549df266a1b3def7e8c1e755b03a9ce486d17bba7051e97dfda
4
- data.tar.gz: 607abfa5738cb016172bba2eb94af48b80b9e73dddea1090be77b7ca7d9f121d
3
+ metadata.gz: 96a4b41c02dc01b416bd262f43812b9541479330e4b073d428a6f0186fe07f9a
4
+ data.tar.gz: b221e0b0ce1da0552a7c08e1dd1ce84daab07129b834fd2bdec82f01a8645c50
5
5
  SHA512:
6
- metadata.gz: 7effd658adb07d075cfbc883f47382c23f774a872fcfa2daa0b137ff5f903057a1f825a90cd96cd5784a2e72fcb583ce05b4fcf98201a2a2cb6830c90109e096
7
- data.tar.gz: ed2f42c2e5e91c373c8882fbe17abfab93c43e6ab39b83a7aa3031d6dba48088da9c3a271b52bbb7bc83ace117d677ec25e4865936972d939a00b08580f5e45e
6
+ metadata.gz: 27c071b0a4efceb864931a673f7889fc95110f1ed8de4b50c17c99ecd4d62230321d14a23f346129f1f2198dc6a3222370e5bf8f105f52299799ba78aa361741
7
+ data.tar.gz: d5546dd05eaf860178526dc3bdcd33546f80cdcc5ebdb748ebf0b1fe8b813efed15387ea5835f4ab846775261d6df05e4d15df28ff81abb04ab795232435a194
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Unreleased
2
2
 
3
+ # 1.10.0
4
+
5
+ * Delay requiring `FileUtils`. (#285)
6
+ `FileUtils` can be installed as a gem, so it's best to wait for bundler to have setup the load path before requiring it.
7
+
8
+ * Improve support of Psych 4. (#392)
9
+ Since `1.8.0`, `YAML.load_file` was no longer cached when Psych 4 was used. This is because `load_file` loads
10
+ in safe mode by default, so the Bootsnap cache could defeat that safety.
11
+ Now when precompiling YAML files, Bootsnap first try to parse them in safe mode, and if it can't fallback to unsafe mode,
12
+ and the cache contains a flag that records wether it was generated in safe mode or not.
13
+ `YAML.unsafe_load_file` will use safe caches just fine, but `YAML.load_file` will fallback to uncached YAML parsing
14
+ if the cache was generated using unsafe parsing.
15
+
16
+ * Minimize the Kernel.require extra stack frames. (#393)
17
+ This should reduce the noise generated by bootsnap on `LoadError`.
18
+
3
19
  # 1.9.4
4
20
 
5
21
  * Ignore absolute paths in the loaded feature index. (#385)
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2017 Shopify, Inc.
3
+ Copyright (c) 2017-present Shopify, Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -41,7 +41,7 @@ getting progressively slower, this is almost certainly the cause.**
41
41
  It's technically possible to simply specify `gem 'bootsnap', require: 'bootsnap/setup'`, but it's
42
42
  important to load Bootsnap as early as possible to get maximum performance improvement.
43
43
 
44
- You can see how this require works [here](https://github.com/Shopify/bootsnap/blob/master/lib/bootsnap/setup.rb).
44
+ You can see how this require works [here](https://github.com/Shopify/bootsnap/blob/main/lib/bootsnap/setup.rb).
45
45
 
46
46
  If you are not using Rails, or if you are but want more control over things, add this to your
47
47
  application setup immediately after `require 'bundler/setup'` (i.e. as early as possible: the sooner
@@ -161,7 +161,7 @@ The only directories considered "stable" are things under the Ruby install prefi
161
161
  "volatile".
162
162
 
163
163
  In addition to the [`Bootsnap::LoadPathCache::Cache`
164
- source](https://github.com/Shopify/bootsnap/blob/master/lib/bootsnap/load_path_cache/cache.rb),
164
+ source](https://github.com/Shopify/bootsnap/blob/main/lib/bootsnap/load_path_cache/cache.rb),
165
165
  this diagram may help clarify how entry resolution works:
166
166
 
167
167
  ![How path searching works](https://cloud.githubusercontent.com/assets/3074765/25388270/670b5652-299b-11e7-87fb-975647f68981.png)
data/exe/bootsnap CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'bootsnap/cli'
4
+ require "bootsnap/cli"
5
5
  exit Bootsnap::CLI.new(ARGV).run
@@ -75,7 +75,7 @@ struct bs_cache_key {
75
75
  STATIC_ASSERT(sizeof(struct bs_cache_key) == KEY_SIZE);
76
76
 
77
77
  /* Effectively a schema version. Bumping invalidates all previous caches */
78
- static const uint32_t current_version = 3;
78
+ static const uint32_t current_version = 4;
79
79
 
80
80
  /* hash of e.g. "x86_64-darwin17", invalidating when ruby is recompiled on a
81
81
  * new OS ABI, etc. */
@@ -91,8 +91,7 @@ static mode_t current_umask;
91
91
  static VALUE rb_mBootsnap;
92
92
  static VALUE rb_mBootsnap_CompileCache;
93
93
  static VALUE rb_mBootsnap_CompileCache_Native;
94
- static VALUE rb_eBootsnap_CompileCache_Uncompilable;
95
- static ID uncompilable;
94
+ static VALUE rb_cBootsnap_CompileCache_UNCOMPILABLE;
96
95
  static ID instrumentation_method;
97
96
  static VALUE sym_miss;
98
97
  static VALUE sym_stale;
@@ -120,10 +119,8 @@ static uint32_t get_ruby_platform(void);
120
119
  * exception.
121
120
  */
122
121
  static int bs_storage_to_output(VALUE handler, VALUE args, VALUE storage_data, VALUE * output_data);
123
- static VALUE prot_storage_to_output(VALUE arg);
124
122
  static VALUE prot_input_to_output(VALUE arg);
125
123
  static void bs_input_to_output(VALUE handler, VALUE args, VALUE input_data, VALUE * output_data, int * exception_tag);
126
- static VALUE prot_input_to_storage(VALUE arg);
127
124
  static int bs_input_to_storage(VALUE handler, VALUE args, VALUE input_data, VALUE pathval, VALUE * storage_data);
128
125
  struct s2o_data;
129
126
  struct i2o_data;
@@ -151,12 +148,12 @@ Init_bootsnap(void)
151
148
  rb_mBootsnap = rb_define_module("Bootsnap");
152
149
  rb_mBootsnap_CompileCache = rb_define_module_under(rb_mBootsnap, "CompileCache");
153
150
  rb_mBootsnap_CompileCache_Native = rb_define_module_under(rb_mBootsnap_CompileCache, "Native");
154
- rb_eBootsnap_CompileCache_Uncompilable = rb_define_class_under(rb_mBootsnap_CompileCache, "Uncompilable", rb_eStandardError);
151
+ rb_cBootsnap_CompileCache_UNCOMPILABLE = rb_const_get(rb_mBootsnap_CompileCache, rb_intern("UNCOMPILABLE"));
152
+ rb_global_variable(&rb_cBootsnap_CompileCache_UNCOMPILABLE);
155
153
 
156
154
  current_ruby_revision = get_ruby_revision();
157
155
  current_ruby_platform = get_ruby_platform();
158
156
 
159
- uncompilable = rb_intern("__bootsnap_uncompilable__");
160
157
  instrumentation_method = rb_intern("_instrument");
161
158
 
162
159
  sym_miss = ID2SYM(rb_intern("miss"));
@@ -426,6 +423,7 @@ open_current_file(char * path, struct bs_cache_key * key, const char ** errno_pr
426
423
  #define ERROR_WITH_ERRNO -1
427
424
  #define CACHE_MISS -2
428
425
  #define CACHE_STALE -3
426
+ #define CACHE_UNCOMPILABLE -4
429
427
 
430
428
  /*
431
429
  * Read the cache key from the given fd, which must have position 0 (e.g.
@@ -507,14 +505,14 @@ fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE *
507
505
  if (data_size > 100000000000) {
508
506
  *errno_provenance = "bs_fetch:fetch_cached_data:datasize";
509
507
  errno = EINVAL; /* because wtf? */
510
- ret = -1;
508
+ ret = ERROR_WITH_ERRNO;
511
509
  goto done;
512
510
  }
513
511
  data = ALLOC_N(char, data_size);
514
512
  nread = read(fd, data, data_size);
515
513
  if (nread < 0) {
516
514
  *errno_provenance = "bs_fetch:fetch_cached_data:read";
517
- ret = -1;
515
+ ret = ERROR_WITH_ERRNO;
518
516
  goto done;
519
517
  }
520
518
  if (nread != data_size) {
@@ -525,6 +523,10 @@ fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE *
525
523
  storage_data = rb_str_new(data, data_size);
526
524
 
527
525
  *exception_tag = bs_storage_to_output(handler, args, storage_data, output_data);
526
+ if (*output_data == rb_cBootsnap_CompileCache_UNCOMPILABLE) {
527
+ ret = CACHE_UNCOMPILABLE;
528
+ goto done;
529
+ }
528
530
  ret = 0;
529
531
  done:
530
532
  if (data != NULL) xfree(data);
@@ -737,7 +739,15 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
737
739
  &output_data, &exception_tag, &errno_provenance
738
740
  );
739
741
  if (exception_tag != 0) goto raise;
740
- else if (res == CACHE_MISS || res == CACHE_STALE) valid_cache = 0;
742
+ else if (res == CACHE_UNCOMPILABLE) {
743
+ /* If fetch_cached_data returned `Uncompilable` we fallback to `input_to_output`
744
+ This happens if we have say, an unsafe YAML cache, but try to load it in safe mode */
745
+ if (bs_read_contents(current_fd, current_key.size, &contents, &errno_provenance) < 0) goto fail_errno;
746
+ input_data = rb_str_new(contents, current_key.size);
747
+ bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
748
+ if (exception_tag != 0) goto raise;
749
+ goto succeed;
750
+ } else if (res == CACHE_MISS || res == CACHE_STALE) valid_cache = 0;
741
751
  else if (res == ERROR_WITH_ERRNO) goto fail_errno;
742
752
  else if (!NIL_P(output_data)) goto succeed; /* fast-path, goal */
743
753
  }
@@ -754,7 +764,7 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
754
764
  if (exception_tag != 0) goto raise;
755
765
  /* If input_to_storage raised Bootsnap::CompileCache::Uncompilable, don't try
756
766
  * to cache anything; just return input_to_output(input_data) */
757
- if (storage_data == uncompilable) {
767
+ if (storage_data == rb_cBootsnap_CompileCache_UNCOMPILABLE) {
758
768
  bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
759
769
  if (exception_tag != 0) goto raise;
760
770
  goto succeed;
@@ -772,9 +782,13 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
772
782
  exception_tag = bs_storage_to_output(handler, args, storage_data, &output_data);
773
783
  if (exception_tag != 0) goto raise;
774
784
 
775
- /* If output_data is nil, delete the cache entry and generate the output
776
- * using input_to_output */
777
- if (NIL_P(output_data)) {
785
+ if (output_data == rb_cBootsnap_CompileCache_UNCOMPILABLE) {
786
+ /* If storage_to_output returned `Uncompilable` we fallback to `input_to_output` */
787
+ bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
788
+ if (exception_tag != 0) goto raise;
789
+ } else if (NIL_P(output_data)) {
790
+ /* If output_data is nil, delete the cache entry and generate the output
791
+ * using input_to_output */
778
792
  if (unlink(cache_path) < 0) {
779
793
  errno_provenance = "bs_fetch:unlink";
780
794
  goto fail_errno;
@@ -856,7 +870,7 @@ bs_precompile(char * path, VALUE path_v, char * cache_path, VALUE handler)
856
870
 
857
871
  /* If input_to_storage raised Bootsnap::CompileCache::Uncompilable, don't try
858
872
  * to cache anything; just return false */
859
- if (storage_data == uncompilable) {
873
+ if (storage_data == rb_cBootsnap_CompileCache_UNCOMPILABLE) {
860
874
  goto fail;
861
875
  }
862
876
  /* If storage_data isn't a string, we can't cache it */
@@ -919,7 +933,7 @@ struct i2s_data {
919
933
  };
920
934
 
921
935
  static VALUE
922
- prot_storage_to_output(VALUE arg)
936
+ try_storage_to_output(VALUE arg)
923
937
  {
924
938
  struct s2o_data * data = (struct s2o_data *)arg;
925
939
  return rb_funcall(data->handler, rb_intern("storage_to_output"), 2, data->storage_data, data->args);
@@ -934,7 +948,7 @@ bs_storage_to_output(VALUE handler, VALUE args, VALUE storage_data, VALUE * outp
934
948
  .args = args,
935
949
  .storage_data = storage_data,
936
950
  };
937
- *output_data = rb_protect(prot_storage_to_output, (VALUE)&s2o_data, &state);
951
+ *output_data = rb_protect(try_storage_to_output, (VALUE)&s2o_data, &state);
938
952
  return state;
939
953
  }
940
954
 
@@ -963,22 +977,6 @@ try_input_to_storage(VALUE arg)
963
977
  return rb_funcall(data->handler, rb_intern("input_to_storage"), 2, data->input_data, data->pathval);
964
978
  }
965
979
 
966
- static VALUE
967
- rescue_input_to_storage(VALUE arg, VALUE e)
968
- {
969
- return uncompilable;
970
- }
971
-
972
- static VALUE
973
- prot_input_to_storage(VALUE arg)
974
- {
975
- struct i2s_data * data = (struct i2s_data *)arg;
976
- return rb_rescue2(
977
- try_input_to_storage, (VALUE)data,
978
- rescue_input_to_storage, Qnil,
979
- rb_eBootsnap_CompileCache_Uncompilable, 0);
980
- }
981
-
982
980
  static int
983
981
  bs_input_to_storage(VALUE handler, VALUE args, VALUE input_data, VALUE pathval, VALUE * storage_data)
984
982
  {
@@ -988,6 +986,6 @@ bs_input_to_storage(VALUE handler, VALUE args, VALUE input_data, VALUE pathval,
988
986
  .input_data = input_data,
989
987
  .pathval = pathval,
990
988
  };
991
- *storage_data = rb_protect(prot_input_to_storage, (VALUE)&i2s_data, &state);
989
+ *storage_data = rb_protect(try_input_to_storage, (VALUE)&i2s_data, &state);
992
990
  return state;
993
991
  }
@@ -1,21 +1,23 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require("mkmf")
3
4
 
4
- if RUBY_ENGINE == 'ruby'
5
- $CFLAGS << ' -O3 '
6
- $CFLAGS << ' -std=c99'
5
+ if RUBY_ENGINE == "ruby"
6
+ $CFLAGS << " -O3 "
7
+ $CFLAGS << " -std=c99"
7
8
 
8
9
  # ruby.h has some -Wpedantic fails in some cases
9
10
  # (e.g. https://github.com/Shopify/bootsnap/issues/15)
10
- unless ['0', '', nil].include?(ENV['BOOTSNAP_PEDANTIC'])
11
- $CFLAGS << ' -Wall'
12
- $CFLAGS << ' -Werror'
13
- $CFLAGS << ' -Wextra'
14
- $CFLAGS << ' -Wpedantic'
11
+ unless ["0", "", nil].include?(ENV["BOOTSNAP_PEDANTIC"])
12
+ $CFLAGS << " -Wall"
13
+ $CFLAGS << " -Werror"
14
+ $CFLAGS << " -Wextra"
15
+ $CFLAGS << " -Wpedantic"
15
16
 
16
- $CFLAGS << ' -Wno-unused-parameter' # VALUE self has to be there but we don't care what it is.
17
- $CFLAGS << ' -Wno-keyword-macro' # hiding return
18
- $CFLAGS << ' -Wno-gcc-compat' # ruby.h 2.6.0 on macos 10.14, dunno
17
+ $CFLAGS << " -Wno-unused-parameter" # VALUE self has to be there but we don't care what it is.
18
+ $CFLAGS << " -Wno-keyword-macro" # hiding return
19
+ $CFLAGS << " -Wno-gcc-compat" # ruby.h 2.6.0 on macos 10.14, dunno
20
+ $CFLAGS << " -Wno-compound-token-split-by-macro"
19
21
  end
20
22
 
21
23
  create_makefile("bootsnap/bootsnap")
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Bootsnap
3
4
  extend(self)
4
5
 
@@ -63,6 +63,7 @@ module Bootsnap
63
63
  loop do
64
64
  job, *args = Marshal.load(@pipe_out)
65
65
  return if job == :exit
66
+
66
67
  @jobs.fetch(job).call(*args)
67
68
  end
68
69
  rescue IOError
data/lib/bootsnap/cli.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'bootsnap'
4
- require 'bootsnap/cli/worker_pool'
5
- require 'optparse'
6
- require 'fileutils'
7
- require 'etc'
3
+ require "bootsnap"
4
+ require "bootsnap/cli/worker_pool"
5
+ require "optparse"
6
+ require "fileutils"
7
+ require "etc"
8
8
 
9
9
  module Bootsnap
10
10
  class CLI
@@ -25,7 +25,7 @@ module Bootsnap
25
25
 
26
26
  def initialize(argv)
27
27
  @argv = argv
28
- self.cache_dir = ENV.fetch('BOOTSNAP_CACHE_DIR', 'tmp/cache')
28
+ self.cache_dir = ENV.fetch("BOOTSNAP_CACHE_DIR", "tmp/cache")
29
29
  self.compile_gemfile = false
30
30
  self.exclude = nil
31
31
  self.verbose = false
@@ -36,16 +36,16 @@ module Bootsnap
36
36
  end
37
37
 
38
38
  def precompile_command(*sources)
39
- require 'bootsnap/compile_cache/iseq'
40
- require 'bootsnap/compile_cache/yaml'
41
- require 'bootsnap/compile_cache/json'
39
+ require "bootsnap/compile_cache/iseq"
40
+ require "bootsnap/compile_cache/yaml"
41
+ require "bootsnap/compile_cache/json"
42
42
 
43
43
  fix_default_encoding do
44
- Bootsnap::CompileCache::ISeq.cache_dir = self.cache_dir
44
+ Bootsnap::CompileCache::ISeq.cache_dir = cache_dir
45
45
  Bootsnap::CompileCache::YAML.init!
46
- Bootsnap::CompileCache::YAML.cache_dir = self.cache_dir
46
+ Bootsnap::CompileCache::YAML.cache_dir = cache_dir
47
47
  Bootsnap::CompileCache::JSON.init!
48
- Bootsnap::CompileCache::JSON.cache_dir = self.cache_dir
48
+ Bootsnap::CompileCache::JSON.cache_dir = cache_dir
49
49
 
50
50
  @work_pool = WorkerPool.create(size: jobs, jobs: {
51
51
  ruby: method(:precompile_ruby),
@@ -61,7 +61,7 @@ module Bootsnap
61
61
 
62
62
  if compile_gemfile
63
63
  # Some gems embed their tests, they're very unlikely to be loaded, so not worth precompiling.
64
- gem_exclude = Regexp.union([exclude, '/spec/', '/test/'].compact)
64
+ gem_exclude = Regexp.union([exclude, "/spec/", "/test/"].compact)
65
65
  precompile_ruby_files($LOAD_PATH.map { |d| File.expand_path(d) }, exclude: gem_exclude)
66
66
 
67
67
  # Gems that include JSON or YAML files usually don't put them in `lib/`.
@@ -72,7 +72,7 @@ module Bootsnap
72
72
  precompile_json_files(gem_paths, exclude: gem_exclude)
73
73
  end
74
74
 
75
- if exitstatus = @work_pool.shutdown
75
+ if (exitstatus = @work_pool.shutdown)
76
76
  exit(exitstatus)
77
77
  end
78
78
  end
@@ -89,7 +89,7 @@ module Bootsnap
89
89
  if dir_sort
90
90
  def list_files(path, pattern)
91
91
  if File.directory?(path)
92
- Dir[File.join(path, pattern), sort: false]
92
+ Dir[File.join(path, pattern), sort: false]
93
93
  elsif File.exist?(path)
94
94
  [path]
95
95
  else
@@ -99,7 +99,7 @@ module Bootsnap
99
99
  else
100
100
  def list_files(path, pattern)
101
101
  if File.directory?(path)
102
- Dir[File.join(path, pattern)]
102
+ Dir[File.join(path, pattern)]
103
103
  elsif File.exist?(path)
104
104
  [path]
105
105
  else
@@ -126,9 +126,9 @@ module Bootsnap
126
126
 
127
127
  load_paths.each do |path|
128
128
  if !exclude || !exclude.match?(path)
129
- list_files(path, '**/*.{yml,yaml}').each do |yaml_file|
129
+ list_files(path, "**/*.{yml,yaml}").each do |yaml_file|
130
130
  # We ignore hidden files to not match the various .ci.yml files
131
- if !File.basename(yaml_file).start_with?('.') && (!exclude || !exclude.match?(yaml_file))
131
+ if !File.basename(yaml_file).start_with?(".") && (!exclude || !exclude.match?(yaml_file))
132
132
  @work_pool.push(:yaml, yaml_file)
133
133
  end
134
134
  end
@@ -138,7 +138,7 @@ module Bootsnap
138
138
 
139
139
  def precompile_yaml(*yaml_files)
140
140
  Array(yaml_files).each do |yaml_file|
141
- if CompileCache::YAML.precompile(yaml_file, cache_dir: cache_dir)
141
+ if CompileCache::YAML.precompile(yaml_file)
142
142
  STDERR.puts(yaml_file) if verbose
143
143
  end
144
144
  end
@@ -149,9 +149,9 @@ module Bootsnap
149
149
 
150
150
  load_paths.each do |path|
151
151
  if !exclude || !exclude.match?(path)
152
- list_files(path, '**/*.json').each do |json_file|
152
+ list_files(path, "**/*.json").each do |json_file|
153
153
  # We ignore hidden files to not match the various .config.json files
154
- if !File.basename(json_file).start_with?('.') && (!exclude || !exclude.match?(json_file))
154
+ if !File.basename(json_file).start_with?(".") && (!exclude || !exclude.match?(json_file))
155
155
  @work_pool.push(:json, json_file)
156
156
  end
157
157
  end
@@ -161,7 +161,7 @@ module Bootsnap
161
161
 
162
162
  def precompile_json(*json_files)
163
163
  Array(json_files).each do |json_file|
164
- if CompileCache::JSON.precompile(json_file, cache_dir: cache_dir)
164
+ if CompileCache::JSON.precompile(json_file)
165
165
  STDERR.puts(json_file) if verbose
166
166
  end
167
167
  end
@@ -172,7 +172,7 @@ module Bootsnap
172
172
 
173
173
  load_paths.each do |path|
174
174
  if !exclude || !exclude.match?(path)
175
- list_files(path, '**/*.rb').each do |ruby_file|
175
+ list_files(path, "**/*.rb").each do |ruby_file|
176
176
  if !exclude || !exclude.match?(ruby_file)
177
177
  @work_pool.push(:ruby, ruby_file)
178
178
  end
@@ -183,7 +183,7 @@ module Bootsnap
183
183
 
184
184
  def precompile_ruby(*ruby_files)
185
185
  Array(ruby_files).each do |ruby_file|
186
- if CompileCache::ISeq.precompile(ruby_file, cache_dir: cache_dir)
186
+ if CompileCache::ISeq.precompile(ruby_file)
187
187
  STDERR.puts(ruby_file) if verbose
188
188
  end
189
189
  end
@@ -210,7 +210,7 @@ module Bootsnap
210
210
  end
211
211
 
212
212
  def cache_dir=(dir)
213
- @cache_dir = File.expand_path(File.join(dir, 'bootsnap/compile-cache'))
213
+ @cache_dir = File.expand_path(File.join(dir, "bootsnap/compile-cache"))
214
214
  end
215
215
 
216
216
  def exclude_pattern(pattern)
@@ -225,24 +225,24 @@ module Bootsnap
225
225
  opts.separator "GLOBAL OPTIONS"
226
226
  opts.separator ""
227
227
 
228
- help = <<~EOS
228
+ help = <<~HELP
229
229
  Path to the bootsnap cache directory. Defaults to tmp/cache
230
- EOS
231
- opts.on('--cache-dir DIR', help.strip) do |dir|
230
+ HELP
231
+ opts.on("--cache-dir DIR", help.strip) do |dir|
232
232
  self.cache_dir = dir
233
233
  end
234
234
 
235
- help = <<~EOS
235
+ help = <<~HELP
236
236
  Print precompiled paths.
237
- EOS
238
- opts.on('--verbose', '-v', help.strip) do
237
+ HELP
238
+ opts.on("--verbose", "-v", help.strip) do
239
239
  self.verbose = true
240
240
  end
241
241
 
242
- help = <<~EOS
242
+ help = <<~HELP
243
243
  Number of workers to use. Default to number of processors, set to 0 to disable multi-processing.
244
- EOS
245
- opts.on('--jobs JOBS', '-j', help.strip) do |jobs|
244
+ HELP
245
+ opts.on("--jobs JOBS", "-j", help.strip) do |jobs|
246
246
  self.jobs = Integer(jobs)
247
247
  end
248
248
 
@@ -251,30 +251,30 @@ module Bootsnap
251
251
  opts.separator ""
252
252
  opts.separator " precompile [DIRECTORIES...]: Precompile all .rb files in the passed directories"
253
253
 
254
- help = <<~EOS
254
+ help = <<~HELP
255
255
  Precompile the gems in Gemfile
256
- EOS
257
- opts.on('--gemfile', help) { self.compile_gemfile = true }
256
+ HELP
257
+ opts.on("--gemfile", help) { self.compile_gemfile = true }
258
258
 
259
- help = <<~EOS
259
+ help = <<~HELP
260
260
  Path pattern to not precompile. e.g. --exclude 'aws-sdk|google-api'
261
- EOS
262
- opts.on('--exclude PATTERN', help) { |pattern| exclude_pattern(pattern) }
261
+ HELP
262
+ opts.on("--exclude PATTERN", help) { |pattern| exclude_pattern(pattern) }
263
263
 
264
- help = <<~EOS
264
+ help = <<~HELP
265
265
  Disable ISeq (.rb) precompilation.
266
- EOS
267
- opts.on('--no-iseq', help) { self.iseq = false }
266
+ HELP
267
+ opts.on("--no-iseq", help) { self.iseq = false }
268
268
 
269
- help = <<~EOS
269
+ help = <<~HELP
270
270
  Disable YAML precompilation.
271
- EOS
272
- opts.on('--no-yaml', help) { self.yaml = false }
271
+ HELP
272
+ opts.on("--no-yaml", help) { self.yaml = false }
273
273
 
274
- help = <<~EOS
274
+ help = <<~HELP
275
275
  Disable JSON precompilation.
276
- EOS
277
- opts.on('--no-json', help) { self.json = false }
276
+ HELP
277
+ opts.on("--no-json", help) { self.json = false }
278
278
  end
279
279
  end
280
280
  end
@@ -1,12 +1,17 @@
1
1
  # frozen_string_literal: true
2
- require('bootsnap/bootsnap')
3
- require('zlib')
2
+
3
+ require("bootsnap/bootsnap")
4
+ require("zlib")
4
5
 
5
6
  module Bootsnap
6
7
  module CompileCache
7
8
  module ISeq
8
9
  class << self
9
- attr_accessor(:cache_dir)
10
+ attr_reader(:cache_dir)
11
+
12
+ def cache_dir=(cache_dir)
13
+ @cache_dir = cache_dir.end_with?("/") ? "#{cache_dir}iseq" : "#{cache_dir}-iseq"
14
+ end
10
15
  end
11
16
 
12
17
  has_ruby_bug_18250 = begin # https://bugs.ruby-lang.org/issues/18250
@@ -23,27 +28,27 @@ module Bootsnap
23
28
  iseq = begin
24
29
  RubyVM::InstructionSequence.compile_file(path)
25
30
  rescue SyntaxError
26
- raise(Uncompilable, 'syntax error')
31
+ return UNCOMPILABLE # syntax error
27
32
  end
28
33
 
29
34
  begin
30
35
  iseq.to_binary
31
36
  rescue TypeError
32
- raise(Uncompilable, 'ruby bug #18250')
37
+ return UNCOMPILABLE # ruby bug #18250
33
38
  end
34
39
  end
35
40
  else
36
41
  def self.input_to_storage(_, path)
37
42
  RubyVM::InstructionSequence.compile_file(path).to_binary
38
43
  rescue SyntaxError
39
- raise(Uncompilable, 'syntax error')
44
+ return UNCOMPILABLE # syntax error
40
45
  end
41
46
  end
42
47
 
43
48
  def self.storage_to_output(binary, _args)
44
49
  RubyVM::InstructionSequence.load_from_binary(binary)
45
- rescue RuntimeError => e
46
- if e.message == 'broken binary format'
50
+ rescue RuntimeError => error
51
+ if error.message == "broken binary format"
47
52
  STDERR.puts("[Bootsnap::CompileCache] warning: rejecting broken binary")
48
53
  nil
49
54
  else
@@ -60,7 +65,7 @@ module Bootsnap
60
65
  )
61
66
  end
62
67
 
63
- def self.precompile(path, cache_dir: ISeq.cache_dir)
68
+ def self.precompile(path)
64
69
  Bootsnap::CompileCache::Native.precompile(
65
70
  cache_dir,
66
71
  path.to_s,
@@ -80,8 +85,8 @@ module Bootsnap
80
85
  Bootsnap::CompileCache::ISeq.fetch(path.to_s)
81
86
  rescue Errno::EACCES
82
87
  Bootsnap::CompileCache.permission_error(path)
83
- rescue RuntimeError => e
84
- if e.message =~ /unmatched platform/
88
+ rescue RuntimeError => error
89
+ if error.message =~ /unmatched platform/
85
90
  puts("unmatched platform for file #{path}")
86
91
  end
87
92
  raise
@@ -1,11 +1,17 @@
1
1
  # frozen_string_literal: true
2
- require('bootsnap/bootsnap')
2
+
3
+ require("bootsnap/bootsnap")
3
4
 
4
5
  module Bootsnap
5
6
  module CompileCache
6
7
  module JSON
7
8
  class << self
8
- attr_accessor(:msgpack_factory, :cache_dir, :supported_options)
9
+ attr_accessor(:msgpack_factory, :supported_options)
10
+ attr_reader(:cache_dir)
11
+
12
+ def cache_dir=(cache_dir)
13
+ @cache_dir = cache_dir.end_with?("/") ? "#{cache_dir}json" : "#{cache_dir}-json"
14
+ end
9
15
 
10
16
  def input_to_storage(payload, _)
11
17
  obj = ::JSON.parse(payload)
@@ -13,7 +19,7 @@ module Bootsnap
13
19
  end
14
20
 
15
21
  def storage_to_output(data, kwargs)
16
- if kwargs && kwargs.key?(:symbolize_names)
22
+ if kwargs&.key?(:symbolize_names)
17
23
  kwargs[:symbolize_keys] = kwargs.delete(:symbolize_names)
18
24
  end
19
25
  msgpack_factory.load(data, kwargs)
@@ -23,7 +29,7 @@ module Bootsnap
23
29
  ::JSON.parse(data, **(kwargs || {}))
24
30
  end
25
31
 
26
- def precompile(path, cache_dir: self.cache_dir)
32
+ def precompile(path)
27
33
  Bootsnap::CompileCache::Native.precompile(
28
34
  cache_dir,
29
35
  path.to_s,
@@ -40,22 +46,23 @@ module Bootsnap
40
46
  end
41
47
 
42
48
  def init!
43
- require('json')
44
- require('msgpack')
49
+ require("json")
50
+ require("msgpack")
45
51
 
46
52
  self.msgpack_factory = MessagePack::Factory.new
47
53
  self.supported_options = [:symbolize_names]
48
54
  if ::JSON.parse('["foo"]', freeze: true).first.frozen?
49
55
  self.supported_options = [:freeze]
50
56
  end
51
- self.supported_options.freeze
57
+ supported_options.freeze
52
58
  end
53
59
  end
54
60
 
55
61
  module Patch
56
62
  def load_file(path, *args)
57
63
  return super if args.size > 1
58
- if kwargs = args.first
64
+
65
+ if (kwargs = args.first)
59
66
  return super unless kwargs.is_a?(Hash)
60
67
  return super unless (kwargs.keys - ::Bootsnap::CompileCache::JSON.supported_options).empty?
61
68
  end