From 06bb54d38065c35872d3c6e4e139521af527f05f Mon Sep 17 00:00:00 2001 From: dearblue Date: Sat, 7 Dec 2024 22:32:05 +0900 Subject: [PATCH 1/2] Improved `File.expand_path` test in `mruby-io Since `mruby-io` does not depend on `mruby-env` even for test builds, it is impossible that `ENV` constants are defined. Therefore, define `MRubyIOTestUtil::ENV_HOME` for alternative use. --- mrbgems/mruby-io/test/file.rb | 10 +++++----- mrbgems/mruby-io/test/mruby_io_test.c | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/mrbgems/mruby-io/test/file.rb b/mrbgems/mruby-io/test/file.rb index 5746986ad..465135185 100644 --- a/mrbgems/mruby-io/test/file.rb +++ b/mrbgems/mruby-io/test/file.rb @@ -210,13 +210,13 @@ assert('File.expand_path') do end end -assert('File.expand_path (with ENV)') do - skip unless Object.const_defined?(:ENV) && ENV['HOME'] +assert('File.expand_path (with getenv(3))') do + skip unless MRubyIOTestUtil.const_defined?(:ENV_HOME) - assert_equal ENV['HOME'], File.expand_path("~/"), "home" - assert_equal ENV['HOME'], File.expand_path("~/", "/"), "home with base_dir" + assert_equal MRubyIOTestUtil::ENV_HOME, File.expand_path("~/"), "home" + assert_equal MRubyIOTestUtil::ENV_HOME, File.expand_path("~/", "/"), "home with base_dir" - assert_equal "#{ENV['HOME']}/user", File.expand_path("user", ENV['HOME']), "relative with base_dir" + assert_equal "#{MRubyIOTestUtil::ENV_HOME}/user", File.expand_path("user", MRubyIOTestUtil::ENV_HOME), "relative with base_dir" end assert('File.path') do diff --git a/mrbgems/mruby-io/test/mruby_io_test.c b/mrbgems/mruby-io/test/mruby_io_test.c index c1ff0f8f0..1b54a4438 100644 --- a/mrbgems/mruby-io/test/mruby_io_test.c +++ b/mrbgems/mruby-io/test/mruby_io_test.c @@ -243,4 +243,26 @@ mrb_mruby_io_gem_test(mrb_state* mrb) mrb_define_class_method(mrb, io_test, "win?", mrb_io_win_p, MRB_ARGS_NONE()); mrb_define_const(mrb, io_test, "MRB_WITH_IO_PREAD_PWRITE", mrb_bool_value(MRB_WITH_IO_PREAD_PWRITE_ENABLED)); + + const char *env_home = getenv("HOME"); +#ifdef _WIN32 + if (!env_home) { + env_home = getenv("USERPROFILE"); + } +#endif + if (env_home) { + char *utf8 = mrb_utf8_from_locale(env_home, strlen(env_home)); + mrb_value path = mrb_str_new_cstr(mrb, utf8); +#ifdef _WIN32 + char *pathp = RSTRING_PTR(path); + const char *const pathend = pathp + RSTRING_LEN(path); + for (;;) { + pathp = memchr(pathp, '\\', pathend - pathp); + if (!pathp) break; + *pathp++ = '/'; + } +#endif + mrb_define_const(mrb, io_test, "ENV_HOME", path); + mrb_utf8_free(utf8); + } } From 88e3ce1b5888d3fd1cc53d14621ac5eddffb0fed Mon Sep 17 00:00:00 2001 From: dearblue Date: Sat, 7 Dec 2024 22:35:23 +0900 Subject: [PATCH 2/2] Fix `File.expand_path` for Windows - The inner method `File._gethome` could be read as intending to use the `USERPROFILE` environment variable instead on Windows when the `HOME` environment variable is not available. In reality, however, this was not the case. - The result of `File.expand_path` should unify path separators with `/`, but it did not. --- mrbgems/mruby-io/mrblib/file.rb | 2 +- mrbgems/mruby-io/src/file.c | 18 +++++++++++++----- mrbgems/mruby-io/test/file.rb | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/mrbgems/mruby-io/mrblib/file.rb b/mrbgems/mruby-io/mrblib/file.rb index 719f4e629..e5594ca50 100644 --- a/mrbgems/mruby-io/mrblib/file.rb +++ b/mrbgems/mruby-io/mrblib/file.rb @@ -149,7 +149,7 @@ class File < IO if drive_prefix.empty? expanded_path else - drive_prefix + expanded_path.gsub("/", File::ALT_SEPARATOR) + drive_prefix + expanded_path end end diff --git a/mrbgems/mruby-io/src/file.c b/mrbgems/mruby-io/src/file.c index 4d744eb48..7afc2de10 100644 --- a/mrbgems/mruby-io/src/file.c +++ b/mrbgems/mruby-io/src/file.c @@ -345,15 +345,14 @@ mrb_file__gethome(mrb_state *mrb, mrb_value klass) mrb_int argc = mrb_get_args(mrb, "|S", &username); if (argc == 0) { home = getenv("HOME"); - if (home == NULL) { - return mrb_nil_value(); - } #ifdef _WIN32 - home = getenv("USERPROFILE"); if (home == NULL) { - return mrb_nil_value(); + home = getenv("USERPROFILE"); } #endif + if (home == NULL) { + return mrb_nil_value(); + } if (!mrb_file_is_absolute_path(home)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "non-absolute home"); } @@ -378,6 +377,15 @@ mrb_file__gethome(mrb_state *mrb, mrb_value klass) home = mrb_utf8_from_locale(home, -1); path = mrb_str_new_cstr(mrb, home); mrb_utf8_free(home); +#ifdef _WIN32 + char *pathp = RSTRING_PTR(path); + const char *const pathend = pathp + RSTRING_LEN(path); + for (;;) { + pathp = memchr(pathp, '\\', pathend - pathp); + if (!pathp) break; + *pathp++ = '/'; + } +#endif return path; } diff --git a/mrbgems/mruby-io/test/file.rb b/mrbgems/mruby-io/test/file.rb index 465135185..07e32b325 100644 --- a/mrbgems/mruby-io/test/file.rb +++ b/mrbgems/mruby-io/test/file.rb @@ -204,7 +204,7 @@ assert('File.expand_path') do assert_equal "/", File.expand_path("../../../..", "/") if File._getwd[1] == ":" drive_letter = File._getwd[0] - assert_equal drive_letter + ":\\", File.expand_path(([".."] * 100).join("/")) + assert_equal drive_letter + ":/", File.expand_path(([".."] * 100).join("/")) else assert_equal "/", File.expand_path(([".."] * 100).join("/")) end