diff options
| author | takahashim <[email protected]> | 2015-12-06 00:07:16 +0900 |
|---|---|---|
| committer | takahashim <[email protected]> | 2015-12-08 00:29:42 +0900 |
| commit | dd754220ce2a53f8cf44362a2b2d1f59f40e62d5 (patch) | |
| tree | 645df51d35e9932b74f6d8503c34a61670cff987 | |
| parent | 68de1e4fc5a124689e3ad975172c77071e4e63dc (diff) | |
| download | mruby-dd754220ce2a53f8cf44362a2b2d1f59f40e62d5.tar.gz mruby-dd754220ce2a53f8cf44362a2b2d1f59f40e62d5.zip | |
Fix for windows(mingw)
* File.expand_path: support drive letter and ALT_SEPARATOR
* File.dirname: support ALT_SEPARATOR
* File.basename: ditto.
* IO.popen: raise NotImplementedError
* IO.pipe: ditto.
* `cmd`: ditto.
* File#flock: ditto.
* FileTest.pipe?: ditto.
* FileTest.symlink?: ditto.
* FileTest.socket?: ditto.
| -rw-r--r-- | mrblib/file.rb | 24 | ||||
| -rw-r--r-- | mrblib/io.rb | 6 | ||||
| -rw-r--r-- | src/file.c | 43 | ||||
| -rw-r--r-- | src/file_test.c | 12 | ||||
| -rw-r--r-- | test/file.rb | 32 | ||||
| -rw-r--r-- | test/file_test.rb | 30 | ||||
| -rw-r--r-- | test/io.rb | 94 |
7 files changed, 165 insertions, 76 deletions
diff --git a/mrblib/file.rb b/mrblib/file.rb index f644ff691..86074c3e3 100644 --- a/mrblib/file.rb +++ b/mrblib/file.rb @@ -89,14 +89,21 @@ class File < IO end expanded_path = concat_path(path, default_dir) + drive_prefix = "" + if File::ALT_SEPARATOR && expanded_path.size > 2 && + ("A".."Z").include?(expanded_path[0].upcase) && expanded_path[1] == ":" + drive_prefix = expanded_path[0, 2] + expanded_path = expanded_path[2, expanded_path.size] + end expand_path_array = [] + if File::ALT_SEPARATOR && expanded_path.include?(File::ALT_SEPARATOR) + expanded_path.gsub!(File::ALT_SEPARATOR, '/') + end while expanded_path.include?('//') expanded_path = expanded_path.gsub('//', '/') end - if expanded_path == "/" - expanded_path - else + if expanded_path != "/" expanded_path.split('/').each do |path_token| if path_token == '..' if expand_path_array.size > 1 @@ -109,8 +116,15 @@ class File < IO end end - expand_path = expand_path_array.join("/") - expand_path.empty? ? '/' : expand_path + expanded_path = expand_path_array.join("/") + if expanded_path.empty? + expanded_path = '/' + end + end + if drive_prefix.empty? + expanded_path + else + drive_prefix + expanded_path.gsub("/", File::ALT_SEPARATOR) end end diff --git a/mrblib/io.rb b/mrblib/io.rb index 1742fac32..755dbbf6d 100644 --- a/mrblib/io.rb +++ b/mrblib/io.rb @@ -27,6 +27,9 @@ class IO end def self.popen(command, mode = 'r', &block) + if !self.respond_to?(:_popen) + raise NotImplementedError, "popen is not supported on this platform" + end io = self._popen(command, mode) return io unless block @@ -42,6 +45,9 @@ class IO end def self.pipe(&block) + if !self.respond_to?(:_pipe) + raise NotImplementedError, "pipe is not supported on this platform" + end if block begin r, w = IO._pipe diff --git a/src/file.c b/src/file.c index a118cf1f5..84aba39ad 100644 --- a/src/file.c +++ b/src/file.c @@ -130,17 +130,28 @@ mrb_file_s_rename(mrb_state *mrb, mrb_value obj) static mrb_value mrb_file_dirname(mrb_state *mrb, mrb_value klass) { - #if defined(_WIN32) || defined(_WIN64) +#if defined(_WIN32) || defined(_WIN64) char dname[_MAX_DIR], vname[_MAX_DRIVE]; char buffer[_MAX_DRIVE + _MAX_DIR]; char *path; + size_t ridx; mrb_value s; mrb_get_args(mrb, "S", &s); path = mrb_str_to_cstr(mrb, s); _splitpath((const char*)path, vname, dname, NULL, NULL); snprintf(buffer, _MAX_DRIVE + _MAX_DIR, "%s%s", vname, dname); + ridx = strlen(buffer); + if (ridx == 0) { + strncpy(buffer, ".", 2); /* null terminated */ + } else if (ridx > 1) { + ridx--; + while (ridx > 0 && (buffer[ridx] == '/' || buffer[ridx] == '\\')) { + buffer[ridx] = '\0'; /* remove last char */ + ridx--; + } + } return mrb_str_new_cstr(mrb, buffer); - #else +#else char *dname, *path; mrb_value s; mrb_get_args(mrb, "S", &s); @@ -149,25 +160,37 @@ mrb_file_dirname(mrb_state *mrb, mrb_value klass) if ((dname = dirname(path)) == NULL) { mrb_sys_fail(mrb, "dirname"); } - #endif +#endif return mrb_str_new_cstr(mrb, dname); } static mrb_value mrb_file_basename(mrb_state *mrb, mrb_value klass) { - #if defined(_WIN32) || defined(_WIN64) +#if defined(_WIN32) || defined(_WIN64) char bname[_MAX_DIR]; char extname[_MAX_EXT]; char *path; + size_t ridx; char buffer[_MAX_DIR + _MAX_EXT]; mrb_value s; mrb_get_args(mrb, "S", &s); path = mrb_str_to_cstr(mrb, s); + ridx = strlen(path); + if (ridx > 0) { + ridx--; + while (ridx > 0 && (path[ridx] == '/' || path[ridx] == '\\')) { + path[ridx] = '\0'; + ridx--; + } + if (strncmp(path, "/", 2) == 0) { + return mrb_str_new_cstr(mrb, path); + } + } _splitpath((const char*)path, NULL, NULL, bname, extname); snprintf(buffer, _MAX_DIR + _MAX_EXT, "%s%s", bname, extname); return mrb_str_new_cstr(mrb, buffer); - #else +#else char *bname, *path; mrb_value s; mrb_get_args(mrb, "S", &s); @@ -176,7 +199,7 @@ mrb_file_basename(mrb_state *mrb, mrb_value klass) mrb_sys_fail(mrb, "basename"); } return mrb_str_new_cstr(mrb, bname); - #endif +#endif } static mrb_value @@ -255,12 +278,11 @@ mrb_file__gethome(mrb_state *mrb, mrb_value klass) #endif } -#ifndef _WIN32 mrb_value mrb_file_flock(mrb_state *mrb, mrb_value self) { -#if defined(sun) - mrb_raise(mrb, E_RUNTIME_ERROR, "flock is not supported on Illumos/Solaris"); +#if defined(_WIN32) || defined(_WIN64) || defined(sun) + mrb_raise(mrb, E_NOTIMP_ERROR, "flock is not supported on Illumos/Solaris/Windows"); #else mrb_int operation; int fd; @@ -289,7 +311,6 @@ mrb_file_flock(mrb_state *mrb, mrb_value self) #endif return mrb_fixnum_value(0); } -#endif static mrb_value mrb_file_s_symlink(mrb_state *mrb, mrb_value klass) @@ -333,9 +354,7 @@ mrb_init_file(mrb_state *mrb) mrb_define_class_method(mrb, file, "_getwd", mrb_file__getwd, MRB_ARGS_NONE()); mrb_define_class_method(mrb, file, "_gethome", mrb_file__gethome, MRB_ARGS_OPT(1)); - #ifndef _WIN32 mrb_define_method(mrb, file, "flock", mrb_file_flock, MRB_ARGS_REQ(1)); - #endif cnst = mrb_define_module_under(mrb, file, "Constants"); mrb_define_const(mrb, cnst, "LOCK_SH", mrb_fixnum_value(LOCK_SH)); diff --git a/src/file_test.c b/src/file_test.c index 6c380c4a5..da2ef77b0 100644 --- a/src/file_test.c +++ b/src/file_test.c @@ -128,6 +128,9 @@ mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass) mrb_value mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass) { +#if defined(_WIN32) || defined(_WIN64) + mrb_raise(mrb, E_NOTIMP_ERROR, "pipe is not supported on this platform"); +#else #ifdef S_IFIFO # ifndef S_ISFIFO # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) @@ -145,6 +148,7 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass) #endif return mrb_false_value(); +#endif } /* @@ -157,6 +161,9 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass) mrb_value mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass) { +#if defined(_WIN32) || defined(_WIN64) + mrb_raise(mrb, E_NOTIMP_ERROR, "symlink is not supported on this platform"); +#else #ifndef S_ISLNK # ifdef _S_ISLNK # define S_ISLNK(m) _S_ISLNK(m) @@ -184,6 +191,7 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass) #endif return mrb_false_value(); +#endif } /* @@ -196,6 +204,9 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass) mrb_value mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass) { +#if defined(_WIN32) || defined(_WIN64) + mrb_raise(mrb, E_NOTIMP_ERROR, "socket is not supported on this platform"); +#else #ifndef S_ISSOCK # ifdef _S_ISSOCK # define S_ISSOCK(m) _S_ISSOCK(m) @@ -223,6 +234,7 @@ mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass) #endif return mrb_false_value(); +#endif } /* diff --git a/test/file.rb b/test/file.rb index ef8be37ec..ebb515cbf 100644 --- a/test/file.rb +++ b/test/file.rb @@ -56,12 +56,16 @@ end assert('IO#flock') do f = File.open $mrbtest_io_rfname - assert_equal(f.flock(File::LOCK_SH), 0) - assert_equal(f.flock(File::LOCK_UN), 0) - assert_equal(f.flock(File::LOCK_EX | File::LOCK_NB), 0) - assert_equal(f.flock(File::LOCK_UN), 0) - f.close - true + begin + assert_equal(f.flock(File::LOCK_SH), 0) + assert_equal(f.flock(File::LOCK_UN), 0) + assert_equal(f.flock(File::LOCK_EX | File::LOCK_NB), 0) + assert_equal(f.flock(File::LOCK_UN), 0) + rescue NotImplementedError => e + skip e.message + ensure + f.close + end end assert('File.join') do @@ -76,8 +80,13 @@ assert('File.join') do end assert('File.realpath') do - usrbin = IO.popen("cd bin; /bin/pwd -P") { |f| f.read.chomp } - assert_equal usrbin, File.realpath("bin") + if File.const_defined?(:ALT_SEPARATOR) && File::ALT_SEPARATOR + readme_path = File._getwd + File::ALT_SEPARATOR + "README.md" + assert_equal readme_path, File.realpath("README.md") + else + usrbin = IO.popen("cd bin; /bin/pwd -P") { |f| f.read.chomp } + assert_equal usrbin, File.realpath("bin") + end end assert('File TEST CLEANUP') do @@ -95,7 +104,12 @@ assert('File.expand_path') do assert_equal "/hoge", File.expand_path("////tmp/..///////hoge") assert_equal "/", File.expand_path("../../../..", "/") - assert_equal "/", File.expand_path(([".."] * 100).join("/")) + if File._getwd[1] == ":" + drive_letter = File._getwd[0] + assert_equal drive_letter + ":\\", File.expand_path(([".."] * 100).join("/")) + else + assert_equal "/", File.expand_path(([".."] * 100).join("/")) + end end assert('File.expand_path (with ENV)') do diff --git a/test/file_test.rb b/test/file_test.rb index 11742f2db..87db67954 100644 --- a/test/file_test.rb +++ b/test/file_test.rb @@ -6,8 +6,8 @@ assert('FileTest TEST SETUP') do end assert("FileTest.directory?") do - assert_equal true, FileTest.directory?("/tmp") - assert_equal false, FileTest.directory?("/bin/sh") + assert_equal true, FileTest.directory?(File.join(File._getwd, "mrblib")) + assert_equal false, FileTest.directory?(File.join(File._getwd, "README.md")) end assert("FileTest.exist?") do @@ -23,14 +23,18 @@ assert("FileTest.exist?") do end assert("FileTest.file?") do - assert_equal false, FileTest.file?("/tmp") - assert_equal true, FileTest.file?("/bin/sh") + assert_equal false, FileTest.file?(File.join(File._getwd, "mrblib")) + assert_equal true, FileTest.file?(File.join(File._getwd, "README.md")) end assert("FileTest.pipe?") do - io = IO.popen("ls") - assert_equal true, FileTest.pipe?(io) - assert_equal false, FileTest.pipe?("/tmp") + begin + assert_equal false, FileTest.pipe?("/tmp") + io = IO.popen("ls") + assert_equal true, FileTest.pipe?(io) + rescue NotImplementedError => e + skip e.message + end end assert('FileTest.size') do @@ -61,11 +65,19 @@ assert("FileTest.size?") do end assert("FileTest.socket?") do - assert_true FileTest.socket?($mrbtest_io_socketname) + begin + assert_true FileTest.socket?($mrbtest_io_socketname) + rescue NotImplementedError => e + skip e.message + end end assert("FileTest.symlink?") do - assert_true FileTest.symlink?($mrbtest_io_symlinkname) + begin + assert_true FileTest.symlink?($mrbtest_io_symlinkname) + rescue NotImplementedError => e + skip e.message + end end assert("FileTest.zero?") do diff --git a/test/io.rb b/test/io.rb index 5104b343c..ee0432b14 100644 --- a/test/io.rb +++ b/test/io.rb @@ -359,15 +359,19 @@ assert('IO#gets - paragraph mode') do end assert('IO.popen') do - io = IO.popen("ls") - assert_true io.close_on_exec? - assert_equal Fixnum, io.pid.class - ls = io.read - assert_equal ls.class, String - assert_include ls, 'AUTHORS' - assert_include ls, 'mrblib' - io.close - io.closed? + begin + io = IO.popen("ls") + assert_true io.close_on_exec? + assert_equal Fixnum, io.pid.class + ls = io.read + assert_equal ls.class, String + assert_include ls, 'AUTHORS' + assert_include ls, 'mrblib' + io.close + io.closed? + rescue NotImplementedError => e + skip e.message + end end assert('IO.read') do @@ -450,43 +454,51 @@ assert('IO#sysseek') do end assert('IO.pipe') do - called = false - IO.pipe do |r, w| - assert_true r.kind_of?(IO) - assert_true w.kind_of?(IO) - assert_false r.closed? - assert_false w.closed? - assert_true FileTest.pipe?(r) - assert_true FileTest.pipe?(w) - assert_nil r.pid - assert_nil w.pid - assert_true 2 < r.fileno - assert_true 2 < w.fileno - assert_true r.fileno != w.fileno - assert_false r.sync - assert_true w.sync - assert_equal 8, w.write('test for') - assert_equal 'test', r.read(4) - assert_equal ' for', r.read(4) - assert_equal 5, w.write(' pipe') - assert_equal nil, w.close - assert_equal ' pipe', r.read - called = true - assert_raise(IOError) { r.write 'test' } - # TODO: - # This assert expect raise IOError but got RuntimeError - # Because mruby-io not have flag for I/O readable - # assert_raise(IOError) { w.read } - end - assert_true called + begin + called = false + IO.pipe do |r, w| + assert_true r.kind_of?(IO) + assert_true w.kind_of?(IO) + assert_false r.closed? + assert_false w.closed? + assert_true FileTest.pipe?(r) + assert_true FileTest.pipe?(w) + assert_nil r.pid + assert_nil w.pid + assert_true 2 < r.fileno + assert_true 2 < w.fileno + assert_true r.fileno != w.fileno + assert_false r.sync + assert_true w.sync + assert_equal 8, w.write('test for') + assert_equal 'test', r.read(4) + assert_equal ' for', r.read(4) + assert_equal 5, w.write(' pipe') + assert_equal nil, w.close + assert_equal ' pipe', r.read + called = true + assert_raise(IOError) { r.write 'test' } + # TODO: + # This assert expect raise IOError but got RuntimeError + # Because mruby-io not have flag for I/O readable + # assert_raise(IOError) { w.read } + end + assert_true called - assert_nothing_raised do - IO.pipe { |r, w| r.close; w.close } + assert_nothing_raised do + IO.pipe { |r, w| r.close; w.close } + end + rescue NotImplementedError => e + skip e.message end end assert('`cmd`') do - assert_equal `echo foo`, "foo\n" + begin + assert_equal `echo foo`, "foo\n" + rescue NotImplementedError => e + skip e.message + end end assert('IO TEST CLEANUP') do |
