Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: eb3d106ab84a^
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 24e246dd1270
Choose a head ref

Commits on Mar 3, 2016

  1. Copy the full SHA
    eb3d106 View commit details
  2. Copy the full SHA
    b5e0310 View commit details
  3. Copy the full SHA
    9fa185b View commit details
  4. Copy the full SHA
    79d923e View commit details
  5. Copy the full SHA
    fdefbcf View commit details
  6. Windows will explicitly set JVM file.encoding to UTF-8 so MRI tests e…

    …xecute more consistently
    enebo committed Mar 3, 2016
    Copy the full SHA
    165a83a View commit details
  7. Copy the full SHA
    7254caf View commit details

Commits on Mar 4, 2016

  1. Copy the full SHA
    8395657 View commit details

Commits on Mar 5, 2016

  1. Revert "Update to RubyGems 2.6.1. Fixes #3631."

    This reverts commit 8395657.
    headius committed Mar 5, 2016
    Copy the full SHA
    765042f View commit details

Commits on Mar 8, 2016

  1. Copy the full SHA
    cb99e74 View commit details
  2. add mavengem repo

    mkristian committed Mar 8, 2016
    Copy the full SHA
    c356709 View commit details
  3. Revert "add mavengem repo"

    This reverts commit c356709.
    mkristian committed Mar 8, 2016
    Copy the full SHA
    b044f15 View commit details
  4. Copy the full SHA
    137cb39 View commit details

Commits on Mar 9, 2016

  1. Copy the full SHA
    5cf7975 View commit details
  2. Copy the full SHA
    80daa93 View commit details
  3. Copy the full SHA
    ab20ef5 View commit details
  4. We need to use forward slashes in test if we are embedding that path …

    …into a ruby script on Windows
    enebo committed Mar 9, 2016
    Copy the full SHA
    bc7de11 View commit details
  5. Some hinky env magic so these tests run on windows from CLI and from …

    …IDE. The logic on windows ends up being different from MacOS too...bleh
    enebo committed Mar 9, 2016
    Copy the full SHA
    ade7d56 View commit details
  6. Copy the full SHA
    88cd8a5 View commit details
  7. Copy the full SHA
    485b42e View commit details
  8. Revert last change

    enebo committed Mar 9, 2016
    Copy the full SHA
    49f84a4 View commit details

Commits on Mar 10, 2016

  1. Copy the full SHA
    8fc8d87 View commit details
  2. Copy the full SHA
    9851e84 View commit details
  3. Copy the full SHA
    1e78fdf View commit details
  4. Copy the full SHA
    8097d27 View commit details

Commits on Mar 11, 2016

  1. Copy the full SHA
    12fd533 View commit details
  2. Remove 64 bit windows from CI for now since some tests fail from bad …

    …quoting in jruby-launcher (JRUBY #3725)
    enebo committed Mar 11, 2016
    Copy the full SHA
    fed46bd View commit details
  3. Update for jnr updates

    enebo committed Mar 11, 2016
    Copy the full SHA
    cb7dde3 View commit details
  4. Copy the full SHA
    0809846 View commit details
  5. Add failing windows test

    enebo committed Mar 11, 2016
    Copy the full SHA
    4ecc4c7 View commit details
  6. Copy the full SHA
    0cb9dc2 View commit details
  7. Fixes #3727. Tempfile#open on windows unconditionally opens in b mode…

    … messing CRLF logic (--1.9)
    enebo committed Mar 11, 2016
    Copy the full SHA
    a678e5e View commit details

Commits on Mar 15, 2016

  1. Lots of tagging

    enebo committed Mar 15, 2016
    Copy the full SHA
    0eb7422 View commit details

Commits on Mar 16, 2016

  1. Copy the full SHA
    18121a7 View commit details

Commits on Mar 17, 2016

  1. Fixes #3278: File.open w/ File::RDWR should write \r\n but gets should

    read as \n after rewind on windows.
    
    We were missing some windows-specific logic in needsWriteConversion.  With
    this change I get three more specs passing and no regression on MRI test
    suite.  SHIP IT...
    enebo committed Mar 17, 2016
    Copy the full SHA
    4496cff View commit details

Commits on Mar 18, 2016

  1. Fixes #3745. IO#block_nonwrite causes CCE on Windows.

    I made a marker interface so that both ChannelStream and CRLFStream
    wrapper can have a common type so they can call writenonblock.  I added
    an error check to throw and IOException if CRLFStreamWrapper is wrapping
    from stream type but I suspect it is an impossible path by this point in
    our code.  Zero 1.7 risk fix since this was just dumping stack before.
    enebo committed Mar 18, 2016
    Copy the full SHA
    3eb8c5f View commit details
  2. Copy the full SHA
    bf555d1 View commit details
  3. Copy the full SHA
    1acb5df View commit details

Commits on Mar 21, 2016

  1. Fixes #1981. Wrong number of reported lines in Coverage API

    This ended up being much simpler than I think any of us thought.
    Base problem was any lines after last *newline* marked node would
    not update the primitive 'coverage' array which coverage sets up.
    So we just call one method at end up parse to update that array
    to include final lines of the file.
    enebo committed Mar 21, 2016
    Copy the full SHA
    d465231 View commit details
  2. Copy the full SHA
    5ecba25 View commit details
  3. Copy the full SHA
    8ce7d99 View commit details

Commits on Mar 22, 2016

  1. Copy the full SHA
    2a7d6a9 View commit details

Commits on Mar 29, 2016

  1. Fixes #3766. IO.copy_streams are not closing filename argument IO

    instances.
    
    Solution is to close any open IO instances which were not passed in
    as actual IO instances.
    enebo committed Mar 29, 2016
    Copy the full SHA
    04b8191 View commit details
  2. Copy the full SHA
    3211091 View commit details
  3. Copy the full SHA
    528f28d View commit details

Commits on Mar 30, 2016

  1. Workaround for JRuby bug with UTF-8 encoding on non-English Windows

    We discovered this with a customer yesterday. DNS resolving (using `Resolv::DNS#getaddresses`) failed. It turned out that the underlying problem was that the way `win32/registry.rb` retrieves error messages from Windows is flawed, under certain circumstances.
    
    The bug only appears if:
    
    - `JAVA_OPTS` includes `-Dfile.encoding=UTF-8`
    - The environment you run it on is a _non-English_ Windows installation, or more specifically: a Windows installation where the error message(s) include some non-ASCII character. The specific use case here is a Swedish Windows installation, where the error message for error number 2 (File not found) reads as "Filen du söker finns inte", or something similar. (The debugging here was complicated by the fact that I don't have a Swedish Windows myself, only the customer).
    
    Here is a test script that reproduces the problem given that you have a Swedish Windows:
    
    ```ruby
    
    require 'win32/resolv'
    puts Encoding.locale_charmap
    puts Win32::Resolv.send(:get_info).inspect
    ```
    
    Since I don't have a Swedish Windows, I managed to reproduce the same error locally by adding this code into the `Error` constructor:
    
    ```ruby
    msg = "Malm\xf6, G\xf6teborg och V\xe4xj\xf6"
    ```
    
    That gives me the same error: `ArgumentError: invalid byte sequence in UTF-8`. The original bug occurs in the `msg.tr` call, since the string it operates on is _marked_ as UTF-8 (because of the `force_encoding` call), where it is in fact Windows-1252 encoded (since we call `FormatMessageA`, which returns Windows-1252 encoded strings...). IMHO, this is clearly a bug.
    
    ---
    
    Now, to the solution. The "correct" approach would be to not use the ANSI version of the system call _at all_, but instead use the "wide" version. This is the approach MRI has taken, the bug was fixed there almost 3 years ago. :) ruby/ruby@9db6beb is the specific commit, fixing the bug reported in this issue: https://bugs.ruby-lang.org/issues/8508
    
    I tried that first, by copying over their current version of the `Error` class. The only problem is that it depends on `win32/importer`, which we don't have, which in turn depends on `fiddle/import` which we don't seem to have either. You get the picture.
    
    Therefore, I tried with a simpler workaround instead: _if_ we get an exception in this method, let's just retry by fetching the `en-US` error message instead. (inspired by how the code on the MRI side now looks: https://github.com/ruby/ruby/blob/trunk/ext/win32/lib/win32/registry.rb)
    I have tested this with the customer; it works correctly as far as the code no longer crashes. _But_, it fails to retrieve the English error message (possibly because it's not available on that Windows installation). I am willing to live with that for now; if someone wants to fix that part as well, be my guest. The critical part for me and the customer is that the code must not crash on non-ASCII Windows installations.
    perlun committed Mar 30, 2016
    Copy the full SHA
    48f5908 View commit details

Commits on Mar 31, 2016

  1. Copy the full SHA
    afc3763 View commit details
  2. Merge pull request #3767 from ecraft/fix-win32-registry-error-handlin…

    …g-bug-with-utf8-windows-other-languages
    
    Workaround for JRuby bug with UTF-8 encoding on non-English Windows
    enebo committed Mar 31, 2016
    Copy the full SHA
    a53970c View commit details

Commits on Apr 5, 2016

  1. pend out test for greener ci

    enebo committed Apr 5, 2016
    Copy the full SHA
    a8214df View commit details
  2. Copy the full SHA
    d0b7a7d View commit details
Showing with 1,728 additions and 1,262 deletions.
  1. +1 −1 VERSION
  2. +40 −0 appveyor.yml
  3. +5 −0 build.xml
  4. +10 −9 core/pom.xml
  5. +48 −75 core/src/main/java/org/jruby/RubyFile.java
  6. +34 −5 core/src/main/java/org/jruby/RubyIO.java
  7. +10 −3 core/src/main/java/org/jruby/embed/ScriptingContainer.java
  8. +1 −1 core/src/main/java/org/jruby/ext/coverage/CoverageModule.java
  9. +4 −0 core/src/main/java/org/jruby/ext/socket/RubyUDPSocket.java
  10. +30 −4 core/src/main/java/org/jruby/ext/tempfile/Tempfile.java
  11. +1,048 −1,044 core/src/main/java/org/jruby/parser/DefaultRubyParser.java
  12. +4 −0 core/src/main/java/org/jruby/parser/DefaultRubyParser.y
  13. +1 −0 core/src/main/java/org/jruby/parser/Parser.java
  14. +17 −10 core/src/main/java/org/jruby/parser/ParserConfiguration.java
  15. +7 −3 core/src/main/java/org/jruby/parser/Ruby19Parser.java
  16. +4 −0 core/src/main/java/org/jruby/parser/Ruby19Parser.y
  17. +7 −3 core/src/main/java/org/jruby/parser/Ruby20Parser.java
  18. +4 −0 core/src/main/java/org/jruby/parser/Ruby20Parser.y
  19. +2 −0 core/src/main/java/org/jruby/parser/RubyParser.java
  20. +14 −6 core/src/main/java/org/jruby/util/ShellLauncher.java
  21. +11 −1 core/src/main/java/org/jruby/util/io/CRLFStreamWrapper.java
  22. +1 −1 core/src/main/java/org/jruby/util/io/ChannelStream.java
  23. +22 −0 core/src/main/java/org/jruby/util/io/EncodingUtils.java
  24. +12 −0 core/src/main/java/org/jruby/util/io/NonblockWritingStream.java
  25. +116 −0 core/src/main/ruby/jruby/java/core_ext/#object.rb#
  26. +1 −1 core/src/main/ruby/jruby/kernel/jruby/process_manager.rb
  27. +47 −22 core/src/test/java/org/jruby/embed/ScriptingContainerTest.java
  28. +2 −0 core/src/test/java/org/jruby/embed/bsf/JRubyEngineTest.java
  29. +1 −1 docs/man/pom.xml
  30. +1 −1 docs/pom.xml
  31. +2 −2 ext/pom.xml
  32. +1 −1 ext/readline/pom.xml
  33. +2 −2 ext/ripper/pom.xml
  34. +1 −1 lib/pom.rb
  35. +3 −3 lib/pom.xml
  36. +8 −4 lib/ruby/1.9/win32/registry.rb
  37. +1 −1 maven/jruby-complete/pom.xml
  38. +1 −1 maven/jruby-dist/pom.xml
  39. +3 −3 maven/jruby-jars/pom.xml
  40. +2 −1 maven/jruby-jars/src/it/extended/src/test/java/org/example/SimpleTest.java
  41. +1 −1 maven/jruby-noasm/pom.xml
  42. +1 −1 maven/jruby-rake-plugin/pom.xml
  43. +1 −1 maven/jruby-stdlib/pom.xml
  44. +1 −1 maven/jruby/pom.xml
  45. +3 −1 maven/jruby/src/it/extended/src/test/java/org/example/SimpleTest.java
  46. +1 −1 maven/pom.xml
  47. +2 −2 pom.xml
  48. +1 −0 rakelib/commands.rake
  49. +2 −1 rakelib/test.rake
  50. +1 −1 spec/ruby/core/io/gets_spec.rb
  51. +1 −1 spec/ruby/core/io/read_spec.rb
  52. +0 −1 spec/tags/1.8/ruby/core/file/dirname_tags.txt
  53. +2 −1 spec/tags/1.8/ruby/language/regexp/modifiers_tags.txt
  54. +1 −1 spec/tags/1.9/ruby/core/file/dirname_tags.txt
  55. +1 −0 spec/tags/1.9/ruby/language/regexp/modifiers_tags.txt
  56. +1 −0 test/externals/ruby1.8/logger/test_logger.rb
  57. +8 −7 test/externals/ruby1.8/ruby/test_marshal.rb
  58. +4 −1 test/externals/ruby1.9/excludes/OpenSSL/TestPKCS12.rb
  59. +3 −0 test/externals/ruby1.9/excludes/OpenSSL/TestPKCS7.rb
  60. +3 −0 test/externals/ruby1.9/excludes/OpenSSL/TestPKeyDSA.rb
  61. +3 −0 test/externals/ruby1.9/excludes/OpenSSL/TestPKeyRSA.rb
  62. +1 −0 test/externals/ruby1.9/excludes/OpenSSL/TestPair.rb
  63. +1 −0 test/externals/ruby1.9/excludes/TestArgf.rb
  64. +3 −0 test/externals/ruby1.9/excludes/TestCSV/Interface/DifferentOFS.rb
  65. +1 −0 test/externals/ruby1.9/excludes/TestClass.rb
  66. +4 −0 test/externals/ruby1.9/excludes/TestEncodingConverter.rb
  67. +4 −1 test/externals/ruby1.9/excludes/TestException.rb
  68. +3 −0 test/externals/ruby1.9/excludes/TestFiber.rb
  69. +4 −0 test/externals/ruby1.9/excludes/TestFile.rb
  70. +20 −0 test/externals/ruby1.9/excludes/TestFileExhaustive.rb
  71. +19 −0 test/externals/ruby1.9/excludes/TestFileUtils.rb
  72. +4 −0 test/externals/ruby1.9/excludes/TestFind.rb
  73. +7 −0 test/externals/ruby1.9/excludes/TestIO.rb
  74. +5 −0 test/externals/ruby1.9/excludes/TestIO_M17N.rb
  75. +5 −0 test/externals/ruby1.9/excludes/TestIntegration.rb
  76. +3 −0 test/externals/ruby1.9/excludes/TestLogDevice.rb
  77. +1 −0 test/externals/ruby1.9/excludes/TestMarshal.rb
  78. +1 −0 test/externals/ruby1.9/excludes/TestModule.rb
  79. +3 −0 test/externals/ruby1.9/excludes/TestMonitor.rb
  80. +7 −0 test/externals/ruby1.9/excludes/TestOpen3.rb
  81. +3 −0 test/externals/ruby1.9/excludes/TestPath.rb
  82. +10 −0 test/externals/ruby1.9/excludes/TestPathname.rb
  83. +3 −0 test/externals/ruby1.9/excludes/TestSignal.rb
  84. +4 −1 test/externals/ruby1.9/excludes/TestSocketNonblock.rb
  85. +0 −2 test/externals/ruby1.9/excludes/TestSocket_UNIXSocket.rb
  86. +3 −0 test/externals/ruby1.9/excludes/TestString.rb
  87. +1 −0 test/externals/ruby1.9/logger/test_logger.rb
  88. +1 −1 test/externals/ruby1.9/ruby/test_env.rb
  89. +1 −1 test/mri.1.9.index
  90. +4 −1 test/pom.rb
  91. +14 −7 test/pom.xml
  92. +18 −16 test/test_higher_javasupport.rb
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.7.25-SNAPSHOT
1.7.26-SNAPSHOT
40 changes: 40 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
version: '{build}'

build: off

environment:
matrix:
- JAVA_HOME: C:\Program Files (x86)\Java\jdk1.8.0

install:
- ps: >-
Add-Type -AssemblyName System.IO.Compression.FileSystem
if (!(Test-Path -Path "C:\maven" )) {
(new-object System.Net.WebClient).DownloadFile(
'http://www.us.apache.org/dist/maven/maven-3/3.3.3/binaries/apache-maven-3.3.3-bin.zip',
'C:\maven-bin.zip'
)
[System.IO.Compression.ZipFile]::ExtractToDirectory("C:\maven-bin.zip", "C:\maven")
}
- ps: >-
Add-Type -AssemblyName System.IO.Compression.FileSystem
if (!(Test-Path -Path "C:\ant" )) {
(new-object System.Net.WebClient).DownloadFile(
'http://www.us.apache.org/dist/ant/binaries/apache-ant-1.9.7-bin.zip',
'C:\ant-bin.zip'
)
[System.IO.Compression.ZipFile]::ExtractToDirectory("C:\ant-bin.zip", "C:\ant")
}
- cmd: SET PATH=C:\maven\apache-maven-3.3.3\bin;C:\ant\apache-ant-1.9.7\bin;%JAVA_HOME%\bin;%PATH%
- cmd: echo %PATH%
- cmd: java -version

cache:
- C:\maven
- C:\Users\appveyor\.m2

test_script:
- mvn -Ptest
- ant test:mri:appveyor
5 changes: 5 additions & 0 deletions build.xml
Original file line number Diff line number Diff line change
@@ -344,6 +344,11 @@
</javadoc>
</target>

<target name="test:mri:appveyor">
<rake task="test:mri"/>
<rake task="test:mri19"/>
</target>

<target name="installer">
<rake task="installer"/>
</target>
19 changes: 10 additions & 9 deletions core/pom.xml
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
<parent>
<groupId>org.jruby</groupId>
<artifactId>jruby-parent</artifactId>
<version>1.7.25-SNAPSHOT</version>
<version>1.7.26-SNAPSHOT</version>
</parent>
<artifactId>jruby-core</artifactId>
<packaging>jar</packaging>
@@ -45,7 +45,7 @@
<dependency>
<groupId>org.jruby.joni</groupId>
<artifactId>joni</artifactId>
<version>2.1.9</version>
<version>2.1.10</version>
<type>jar</type>
</dependency>
<dependency>
@@ -57,7 +57,7 @@
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-enxio</artifactId>
<version>0.9</version>
<version>0.12</version>
<type>jar</type>
</dependency>
<dependency>
@@ -68,13 +68,13 @@
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-unixsocket</artifactId>
<version>0.8</version>
<version>0.12</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-posix</artifactId>
<version>3.0.27</version>
<version>3.0.29</version>
<type>jar</type>
</dependency>
<dependency>
@@ -86,7 +86,7 @@
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-constants</artifactId>
<version>0.9.0</version>
<version>0.9.2</version>
<type>jar</type>
</dependency>
<dependency>
@@ -98,7 +98,7 @@
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-ffi</artifactId>
<version>2.0.5</version>
<version>2.0.9</version>
<type>jar</type>
</dependency>
<dependency>
@@ -169,7 +169,7 @@
<dependency>
<groupId>com.headius</groupId>
<artifactId>unsafe-mock</artifactId>
<version>8.0</version>
<version>${unsafe.version}</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
@@ -210,7 +210,8 @@
</dependencies>
<properties>
<anno.sources>${project.basedir}/target/generated-sources</anno.sources>
<unsafe.jar>${settings.localRepository}/com/headius/unsafe-mock/8.0/unsafe-mock-8.0.jar</unsafe.jar>
<unsafe.version>8.92.1</unsafe.version>
<unsafe.jar>${settings.localRepository}/com/headius/unsafe-mock/${unsafe.version}/unsafe-mock-${unsafe.version}.jar</unsafe.jar>
<maven.build.timestamp.format>yyyy-MM-dd</maven.build.timestamp.format>
<build.date>${maven.build.timestamp}</build.date>
<Constants.java>org/jruby/runtime/Constants.java</Constants.java>
123 changes: 48 additions & 75 deletions core/src/main/java/org/jruby/RubyFile.java
Original file line number Diff line number Diff line change
@@ -676,92 +676,65 @@ public static IRubyObject dirname(ThreadContext context, IRubyObject recv, IRuby
}

static Pattern PROTOCOL_PATTERN = Pattern.compile(URI_PREFIX_STRING + ".*");
public static String dirname(ThreadContext context, String jfilename) {
String name = jfilename.replace('\\', '/');
int minPathLength = 1;
boolean trimmedSlashes = false;

boolean startsWithDriveLetterOnWindows = startsWithDriveLetterOnWindows(name);
// get dirname with uri scheme stripped off and then recombine that back to scheme.
private static String adjustURIDirname(ThreadContext context, String path, int start) {
String adjustedPath = dirname(context, path.substring(start));
if (adjustedPath.equals(".") || adjustedPath.equals("/")) adjustedPath = "";
return path.substring(0, start) + adjustedPath;
}

if (startsWithDriveLetterOnWindows) {
minPathLength = 3;
// will strip any trailing forward or backslashes except unless the string gets too short.
private static String stripTrailingSlashes(String path, int minPathLength) {
while (path.length() > minPathLength) { // lol
int lastIndex = path.length() - 1;
char c = path.charAt(lastIndex);
if (c != '/' && c != '\\') break;
path = path.substring(0, lastIndex);
}
return path;
}
/**
* Return the dirname of the specified filename. path is the original string. On windows
* if this is a file path it will leave the delimiter the same. If it represents a URI then it
* needs to become forward slashes.
*
* Internally we have two strings in this method: path and normalizedPath which is normalized
* to '/' so we only have to do indexes against a single format of file.
*/
// FIXME: MRI returns '//' -> '//' and '\\\\' -> '\\\\' (bug?). useless values seemingly?
public static String dirname(ThreadContext context, String path) {
String normalizedPath = path.replace('\\', '/');
boolean hasDriveLetter = startsWithDriveLetterOnWindows(normalizedPath);

// jar like paths
if (name.contains(".jar!/")) {
int start = name.indexOf("!/") + 1;
String path = dirname(context, name.substring(start));
if (path.equals(".") || path.equals("/")) path = "";
return name.substring(0, start) + path;
}
// address all the url like paths first
if (PROTOCOL_PATTERN.matcher(name).matches()) {
int start = name.indexOf(":/") + 2;
String path = dirname(context, name.substring(start));
if (path.equals(".")) path = "";
return name.substring(0, start) + path;
}
// Dealing with URIs. These are use normalized path because \ is never valid.
if (normalizedPath.contains(".jar!/")) return adjustURIDirname(context, normalizedPath, normalizedPath.indexOf("!/") + 1);
if (PROTOCOL_PATTERN.matcher(normalizedPath).matches()) return adjustURIDirname(context, normalizedPath,normalizedPath.indexOf(":/") + 2);

while (name.length() > minPathLength && name.charAt(name.length() - 1) == '/') {
trimmedSlashes = true;
name = name.substring(0, name.length() - 1);
}
if (hasDriveLetter && normalizedPath.length() == 2) return path + '.'; // 'C:' passed in

String result;
if (startsWithDriveLetterOnWindows && name.length() == 2) {
if (trimmedSlashes) {
// C:\ is returned unchanged
result = jfilename.substring(0, 3);
} else {
result = jfilename.substring(0, 2) + '.';
}
} else {
//TODO deal with UNC names
int index = name.lastIndexOf('/');
normalizedPath = stripTrailingSlashes(normalizedPath, hasDriveLetter ? 3 : 1); // '/foo[/\\]+' -> '/foo/'

if (index == -1) {
if (startsWithDriveLetterOnWindows) {
return jfilename.substring(0, 2) + '.';
} else {
return ".";
}
}
if (index == 0) {
return "/";
}
// stripped off one or more / from trailing slash normalization above...cope with it (C: handled earlier)
if (hasDriveLetter && normalizedPath.length() == 2) return path.substring(0, 3); // C:[/\\]+

if (startsWithDriveLetterOnWindows && index == 2) {
// Include additional path separator
// (so that dirname of "C:\file.txt" is "C:\", not "C:")
index++;
}
int lastSlash = normalizedPath.lastIndexOf('/');
if (lastSlash == -1) return hasDriveLetter ? path.substring(0, 2) + '.' : "."; // 'C:foo' or 'foo' (no slash)
if (lastSlash == 0) return path.substring(0, 1); // '/' or '\'
if (lastSlash == 2 && hasDriveLetter) return path.substring(0, 3); // 'C:[/\\]file'

if (jfilename.startsWith("\\\\")) {
index = jfilename.length();
String[] splitted = jfilename.split(Pattern.quote("\\"));
int last = splitted.length-1;
if (splitted[last].contains(".")) {
index = jfilename.lastIndexOf('\\');
}

}

result = jfilename.substring(0, index);

}

char endChar;
// trim trailing slashes
while (result.length() > minPathLength) {
endChar = result.charAt(result.length() - 1);
if (endChar == '/' || endChar == '\\') {
result = result.substring(0, result.length() - 1);
} else {
break;
if (Platform.IS_WINDOWS && normalizedPath.startsWith("//")) { // UNC path
if (lastSlash == 1) return path.substring(0, normalizedPath.length()); // '//foo'

if (!normalizedPath.substring(2, lastSlash - 2).contains("/")) { // '//foo/bar'
return path.substring(0, normalizedPath.length());
}

// deeper UNC path
}

return result;
// we strip one last time for case '/foo///////bar.txt'
return stripTrailingSlashes(path.substring(0, lastSlash), hasDriveLetter ? 3 : 1);
}

/**
@@ -1332,7 +1305,7 @@ protected void sysopenInternal19(String path, int oflags, int perm) {
}

ChannelDescriptor descriptor = sysopen(path, modes, perm);
openFile.setMainStream(fdopen(descriptor, modes));
openFile.setMainStream(reprocessStreamInCaseECOptsWantsCRLF(fdopen(descriptor, modes), modes));
}

protected void openInternal(String path, String modeString) {
39 changes: 34 additions & 5 deletions core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
@@ -38,10 +38,12 @@
import org.jruby.runtime.Helpers;
import org.jruby.util.ResourceException;
import org.jruby.util.StringSupport;
import org.jruby.util.io.CRLFStreamWrapper;
import org.jruby.util.io.DirectoryAsFileException;
import org.jruby.util.io.EncodingUtils;
import org.jruby.util.io.FileExistsException;
import org.jruby.util.io.ModeFlags;
import org.jruby.util.io.NonblockWritingStream;
import org.jruby.util.io.SelectBlob;
import jnr.constants.platform.Fcntl;
import java.io.EOFException;
@@ -318,6 +320,23 @@ public Stream getHandler() throws BadDescriptorException {
return getOpenFileChecked().getMainStreamSafe();
}

// FIXME: This is a bit wonky. 1.9 uses this special stream wrapper on windows but at the
// location it is created we do not have access to ecflags and their newline processing
// preferences. So this check was added to strip off crlf conversion if one of the IO
// options from ECONV says not to.
protected Stream reprocessStreamInCaseECOptsWantsCRLF(Stream fd, ModeFlags modes) {
// FIXME: I do not understand how a 1.8 path hits this since this is only called
// from open methods that end in 19?
if (getRuntime().is1_9() && Platform.IS_WINDOWS && !modes.isBinary() &&
(ecflags & EncodingUtils.ECONV_UNIVERSAL_NEWLINE_DECORATOR) == 0 &&
(ecflags & EncodingUtils.ECONV_CRLF_NEWLINE_DECORATOR) == 0 &&
fd instanceof CRLFStreamWrapper) {
return ((CRLFStreamWrapper) fd).getOriginalStream();
}

return fd;
}

protected void reopenPath(Ruby runtime, IRubyObject[] args) {
IRubyObject pathString;

@@ -896,7 +915,7 @@ private IRubyObject initializeCommon19(ThreadContext context, int fileno, IRubyO
ModeFlags modes = ModeFlags.createModeFlags(oflags_p[0]);

openFile.setMode(fmode_p[0]);
openFile.setMainStream(fdopen(descriptor, modes));
openFile.setMainStream(reprocessStreamInCaseECOptsWantsCRLF(fdopen(descriptor, modes), modes));
clearCodeConversion();

// io_check_tty(fp);
@@ -1363,7 +1382,7 @@ public IRubyObject doWriteNonblock(ThreadContext context, IRubyObject obj, boole
runtime.getWarnings().warn(ID.SYSWRITE_BUFFERED_IO, "write_nonblock for buffered IO");
}

ChannelStream stream = (ChannelStream)myOpenFile.getWriteStream();
NonblockWritingStream stream = (NonblockWritingStream)myOpenFile.getWriteStream();

int written = stream.writenonblock(str.getByteList());
if (written == 0) {
@@ -4620,7 +4639,9 @@ public static IRubyObject copy_stream(ThreadContext context, IRubyObject recv,
RubyInteger length = null;
RubyInteger offset = null;

boolean io1FromIO = false;
RubyIO io1 = null;
boolean io2FromIO = false;
RubyIO io2 = null;

RubyString read = null;
@@ -4636,6 +4657,7 @@ public static IRubyObject copy_stream(ThreadContext context, IRubyObject recv,
if (arg1 instanceof RubyString) {
io1 = (RubyIO) RubyFile.open(context, runtime.getFile(), new IRubyObject[] {arg1}, Block.NULL_BLOCK);
} else if (arg1 instanceof RubyIO) {
io1FromIO = true;
io1 = (RubyIO) arg1;
} else if (arg1.respondsTo("to_path")) {
RubyString path = (RubyString) TypeConverter.convertToType19(arg1, runtime.getString(), "to_path");
@@ -4653,6 +4675,7 @@ public static IRubyObject copy_stream(ThreadContext context, IRubyObject recv,
if (arg2 instanceof RubyString) {
io2 = (RubyIO) RubyFile.open(context, runtime.getFile(), new IRubyObject[] {arg2, runtime.newString("w")}, Block.NULL_BLOCK);
} else if (arg2 instanceof RubyIO) {
io2FromIO = true;
io2 = (RubyIO) arg2;
} else if (arg2.respondsTo("to_path")) {
RubyString path = (RubyString) TypeConverter.convertToType19(arg2, runtime.getString(), "to_path");
@@ -4713,6 +4736,9 @@ public static IRubyObject copy_stream(ThreadContext context, IRubyObject recv,
}
} catch (BadDescriptorException e) {
throw runtime.newErrnoEBADFError();
} finally {
if (!io1FromIO && io1 != null && !io1.isClosed()) io1.ioClose(runtime);
if (!io2FromIO && io2 != null && !io2.isClosed()) io2.ioClose(runtime);
}
}

@@ -5180,10 +5206,13 @@ private boolean needsReadConversion() {

// MRI: NEED_WRITECONV (FIXME: Windows has slightly different version)
private boolean needsWriteConversion(ThreadContext context) {
Encoding ascii8bit = context.runtime.getEncodingService().getAscii8bitEncoding();
boolean notAscii8bit = enc != null && enc != context.runtime.getEncodingService().getAscii8bitEncoding();

return (enc != null && enc != ascii8bit) || openFile.isTextMode() ||
(ecflags & ((EncodingUtils.ECONV_DECORATOR_MASK & ~EncodingUtils.ECONV_CRLF_NEWLINE_DECORATOR)|EncodingUtils.ECONV_STATEFUL_DECORATOR_MASK)) != 0;
if (Platform.IS_WINDOWS) {
return notAscii8bit || (ecflags & ((EncodingUtils.ECONV_DECORATOR_MASK & ~EncodingUtils.ECONV_CRLF_NEWLINE_DECORATOR)|EncodingUtils.ECONV_STATEFUL_DECORATOR_MASK)) != 0;
} else {
return notAscii8bit || openFile.isTextMode() || (ecflags & (EncodingUtils.ECONV_DECORATOR_MASK|EncodingUtils.ECONV_STATEFUL_DECORATOR_MASK)) != 0;
}
}

// MRI: make_readconv
Loading