bootsnap 1.4.6 → 1.5.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 +4 -4
- data/CHANGELOG.md +32 -0
- data/README.md +14 -1
- data/exe/bootsnap +5 -0
- data/ext/bootsnap/bootsnap.c +64 -41
- data/lib/bootsnap.rb +1 -0
- data/lib/bootsnap/cli.rb +136 -0
- data/lib/bootsnap/compile_cache.rb +2 -2
- data/lib/bootsnap/compile_cache/iseq.rb +14 -8
- data/lib/bootsnap/compile_cache/yaml.rb +66 -38
- data/lib/bootsnap/load_path_cache.rb +1 -1
- data/lib/bootsnap/load_path_cache/cache.rb +6 -6
- data/lib/bootsnap/load_path_cache/change_observer.rb +1 -1
- data/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +16 -4
- data/lib/bootsnap/load_path_cache/loaded_features_index.rb +2 -2
- data/lib/bootsnap/load_path_cache/path.rb +2 -2
- data/lib/bootsnap/load_path_cache/path_scanner.rb +39 -26
- data/lib/bootsnap/load_path_cache/realpath_cache.rb +5 -5
- data/lib/bootsnap/load_path_cache/store.rb +1 -1
- data/lib/bootsnap/version.rb +1 -1
- metadata +13 -27
- data/.github/CODEOWNERS +0 -2
- data/.github/probots.yml +0 -2
- data/.gitignore +0 -17
- data/.rubocop.yml +0 -20
- data/.travis.yml +0 -21
- data/CODE_OF_CONDUCT.md +0 -74
- data/CONTRIBUTING.md +0 -21
- data/Gemfile +0 -9
- data/README.jp.md +0 -231
- data/Rakefile +0 -13
- data/bin/ci +0 -10
- data/bin/console +0 -15
- data/bin/setup +0 -8
- data/bin/test-minimal-support +0 -7
- data/bin/testunit +0 -8
- data/bootsnap.gemspec +0 -46
- data/dev.yml +0 -10
- data/shipit.rubygems.yml +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2540d5dccef7466e75321e3c503b9c6d10aa6195ea905ed75336ad56f6eea2d0
|
4
|
+
data.tar.gz: 2d36002c885f981b1dd77e211cdc5583a97328995a15c14ca4a127fa74043214
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 672246870422714d082b8233c9bd51d45cf96db5ff6f37f609aafeee208e74822619059df66af56562650c61c655b73c550767b24d76ee9018c088283838bd2e
|
7
|
+
data.tar.gz: 6e6aa8e96453eda1f8c46ffa0aedf7e39a59168d31ef1dc54aaf1de1d86d8bcd67324f668406b068a6f8a42b13178d91c301a9bbe8512058a4907de9233787b7
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,35 @@
|
|
1
|
+
# 1.5.0
|
2
|
+
|
3
|
+
* Add a command line to statically precompile the ISeq cache. (#326)
|
4
|
+
|
5
|
+
# 1.4.9
|
6
|
+
|
7
|
+
* [Windows support](https://github.com/Shopify/bootsnap/pull/319)
|
8
|
+
* [Fix potential crash](https://github.com/Shopify/bootsnap/pull/322)
|
9
|
+
|
10
|
+
# 1.4.8
|
11
|
+
|
12
|
+
* [Prevent FallbackScan from polluting exception cause](https://github.com/Shopify/bootsnap/pull/314)
|
13
|
+
|
14
|
+
# 1.4.7
|
15
|
+
|
16
|
+
* Various performance enhancements
|
17
|
+
* Fix race condition in heavy concurrent load scenarios that would cause bootsnap to raise
|
18
|
+
|
19
|
+
# 1.4.6
|
20
|
+
|
21
|
+
* Fix bug that was erroneously considering that files containing `.` in the names were being
|
22
|
+
required if a different file with the same name was already being required
|
23
|
+
|
24
|
+
Example:
|
25
|
+
|
26
|
+
require 'foo'
|
27
|
+
require 'foo.en'
|
28
|
+
|
29
|
+
Before bootsnap was considering `foo.en` to be the same file as `foo`
|
30
|
+
|
31
|
+
* Use glibc as part of the ruby_platform cache key
|
32
|
+
|
1
33
|
# 1.4.5
|
2
34
|
|
3
35
|
* MRI 2.7 support
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Bootsnap [](https://github.com/Shopify/bootsnap/actions)
|
2
2
|
|
3
3
|
Bootsnap is a library that plugs into Ruby, with optional support for `ActiveSupport` and `YAML`,
|
4
4
|
to optimize and cache expensive computations. See [How Does This Work](#how-does-this-work).
|
@@ -294,6 +294,19 @@ open /c/nope.bundle -> -1
|
|
294
294
|
# (nothing!)
|
295
295
|
```
|
296
296
|
|
297
|
+
## Precompilation
|
298
|
+
|
299
|
+
In development environments the bootsnap compilation cache is generated on the fly when source files are loaded.
|
300
|
+
But in production environments, such as docker images, you might need to precompile the cache.
|
301
|
+
|
302
|
+
To do so you can use the `bootsnap precompile` command.
|
303
|
+
|
304
|
+
Example:
|
305
|
+
|
306
|
+
```bash
|
307
|
+
$ bundle exec bootsnap precompile --gemfile app/ lib/
|
308
|
+
```
|
309
|
+
|
297
310
|
## When not to use Bootsnap
|
298
311
|
|
299
312
|
*Alternative engines*: Bootsnap is pretty reliant on MRI features, and parts are disabled entirely on alternative ruby
|
data/exe/bootsnap
ADDED
data/ext/bootsnap/bootsnap.c
CHANGED
@@ -32,6 +32,8 @@
|
|
32
32
|
|
33
33
|
#define KEY_SIZE 64
|
34
34
|
|
35
|
+
#define MAX_CREATE_TEMPFILE_ATTEMPT 3
|
36
|
+
|
35
37
|
/*
|
36
38
|
* An instance of this key is written as the first 64 bytes of each cache file.
|
37
39
|
* The mtime and size members track whether the file contents have changed, and
|
@@ -89,16 +91,16 @@ static ID uncompilable;
|
|
89
91
|
|
90
92
|
/* Functions exposed as module functions on Bootsnap::CompileCache::Native */
|
91
93
|
static VALUE bs_compile_option_crc32_set(VALUE self, VALUE crc32_v);
|
92
|
-
static VALUE bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler);
|
94
|
+
static VALUE bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler, VALUE args);
|
93
95
|
|
94
96
|
/* Helpers */
|
95
97
|
static uint64_t fnv1a_64(const char *str);
|
96
|
-
static void bs_cache_path(const char * cachedir, const char * path, char (* cache_path)[MAX_CACHEPATH_SIZE]);
|
98
|
+
static void bs_cache_path(const char * cachedir, const char * path, const char * extra, char (* cache_path)[MAX_CACHEPATH_SIZE]);
|
97
99
|
static int bs_read_key(int fd, struct bs_cache_key * key);
|
98
100
|
static int cache_key_equal(struct bs_cache_key * k1, struct bs_cache_key * k2);
|
99
|
-
static VALUE bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler);
|
101
|
+
static VALUE bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args);
|
100
102
|
static int open_current_file(char * path, struct bs_cache_key * key, const char ** errno_provenance);
|
101
|
-
static int fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE * output_data, int * exception_tag, const char ** errno_provenance);
|
103
|
+
static int fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE * output_data, int * exception_tag, const char ** errno_provenance);
|
102
104
|
static uint32_t get_ruby_revision(void);
|
103
105
|
static uint32_t get_ruby_platform(void);
|
104
106
|
|
@@ -106,12 +108,12 @@ static uint32_t get_ruby_platform(void);
|
|
106
108
|
* Helper functions to call ruby methods on handler object without crashing on
|
107
109
|
* exception.
|
108
110
|
*/
|
109
|
-
static int bs_storage_to_output(VALUE handler, VALUE storage_data, VALUE * output_data);
|
111
|
+
static int bs_storage_to_output(VALUE handler, VALUE args, VALUE storage_data, VALUE * output_data);
|
110
112
|
static VALUE prot_storage_to_output(VALUE arg);
|
111
113
|
static VALUE prot_input_to_output(VALUE arg);
|
112
|
-
static void bs_input_to_output(VALUE handler, VALUE input_data, VALUE * output_data, int * exception_tag);
|
114
|
+
static void bs_input_to_output(VALUE handler, VALUE args, VALUE input_data, VALUE * output_data, int * exception_tag);
|
113
115
|
static VALUE prot_input_to_storage(VALUE arg);
|
114
|
-
static int bs_input_to_storage(VALUE handler, VALUE input_data, VALUE pathval, VALUE * storage_data);
|
116
|
+
static int bs_input_to_storage(VALUE handler, VALUE args, VALUE input_data, VALUE pathval, VALUE * storage_data);
|
115
117
|
struct s2o_data;
|
116
118
|
struct i2o_data;
|
117
119
|
struct i2s_data;
|
@@ -146,7 +148,7 @@ Init_bootsnap(void)
|
|
146
148
|
uncompilable = rb_intern("__bootsnap_uncompilable__");
|
147
149
|
|
148
150
|
rb_define_module_function(rb_mBootsnap_CompileCache_Native, "coverage_running?", bs_rb_coverage_running, 0);
|
149
|
-
rb_define_module_function(rb_mBootsnap_CompileCache_Native, "fetch", bs_rb_fetch,
|
151
|
+
rb_define_module_function(rb_mBootsnap_CompileCache_Native, "fetch", bs_rb_fetch, 4);
|
150
152
|
rb_define_module_function(rb_mBootsnap_CompileCache_Native, "compile_option_crc32=", bs_compile_option_crc32_set, 1);
|
151
153
|
|
152
154
|
current_umask = umask(0777);
|
@@ -262,9 +264,12 @@ get_ruby_platform(void)
|
|
262
264
|
* The path will look something like: <cachedir>/12/34567890abcdef
|
263
265
|
*/
|
264
266
|
static void
|
265
|
-
bs_cache_path(const char * cachedir, const char * path, char (* cache_path)[MAX_CACHEPATH_SIZE])
|
267
|
+
bs_cache_path(const char * cachedir, const char * path, const char * extra, char (* cache_path)[MAX_CACHEPATH_SIZE])
|
266
268
|
{
|
267
269
|
uint64_t hash = fnv1a_64(path);
|
270
|
+
if (extra) {
|
271
|
+
hash ^= fnv1a_64(extra);
|
272
|
+
}
|
268
273
|
|
269
274
|
uint8_t first_byte = (hash >> (64 - 8));
|
270
275
|
uint64_t remainder = hash & 0x00ffffffffffffff;
|
@@ -299,7 +304,7 @@ cache_key_equal(struct bs_cache_key * k1, struct bs_cache_key * k2)
|
|
299
304
|
* conversions on the ruby VALUE arguments before passing them along.
|
300
305
|
*/
|
301
306
|
static VALUE
|
302
|
-
bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler)
|
307
|
+
bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler, VALUE args)
|
303
308
|
{
|
304
309
|
FilePathValue(path_v);
|
305
310
|
|
@@ -313,11 +318,16 @@ bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler)
|
|
313
318
|
char * cachedir = RSTRING_PTR(cachedir_v);
|
314
319
|
char * path = RSTRING_PTR(path_v);
|
315
320
|
char cache_path[MAX_CACHEPATH_SIZE];
|
321
|
+
char * extra = NULL;
|
322
|
+
if (!NIL_P(args)) {
|
323
|
+
VALUE args_serial = rb_marshal_dump(args, Qnil);
|
324
|
+
extra = RSTRING_PTR(args_serial);
|
325
|
+
}
|
316
326
|
|
317
327
|
/* generate cache path to cache_path */
|
318
|
-
bs_cache_path(cachedir, path, &cache_path);
|
328
|
+
bs_cache_path(cachedir, path, extra, &cache_path);
|
319
329
|
|
320
|
-
return bs_fetch(path, path_v, cache_path, handler);
|
330
|
+
return bs_fetch(path, path_v, cache_path, handler, args);
|
321
331
|
}
|
322
332
|
|
323
333
|
/*
|
@@ -426,7 +436,7 @@ open_cache_file(const char * path, struct bs_cache_key * key, const char ** errn
|
|
426
436
|
* or exception, will be the final data returnable to the user.
|
427
437
|
*/
|
428
438
|
static int
|
429
|
-
fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE * output_data, int * exception_tag, const char ** errno_provenance)
|
439
|
+
fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE * output_data, int * exception_tag, const char ** errno_provenance)
|
430
440
|
{
|
431
441
|
char * data = NULL;
|
432
442
|
ssize_t nread;
|
@@ -452,9 +462,9 @@ fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE * output_data,
|
|
452
462
|
goto done;
|
453
463
|
}
|
454
464
|
|
455
|
-
storage_data =
|
465
|
+
storage_data = rb_str_new(data, data_size);
|
456
466
|
|
457
|
-
*exception_tag = bs_storage_to_output(handler, storage_data, output_data);
|
467
|
+
*exception_tag = bs_storage_to_output(handler, args, storage_data, output_data);
|
458
468
|
ret = 0;
|
459
469
|
done:
|
460
470
|
if (data != NULL) xfree(data);
|
@@ -499,25 +509,32 @@ atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data, cons
|
|
499
509
|
{
|
500
510
|
char template[MAX_CACHEPATH_SIZE + 20];
|
501
511
|
char * tmp_path;
|
502
|
-
int fd, ret;
|
512
|
+
int fd, ret, attempt;
|
503
513
|
ssize_t nwrite;
|
504
514
|
|
505
|
-
|
506
|
-
|
515
|
+
for (attempt = 0; attempt < MAX_CREATE_TEMPFILE_ATTEMPT; ++attempt) {
|
516
|
+
tmp_path = strncpy(template, path, MAX_CACHEPATH_SIZE);
|
517
|
+
strcat(tmp_path, ".tmp.XXXXXX");
|
507
518
|
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
519
|
+
// mkstemp modifies the template to be the actual created path
|
520
|
+
fd = mkstemp(tmp_path);
|
521
|
+
if (fd > 0) break;
|
522
|
+
|
523
|
+
if (attempt == 0 && mkpath(tmp_path, 0775) < 0) {
|
512
524
|
*errno_provenance = "bs_fetch:atomic_write_cache_file:mkpath";
|
513
525
|
return -1;
|
514
526
|
}
|
515
|
-
fd = open(tmp_path, O_WRONLY | O_CREAT, 0664);
|
516
|
-
if (fd < 0) {
|
517
|
-
*errno_provenance = "bs_fetch:atomic_write_cache_file:open";
|
518
|
-
return -1;
|
519
|
-
}
|
520
527
|
}
|
528
|
+
if (fd < 0) {
|
529
|
+
*errno_provenance = "bs_fetch:atomic_write_cache_file:mkstemp";
|
530
|
+
return -1;
|
531
|
+
}
|
532
|
+
|
533
|
+
if (chmod(tmp_path, 0644) < 0) {
|
534
|
+
*errno_provenance = "bs_fetch:atomic_write_cache_file:chmod";
|
535
|
+
return -1;
|
536
|
+
}
|
537
|
+
|
521
538
|
#ifdef _WIN32
|
522
539
|
setmode(fd, O_BINARY);
|
523
540
|
#endif
|
@@ -615,7 +632,7 @@ bs_read_contents(int fd, size_t size, char ** contents, const char ** errno_prov
|
|
615
632
|
* - Return storage_to_output(storage_data)
|
616
633
|
*/
|
617
634
|
static VALUE
|
618
|
-
bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler)
|
635
|
+
bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args)
|
619
636
|
{
|
620
637
|
struct bs_cache_key cached_key, current_key;
|
621
638
|
char * contents = NULL;
|
@@ -648,7 +665,7 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler)
|
|
648
665
|
if (valid_cache) {
|
649
666
|
/* Fetch the cache data and return it if we're able to load it successfully */
|
650
667
|
res = fetch_cached_data(
|
651
|
-
cache_fd, (ssize_t)cached_key.data_size, handler,
|
668
|
+
cache_fd, (ssize_t)cached_key.data_size, handler, args,
|
652
669
|
&output_data, &exception_tag, &errno_provenance
|
653
670
|
);
|
654
671
|
if (exception_tag != 0) goto raise;
|
@@ -662,15 +679,15 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler)
|
|
662
679
|
|
663
680
|
/* Read the contents of the source file into a buffer */
|
664
681
|
if (bs_read_contents(current_fd, current_key.size, &contents, &errno_provenance) < 0) goto fail_errno;
|
665
|
-
input_data =
|
682
|
+
input_data = rb_str_new(contents, current_key.size);
|
666
683
|
|
667
684
|
/* Try to compile the input_data using input_to_storage(input_data) */
|
668
|
-
exception_tag = bs_input_to_storage(handler, input_data, path_v, &storage_data);
|
685
|
+
exception_tag = bs_input_to_storage(handler, args, input_data, path_v, &storage_data);
|
669
686
|
if (exception_tag != 0) goto raise;
|
670
687
|
/* If input_to_storage raised Bootsnap::CompileCache::Uncompilable, don't try
|
671
688
|
* to cache anything; just return input_to_output(input_data) */
|
672
689
|
if (storage_data == uncompilable) {
|
673
|
-
bs_input_to_output(handler, input_data, &output_data, &exception_tag);
|
690
|
+
bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
|
674
691
|
if (exception_tag != 0) goto raise;
|
675
692
|
goto succeed;
|
676
693
|
}
|
@@ -682,7 +699,7 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler)
|
|
682
699
|
if (res < 0) goto fail_errno;
|
683
700
|
|
684
701
|
/* Having written the cache, now convert storage_data to output_data */
|
685
|
-
exception_tag = bs_storage_to_output(handler, storage_data, &output_data);
|
702
|
+
exception_tag = bs_storage_to_output(handler, args, storage_data, &output_data);
|
686
703
|
if (exception_tag != 0) goto raise;
|
687
704
|
|
688
705
|
/* If output_data is nil, delete the cache entry and generate the output
|
@@ -692,7 +709,7 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler)
|
|
692
709
|
errno_provenance = "bs_fetch:unlink";
|
693
710
|
goto fail_errno;
|
694
711
|
}
|
695
|
-
bs_input_to_output(handler, input_data, &output_data, &exception_tag);
|
712
|
+
bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
|
696
713
|
if (exception_tag != 0) goto raise;
|
697
714
|
}
|
698
715
|
|
@@ -742,16 +759,19 @@ invalid_type_storage_data:
|
|
742
759
|
|
743
760
|
struct s2o_data {
|
744
761
|
VALUE handler;
|
762
|
+
VALUE args;
|
745
763
|
VALUE storage_data;
|
746
764
|
};
|
747
765
|
|
748
766
|
struct i2o_data {
|
749
767
|
VALUE handler;
|
768
|
+
VALUE args;
|
750
769
|
VALUE input_data;
|
751
770
|
};
|
752
771
|
|
753
772
|
struct i2s_data {
|
754
773
|
VALUE handler;
|
774
|
+
VALUE args;
|
755
775
|
VALUE input_data;
|
756
776
|
VALUE pathval;
|
757
777
|
};
|
@@ -760,15 +780,16 @@ static VALUE
|
|
760
780
|
prot_storage_to_output(VALUE arg)
|
761
781
|
{
|
762
782
|
struct s2o_data * data = (struct s2o_data *)arg;
|
763
|
-
return rb_funcall(data->handler, rb_intern("storage_to_output"),
|
783
|
+
return rb_funcall(data->handler, rb_intern("storage_to_output"), 2, data->storage_data, data->args);
|
764
784
|
}
|
765
785
|
|
766
786
|
static int
|
767
|
-
bs_storage_to_output(VALUE handler, VALUE storage_data, VALUE * output_data)
|
787
|
+
bs_storage_to_output(VALUE handler, VALUE args, VALUE storage_data, VALUE * output_data)
|
768
788
|
{
|
769
789
|
int state;
|
770
790
|
struct s2o_data s2o_data = {
|
771
791
|
.handler = handler,
|
792
|
+
.args = args,
|
772
793
|
.storage_data = storage_data,
|
773
794
|
};
|
774
795
|
*output_data = rb_protect(prot_storage_to_output, (VALUE)&s2o_data, &state);
|
@@ -776,10 +797,11 @@ bs_storage_to_output(VALUE handler, VALUE storage_data, VALUE * output_data)
|
|
776
797
|
}
|
777
798
|
|
778
799
|
static void
|
779
|
-
bs_input_to_output(VALUE handler, VALUE input_data, VALUE * output_data, int * exception_tag)
|
800
|
+
bs_input_to_output(VALUE handler, VALUE args, VALUE input_data, VALUE * output_data, int * exception_tag)
|
780
801
|
{
|
781
802
|
struct i2o_data i2o_data = {
|
782
803
|
.handler = handler,
|
804
|
+
.args = args,
|
783
805
|
.input_data = input_data,
|
784
806
|
};
|
785
807
|
*output_data = rb_protect(prot_input_to_output, (VALUE)&i2o_data, exception_tag);
|
@@ -789,18 +811,18 @@ static VALUE
|
|
789
811
|
prot_input_to_output(VALUE arg)
|
790
812
|
{
|
791
813
|
struct i2o_data * data = (struct i2o_data *)arg;
|
792
|
-
return rb_funcall(data->handler, rb_intern("input_to_output"),
|
814
|
+
return rb_funcall(data->handler, rb_intern("input_to_output"), 2, data->input_data, data->args);
|
793
815
|
}
|
794
816
|
|
795
817
|
static VALUE
|
796
818
|
try_input_to_storage(VALUE arg)
|
797
819
|
{
|
798
820
|
struct i2s_data * data = (struct i2s_data *)arg;
|
799
|
-
return rb_funcall(data->handler, rb_intern("input_to_storage"),
|
821
|
+
return rb_funcall(data->handler, rb_intern("input_to_storage"), 3, data->input_data, data->pathval, data->args);
|
800
822
|
}
|
801
823
|
|
802
824
|
static VALUE
|
803
|
-
rescue_input_to_storage(VALUE arg)
|
825
|
+
rescue_input_to_storage(VALUE arg, VALUE e)
|
804
826
|
{
|
805
827
|
return uncompilable;
|
806
828
|
}
|
@@ -816,11 +838,12 @@ prot_input_to_storage(VALUE arg)
|
|
816
838
|
}
|
817
839
|
|
818
840
|
static int
|
819
|
-
bs_input_to_storage(VALUE handler, VALUE input_data, VALUE pathval, VALUE * storage_data)
|
841
|
+
bs_input_to_storage(VALUE handler, VALUE args, VALUE input_data, VALUE pathval, VALUE * storage_data)
|
820
842
|
{
|
821
843
|
int state;
|
822
844
|
struct i2s_data i2s_data = {
|
823
845
|
.handler = handler,
|
846
|
+
.args = args,
|
824
847
|
.input_data = input_data,
|
825
848
|
.pathval = pathval,
|
826
849
|
};
|
data/lib/bootsnap.rb
CHANGED
data/lib/bootsnap/cli.rb
ADDED
@@ -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
|