diff --git a/.github/workflows/check_sast.yml b/.github/workflows/check_sast.yml
index 34cf7e4b9b7a44..669261535b13a0 100644
--- a/.github/workflows/check_sast.yml
+++ b/.github/workflows/check_sast.yml
@@ -78,14 +78,14 @@ jobs:
persist-credentials: false
- name: Initialize CodeQL
- uses: github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
+ uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
with:
languages: ${{ matrix.language }}
build-mode: none
config-file: .github/codeql/codeql-config.yml
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
+ uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
with:
category: '/language:${{ matrix.language }}'
upload: False
@@ -127,7 +127,7 @@ jobs:
continue-on-error: true
- name: Upload SARIF
- uses: github/codeql-action/upload-sarif@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
+ uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
with:
sarif_file: sarif-results/${{ matrix.language }}.sarif
continue-on-error: true
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index 6a2f162b3a9c56..8f3ed45b13cb0f 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -73,6 +73,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
+ uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
with:
sarif_file: results.sarif
diff --git a/.github/workflows/zjit-macos.yml b/.github/workflows/zjit-macos.yml
index 85688e3024946c..feb8c462890303 100644
--- a/.github/workflows/zjit-macos.yml
+++ b/.github/workflows/zjit-macos.yml
@@ -98,7 +98,7 @@ jobs:
rustup install ${{ matrix.rust_version }} --profile minimal
rustup default ${{ matrix.rust_version }}
- - uses: taiki-e/install-action@b6ff580856c41316412a0b9b60540fbc6f8c82cc # v2.86.7
+ - uses: taiki-e/install-action@37f7c5781271959fb65b6b35224e28652ff2b63d # v2.87.0
with:
tool: nextest@0.9
if: ${{ matrix.test_task == 'zjit-check' }}
diff --git a/.github/workflows/zjit-ubuntu.yml b/.github/workflows/zjit-ubuntu.yml
index b8f64735891d9c..9623059e035e18 100644
--- a/.github/workflows/zjit-ubuntu.yml
+++ b/.github/workflows/zjit-ubuntu.yml
@@ -152,7 +152,7 @@ jobs:
ruby-version: '3.1'
bundler: none
- - uses: taiki-e/install-action@b6ff580856c41316412a0b9b60540fbc6f8c82cc # v2.86.7
+ - uses: taiki-e/install-action@37f7c5781271959fb65b6b35224e28652ff2b63d # v2.87.0
with:
tool: nextest@0.9
if: ${{ matrix.test_task == 'zjit-check' }}
diff --git a/.gitignore b/.gitignore
index b49185e46879c1..1ea0a323d92558 100644
--- a/.gitignore
+++ b/.gitignore
@@ -88,12 +88,10 @@ lcov*.info
/config.status
/config.status.lineno
/configure
-/coverage/simplecov
-/coverage/simplecov-html
-/coverage/doclie
/coverage/.last_run.json
+/coverage/.report_stamp
/coverage/.resultset.json*
-/coverage/assets
+/coverage/coverage.json
/coverage/index.html
/doc/capi
/enc.mk
diff --git a/box.c b/box.c
index 9121ba003d6ada..559170c7a452ce 100644
--- a/box.c
+++ b/box.c
@@ -11,6 +11,7 @@
#include "internal/hash.h"
#include "internal/io.h"
#include "internal/load.h"
+#include "internal/random.h"
#include "internal/st.h"
#include "internal/variable.h"
#include "iseq.h"
@@ -47,12 +48,16 @@ static rb_box_gem_flags_t box_gem_flags[1];
static char *tmp_dir;
static bool tmp_dir_has_dirsep;
-#define BOX_TMP_PREFIX "_ruby_box_"
-
#ifndef MAXPATHLEN
# define MAXPATHLEN 1024
#endif
+/* process-private 0700 directory for box-local copies of extensions */
+static char box_ext_tmp_dir[MAXPATHLEN];
+static unsigned long box_ext_seq;
+
+#define BOX_TMP_PREFIX "_ruby_box_"
+
#if defined(_WIN32)
# define DIRSEP "\\"
#else
@@ -560,13 +565,40 @@ system_tmpdir(void)
/* end of copy */
-static int
-sprint_ext_filename(char *str, size_t size, long box_id, const char *prefix, const char *basename)
+/* Box-local copies of extensions are placed in a process-private 0700
+ * directory with an unpredictable name, so that other local users cannot
+ * occupy the copy destination in a shared TMPDIR [Bug #22110], and so
+ * that the file name of each copy stays short regardless of the depth of
+ * the original path (a full path flattened into a single file name can
+ * exceed NAME_MAX). */
+static void
+ensure_box_ext_tmp_dir(void)
{
- if (tmp_dir_has_dirsep) {
- return snprintf(str, size, "%s%sp%"PRI_PIDT_PREFIX"u_%ld_%s", tmp_dir, prefix, getpid(), box_id, basename);
+ if (box_ext_tmp_dir[0]) return;
+
+ int last_errno = 0;
+ for (int retry = 0; retry < 10; retry++) {
+ char path[MAXPATHLEN];
+ uint64_t suffix;
+ if (ruby_fill_random_bytes(&suffix, sizeof(suffix), FALSE) != 0) {
+ /* no random source; mkdir(0700) below still refuses hijacked names */
+ suffix = (uint64_t)(uintptr_t)&suffix ^ (uint64_t)retry;
+ }
+ int wrote = snprintf(path, sizeof(path), "%s%s%sp%"PRI_PIDT_PREFIX"u_%.16"PRIx64,
+ tmp_dir, tmp_dir_has_dirsep ? "" : DIRSEP,
+ BOX_TMP_PREFIX, getpid(), suffix);
+ if (wrote >= (int)sizeof(path)) {
+ rb_raise(rb_eLoadError, "TMPDIR for Ruby Box extensions is too long: %s", tmp_dir);
+ }
+ if (mkdir(path, 0700) == 0) {
+ strlcpy(box_ext_tmp_dir, path, sizeof(box_ext_tmp_dir));
+ return;
+ }
+ last_errno = errno;
+ if (last_errno != EEXIST) break;
}
- return snprintf(str, size, "%s%s%sp%"PRI_PIDT_PREFIX"u_%ld_%s", tmp_dir, DIRSEP, prefix, getpid(), box_id, basename);
+ rb_raise(rb_eLoadError, "can't create the temporary directory for Ruby Box extensions under %s: %s",
+ tmp_dir, strerror(last_errno));
}
enum copy_error_type {
@@ -738,41 +770,14 @@ copy_ext_file(const char *src_path, const char *dst_path)
#define isdirsep(x) ((x) == '/')
#endif
-#define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0)
-#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)
-
-static void
-fname_without_suffix(const char *fname, char *rvalue, size_t rsize)
-{
- size_t len = strlen(fname);
- const char *pos;
- for (pos = fname + len; pos > fname; pos--) {
- if (IS_SOEXT(pos) || IS_DLEXT(pos)) {
- len = pos - fname;
- break;
- }
- if (fname + len - pos > DLEXT_MAXLEN) break;
- }
- if (len > rsize - 1) len = rsize - 1;
- memcpy(rvalue, fname, len);
- rvalue[len] = '\0';
-}
-
-static void
-escaped_basename(const char *path, const char *fname, char *rvalue, size_t rsize)
+static const char *
+ext_basename(const char *path)
{
- char *pos;
- const char *leaf = path, *found;
- // `leaf + 1` looks uncomfortable (when leaf == path), but fname must not be the top-dir itself
- while ((found = strstr(leaf + 1, fname)) != NULL) {
- leaf = found; // find the last occurrence for the path like /etc/my-crazy-lib-dir/etc.so
- }
- strlcpy(rvalue, leaf, rsize);
- for (pos = rvalue; *pos; pos++) {
- if (isdirsep(*pos)) {
- *pos = '+';
- }
+ const char *base = path;
+ for (const char *pos = path; *pos; pos++) {
+ if (isdirsep(*pos)) base = pos + 1;
}
+ return base;
}
static void
@@ -847,22 +852,25 @@ rb_box_unload_local_extensions(void)
ext = next;
}
#endif
+ if (box_ext_tmp_dir[0]) {
+ rmdir(box_ext_tmp_dir);
+ box_ext_tmp_dir[0] = '\0';
+ }
}
VALUE
-rb_box_local_extension(VALUE box_value, VALUE fname, VALUE path, VALUE *cleanup)
+rb_box_local_extension(VALUE box_value, VALUE path, VALUE *cleanup)
{
- char ext_path[MAXPATHLEN], fname2[MAXPATHLEN], basename[MAXPATHLEN];
+ char ext_path[MAXPATHLEN];
int wrote;
- const char *src_path = RSTRING_PTR(path), *fname_ptr = RSTRING_PTR(fname);
+ const char *src_path = RSTRING_PTR(path);
rb_box_t *box = rb_get_box_t(box_value);
- fname_without_suffix(fname_ptr, fname2, sizeof(fname2));
- escaped_basename(src_path, fname2, basename, sizeof(basename));
-
- wrote = sprint_ext_filename(ext_path, sizeof(ext_path), box->box_id, BOX_TMP_PREFIX, basename);
+ ensure_box_ext_tmp_dir();
+ wrote = snprintf(ext_path, sizeof(ext_path), "%s%s%ld_%lu_%s",
+ box_ext_tmp_dir, DIRSEP, box->box_id, box_ext_seq++, ext_basename(src_path));
if (wrote >= (int)sizeof(ext_path)) {
- rb_bug("Extension file path in the box was too long");
+ rb_raise(rb_eLoadError, "extension file path in the box is too long: %"PRIsVALUE, path);
}
VALUE new_path = rb_str_new_cstr(ext_path);
*cleanup = TypedData_Wrap_Struct(0, &box_ext_cleanup_type, NULL);
diff --git a/common.mk b/common.mk
index 68c0e1e33587fa..fcf64566f5c1e4 100644
--- a/common.mk
+++ b/common.mk
@@ -1537,7 +1537,7 @@ update-config_files: PHONY
update-coverage: main PHONY
$(XRUBY) -C "$(srcdir)" bin/gem install --no-document \
- --install-dir .bundle --conservative "simplecov"
+ --install-dir .bundle --conservative "simplecov" -v "~> 1.1"
refresh-gems: update-bundled_gems prepare-gems
# can't recall exactly, but `make` somewhere (not GNU or nmake)
diff --git a/coverage/README b/coverage/README
index a4c3dfcb039400..a69efd9da2a5ef 100644
--- a/coverage/README
+++ b/coverage/README
@@ -13,5 +13,4 @@ Limitation
TODO
- * more reduce bundled simplecov(additional configuration, formatter, etc.)
* measure rubyspec coverage
diff --git a/file.c b/file.c
index 995111e89d88a7..526c6efd338032 100644
--- a/file.c
+++ b/file.c
@@ -2023,13 +2023,22 @@ rb_file_chardev_p(VALUE obj, VALUE fname)
/*
* call-seq:
- * File.exist?(file_name) -> true or false
+ * File.exist?(object) -> true or false
*
- * Return true if the named file exists.
+ * Return whether the specified +object+, a string path or IO object, exists:
*
- * _file_name_ can be an IO object.
+ * # String paths.
+ * File.exist?('README.md') # => true
+ * File.exist?('.') # => true
+ * filepath = 't.tmp'
+ * File.exist?(filepath) # => false
+ * File.write(filepath, 'foo')
+ * File.exist?(filepath) # => true
+ * # File (IO object).
+ * file = File.new(filepath)
+ * File.exist?(file) # => true
+ * file.close # Clean up.
*
- * "file exists" means that stat() or fstat() system call is successful.
*/
static VALUE
@@ -2179,17 +2188,36 @@ rb_file_world_writable_p(VALUE obj, VALUE fname)
/*
* call-seq:
- * File.executable?(file_name) -> true or false
+ * File.executable?(path) -> true or false
*
- * Returns true if the named file is executable by the effective
- * user and group id of this process. See eaccess(3).
+ * Returns whether the filesystem entry at the given string +path+
+ * exists and is executable.
*
- * Windows does not support execute permissions separately from read
- * permissions. On Windows, a file is only considered executable if it ends in
- * .bat, .cmd, .com, or .exe.
+ * On Windows, the entry is executable if its path has file extension
+ * +.bat+, +.cmd+, +.com+, or +.exe+:
*
- * Note that some OS-level security features may cause this to return true
- * even though the file is not executable by the effective user/group.
+ * File.executable?('win32/rtname.cmd') # => true
+ * File.executable?('win32/rtname') # => false
+ * File.executable?('win32/nosuch.cmd') # => false
+ *
+ * On other systems, the entry is executable if it has the execute/search
+ * permission for the effective user and group id of the current process;
+ * see {Permissions}[rdoc-ref:file/filesystem_modes.md@Permissions].
+ *
+ * These examples use
+ * a {helper method}[rdoc-ref:file/filesystem_modes.md@Helper+Method], +mode+,
+ * that displays a mode both in octal digits and in characters:
+ *
+ * File.executable?('.') # => true
+ * mode('.') # => "040775 drwxrwxr-x"
+ * File.executable?('bin/gem') # => true
+ * mode('bin/gem') # => "100775 -rwxrwxr-x"
+ * File.executable?('/etc/passwd') # => false
+ * mode('/etc/passwd') # => "100644 -rw-r--r--"
+ * File.executable?('nosuch') # => false
+ *
+ * Note that some filesystem settings may cause this method to return +true+
+ * even though the entry is not executable by the effective user/group.
*/
static VALUE
diff --git a/hash.c b/hash.c
index 172ed3bd49a502..2686b913c3381a 100644
--- a/hash.c
+++ b/hash.c
@@ -1941,7 +1941,8 @@ rb_hash_init(rb_execution_context_t *ec, VALUE hash, VALUE capa_value, VALUE ifn
if (capa_value != INT2FIX(0)) {
long capa = NUM2LONG(capa_value);
- if (capa > 0 && RHASH_AR_TABLE_P(hash) && RHASH_SIZE(hash) == 0 && capa > RHASH_AR_TABLE_MAX_BOUND(hash)) {
+ if (capa > 0 && RHASH_AR_TABLE_P(hash) && RHASH_SIZE(hash) == 0 &&
+ (unsigned long)capa > RHASH_AR_TABLE_MAX_BOUND(hash)) {
hash_st_table_init(hash, capa);
}
}
diff --git a/internal/box.h b/internal/box.h
index fa01a47307ed66..b5ebc2c3d2c185 100644
--- a/internal/box.h
+++ b/internal/box.h
@@ -88,7 +88,7 @@ void rb_box_gc_update_references(void *ptr);
rb_box_t * rb_get_box_t(VALUE ns);
VALUE rb_get_box_object(rb_box_t *ns);
-VALUE rb_box_local_extension(VALUE box, VALUE fname, VALUE path, VALUE *cleanup);
+VALUE rb_box_local_extension(VALUE box, VALUE path, VALUE *cleanup);
void rb_box_cleanup_local_extension(VALUE cleanup);
void rb_box_defer_unload_local_extension(void *handle);
void rb_box_unload_local_extensions(void);
diff --git a/load.c b/load.c
index c10de25a45e3b6..ecc3da22597d50 100644
--- a/load.c
+++ b/load.c
@@ -1218,7 +1218,7 @@ load_ext(VALUE path, VALUE fname)
const rb_box_t *box = rb_loading_box();
VALUE cleanup = 0;
if (BOX_USER_P(box)) {
- loaded = rb_box_local_extension(box->box_object, fname, path, &cleanup);
+ loaded = rb_box_local_extension(box->box_object, path, &cleanup);
}
rb_scope_visibility_set(METHOD_VISI_PUBLIC);
void *handle = dln_load_feature(RSTRING_PTR(loaded), RSTRING_PTR(fname));
diff --git a/spec/bundler/spec_helper.rb b/spec/bundler/spec_helper.rb
index f4030e70a6fa16..e39c75aa61f5d5 100644
--- a/spec/bundler/spec_helper.rb
+++ b/spec/bundler/spec_helper.rb
@@ -43,30 +43,27 @@
begin
raise LoadError if File.exist?(File.expand_path("../../lib/bundler/bundler.gemspec", __dir__))
- gem "simplecov_json_formatter"
require "simplecov"
SimpleCov.start do
command_name "bundler:#{Process.pid}"
- root File.expand_path("../bundler", __dir__)
+ root File.expand_path("..", __dir__)
coverage_dir File.expand_path("../coverage", __dir__)
- add_filter "/spec/"
- add_filter "/test/"
- add_filter "/lib/rubygems/"
- add_filter "/lib/bundler/vendor/"
- add_filter "/tool/"
- add_filter "/tmp/"
- add_filter ".gemspec"
+ skip "/spec/"
+ skip "/test/"
+ skip "/lib/rubygems/"
+ skip "/lib/bundler/vendor/"
+ skip "/tool/"
+ skip "/tmp/"
+ skip ".gemspec"
end
SimpleCov.print_error_status = false
- SimpleCov.at_exit do
- $stdout = File.open(File::NULL, "w")
- SimpleCov.result.format!
- ensure
- $stdout = STDOUT
- end
+
+ # Only merge this process result into the resultset. Parallel workers share a
+ # coverage directory, so the report is formatted once by `rake coverage:report`.
+ SimpleCov.at_exit { SimpleCov.result }
rescue LoadError
# SimpleCov is not installed
end
diff --git a/test/ruby/test_box.rb b/test/ruby/test_box.rb
index 43f13494de3782..5491578e9fb303 100644
--- a/test/ruby/test_box.rb
+++ b/test/ruby/test_box.rb
@@ -1279,6 +1279,28 @@ def test_loaded_extension_deleted_in_user_box
end
end
+ def test_loading_extension_from_deep_path_in_user_box
+ require 'date'
+ dlext = RbConfig::CONFIG['DLEXT']
+ src = $LOADED_FEATURES.find {|f| f.end_with?("date_core.#{dlext}")}
+ omit "date_core.#{dlext} is not loaded dynamically" unless src && File.exist?(src)
+
+ require 'tmpdir'
+ require 'fileutils'
+ Dir.mktmpdir do |tmpdir|
+ # deep enough that this path flattened into a single file name exceeds NAME_MAX
+ deep = File.join(tmpdir, "d" * 90, "e" * 90, "f" * 90)
+ FileUtils.mkdir_p(deep)
+ FileUtils.cp(src, deep)
+ env = ENV_ENABLE_BOX.merge({'BOX_TEST_EXT_FEATURE'=>File.join(deep, "date_core")})
+ assert_ruby_status([env], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ require ENV['BOX_TEST_EXT_FEATURE'] or raise "already loaded"
+ raise "Date is not defined" unless defined?(Date)
+ end;
+ end
+ end
+
def test_root_box_iclasses_should_be_boxable
assert_separately([ENV_ENABLE_BOX], __FILE__, __LINE__, "#{<<~"begin;"}\n#{<<~'end;'}", ignore_stderr: true)
begin;
diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb
index 73e109796a7ba5..1fe8577b4fc94b 100644
--- a/test/rubygems/helper.rb
+++ b/test/rubygems/helper.rb
@@ -5,7 +5,6 @@
begin
raise LoadError if ENV["GEM_COMMAND"]
- gem "simplecov_json_formatter"
require "simplecov"
unless ENV["SIMPLECOV_SUBPROCESS"]
@@ -14,11 +13,11 @@
root File.expand_path("../..", __dir__)
coverage_dir File.expand_path("../../coverage", __dir__)
- add_filter "/test/"
- add_filter "/bundler/"
- add_filter "/tool/"
- add_filter "/lib/rubygems/vendor/"
- add_filter ".gemspec"
+ skip "/test/"
+ skip "/bundler/"
+ skip "/tool/"
+ skip "/lib/rubygems/vendor/"
+ skip ".gemspec"
end
# Prevent SimpleCov from running in subprocesses spawned by assert_separately
diff --git a/tool/bundler/dev_gems.rb b/tool/bundler/dev_gems.rb
index c8e4d5345c4297..7dc32f80e00c20 100644
--- a/tool/bundler/dev_gems.rb
+++ b/tool/bundler/dev_gems.rb
@@ -14,7 +14,7 @@
gem "rspec-expectations", "~> 3.12"
gem "rspec-mocks", "~> 3.12"
gem "rubygems-generate_index", "~> 1.1"
-gem "simplecov", "~> 0.22"
+gem "simplecov", "~> 1.1"
group :doc do
gem "ronn-ng", "~> 0.10.1", platform: :ruby
diff --git a/tool/bundler/dev_gems.rb.lock b/tool/bundler/dev_gems.rb.lock
index ee91c8baffd35f..72916fb1e1d95f 100644
--- a/tool/bundler/dev_gems.rb.lock
+++ b/tool/bundler/dev_gems.rb.lock
@@ -3,7 +3,6 @@ GEM
specs:
compact_index (0.15.0)
diff-lcs (1.6.2)
- docile (1.4.1)
kramdown (2.5.2)
rexml (>= 3.4.4)
kramdown-parser-gfm (1.1.0)
@@ -58,12 +57,7 @@ GEM
rspec-support (3.13.7)
rubygems-generate_index (1.1.3)
compact_index (~> 0.15.0)
- simplecov (0.22.0)
- docile (~> 1.1)
- simplecov-html (~> 0.11)
- simplecov_json_formatter (~> 0.1)
- simplecov-html (0.13.2)
- simplecov_json_formatter (0.1.4)
+ simplecov (1.1.1)
test-unit (3.7.7)
power_assert
test-unit-ruby-core (1.0.14)
@@ -96,7 +90,7 @@ DEPENDENCIES
rspec-expectations (~> 3.12)
rspec-mocks (~> 3.12)
rubygems-generate_index (~> 1.1)
- simplecov (~> 0.22)
+ simplecov (~> 1.1)
test-unit (~> 3.0)
test-unit-ruby-core
turbo_tests (~> 2.2.3)
@@ -104,7 +98,6 @@ DEPENDENCIES
CHECKSUMS
compact_index (0.15.0) sha256=5c6c404afca8928a7d9f4dde9524f6e1610db17e675330803055db282da84a8b
diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962
- docile (1.4.1) sha256=96159be799bfa73cdb721b840e9802126e4e03dfc26863db73647204c727f21e
kramdown (2.5.2) sha256=1ba542204c66b6f9111ff00dcc26075b95b220b07f2905d8261740c82f7f02fa
kramdown-parser-gfm (1.1.0) sha256=fb39745516427d2988543bf01fc4cf0ab1149476382393e0e9c48592f6581729
mini_portile2 (2.8.9) sha256=0cd7c7f824e010c072e33f68bc02d85a00aeb6fce05bb4819c03dfd3c140c289
@@ -133,9 +126,7 @@ CHECKSUMS
rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47
rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
rubygems-generate_index (1.1.3) sha256=3571424322666598e9586a906485e1543b617f87644913eaf137d986a3393f5c
- simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5
- simplecov-html (0.13.2) sha256=bd0b8e54e7c2d7685927e8d6286466359b6f16b18cb0df47b508e8d73c777246
- simplecov_json_formatter (0.1.4) sha256=529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428
+ simplecov (1.1.1) sha256=25825ef13f0b2e74694d769817dad6ab8e90131dabdaa666e522fea105521e78
test-unit (3.7.7) sha256=3c89d5ff0690a16bef9946156c4624390402b9d54dfcf4ce9cbd5b06bead1e45
test-unit-ruby-core (1.0.14) sha256=d2e997796c9c5c5e8e31ac014f83a473ff5c2523a67cfa491b08893e12d43d22
turbo_tests (2.2.5) sha256=3fa31497d12976d11ccc298add29107b92bda94a90d8a0a5783f06f05102509f
diff --git a/tool/test-coverage.rb b/tool/test-coverage.rb
index 28ef0bf7f8ce21..4e321213c61edf 100644
--- a/tool/test-coverage.rb
+++ b/tool/test-coverage.rb
@@ -72,11 +72,8 @@ def save_coverage_data(res1)
end
def invoke_simplecov_formatter
- # XXX docile-x.y.z and simplecov-x.y.z, simplecov-html-x.y.z, simplecov_json_formatter-x.y.z
- %w[simplecov simplecov-html simplecov_json_formatter docile].each do |f|
- Dir.glob("#{__dir__}/../.bundle/gems/#{f}-*/lib").each do |d|
- $LOAD_PATH.unshift d
- end
+ Dir.glob("#{__dir__}/../.bundle/gems/simplecov-*/lib").each do |d|
+ $LOAD_PATH.unshift d
end
require "simplecov"