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: a2eec06723ee
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: dac98500db5d
Choose a head ref
  • 3 commits
  • 4 files changed
  • 2 contributors

Commits on May 10, 2016

  1. Copy the full SHA
    40f0c84 View commit details
  2. expand_path matches mri

    ahorek authored and headius committed May 10, 2016
    Copy the full SHA
    58b949a View commit details
  3. Further fixes for File.expand_path encoding.

    See #3849 and the PR this is based on #3866.
    headius committed May 10, 2016
    Copy the full SHA
    dac9850 View commit details
29 changes: 16 additions & 13 deletions core/src/main/java/org/jruby/RubyFile.java
Original file line number Diff line number Diff line change
@@ -47,7 +47,6 @@
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
@@ -80,7 +79,6 @@
import org.jruby.util.TypeConverter;
import org.jruby.util.io.EncodingUtils;
import org.jruby.util.io.IOEncodable;
import org.jruby.util.io.ModeFlags;
import org.jruby.util.io.OpenFile;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.encoding.EncodingService;
@@ -786,7 +784,6 @@ public static IRubyObject expand_path(ThreadContext context, IRubyObject recv, I
@JRubyMethod(name = "expand_path", required = 1, optional = 1, meta = true)
public static IRubyObject expand_path19(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
RubyString path = (RubyString) expandPathInternal(context, recv, args, true, false);
path.force_encoding(context, context.runtime.getEncodingService().getDefaultExternal());

return path;
}
@@ -1560,10 +1557,13 @@ private static IRubyObject expandPathInternal(ThreadContext context, IRubyObject

RubyString origPath = StringSupport.checkEmbeddedNulls(runtime, get_path(context, args[0]));
String relativePath = origPath.getUnicodeValue();
Encoding enc = origPath.getEncoding();
// for special paths like ~
Encoding fsenc = runtime.getEncodingService().getFileSystemEncoding();

// Special /dev/null of windows
if (Platform.IS_WINDOWS && ("NUL:".equalsIgnoreCase(relativePath) || "NUL".equalsIgnoreCase(relativePath))) {
return runtime.newString("//./" + relativePath.substring(0, 3));
return RubyString.newString(runtime, "//./" + relativePath.substring(0, 3), fsenc);
}

// treat uri-like and jar-like path as absolute
@@ -1613,21 +1613,22 @@ else if ( ( preFix.equals("uri:classloader:") || preFix.equals("classpath:") )
// this is basically for classpath:/ and uri:classloader:/
relativePath = relativePath.substring(2).replace('\\', '/');
}
return concatStrings(runtime, preFix, extra, relativePath);
return concatStrings(runtime, preFix, extra, relativePath, enc);
}

String[] uriParts = splitURI(relativePath);
String cwd;

// Handle ~user paths
if (expandUser) {
if (expandUser && startsWith(relativePath, '~')) {
enc = fsenc;
relativePath = expandUserPath(context, relativePath, true);
}

if (uriParts != null) {
//If the path was an absolute classpath path, return it as-is.
if (uriParts[0].equals("classpath:")) {
return concatStrings(runtime, preFix, relativePath, postFix);
return concatStrings(runtime, preFix, relativePath, postFix, enc);
}
relativePath = uriParts[1];
}
@@ -1640,6 +1641,7 @@ else if ( ( preFix.equals("uri:classloader:") || preFix.equals("classpath:") )
if (args.length == 2 && !args[1].isNil()) {
// TODO maybe combine this with get_path method
String path = args[1].toString();
enc = fsenc;
if (path.startsWith("uri:")) {
cwd = path;
} else {
@@ -1745,13 +1747,14 @@ else if ( ( preFix.equals("uri:classloader:") || preFix.equals("classpath:") )
}
}
}
return concatStrings(runtime, preFix, realPath, postFix);
return concatStrings(runtime, preFix, realPath, postFix, enc);
}

private static RubyString concatStrings(final Ruby runtime, String s1, String s2, String s3) {
private static RubyString concatStrings(final Ruby runtime, String s1, String s2, String s3, Encoding enc) {
return RubyString.newString(runtime,
new StringBuilder(s1.length() + s2.length() + s3.length()).
append(s1).append(s2).append(s3)
append(s1).append(s2).append(s3).toString(),
enc
);
}

@@ -1808,7 +1811,7 @@ public static String expandUserPath(ThreadContext context, String path) {
public static String expandUserPath(ThreadContext context, String path, final boolean raiseOnRelativePath) {
int pathLength = path.length();

if (pathLength >= 1 && path.charAt(0) == '~') {
if (startsWith(path, '~')) {
// Enebo : Should ~frogger\\foo work (it doesnt in linux ruby)?
int userEnd = path.indexOf('/');

@@ -2049,11 +2052,11 @@ private static boolean startsWith(final CharSequence str, final String prefix) {
}

private static boolean startsWith(final CharSequence str, final char c) {
return ( str.length() < 1 ) ? false : str.charAt(0) == c;
return str.length() >= 1 && str.charAt(0) == c;
}

private static boolean startsWith(final CharSequence str, final char c1, final char c2) {
return ( str.length() < 2 ) ? false : str.charAt(0) == c1 && str.charAt(1) == c2;
return str.length() >= 2 && str.charAt(0) == c1 && str.charAt(1) == c2;
}

// without any char[] array copying, also StringBuilder only has lastIndexOf(String)
Original file line number Diff line number Diff line change
@@ -97,7 +97,7 @@ public Encoding getAscii8bitEncoding() {
}

// mri: rb_filesystem_encoding
public Encoding getFileSystemEncoding(Ruby runtime) {
public Encoding getFileSystemEncoding() {
return SpecialEncoding.FILESYSTEM.toEncoding(runtime);
}

@@ -579,4 +579,9 @@ private Entry findEntryFromEncoding(Encoding e) {
if (e == null) return null;
return findEncodingEntry(new ByteList(e.getName()));
}

@Deprecated
public Encoding getFileSystemEncoding(Ruby runtime) {
return getFileSystemEncoding();
}
}
1 change: 0 additions & 1 deletion spec/tags/ruby/core/file/expand_path_tags.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
fails:File.expand_path raises an Encoding::CompatibilityError if the external encoding is not compatible
fails:File.expand_path returns a String in the same encoding as the argument
fails:File.expand_path expands a path when the default external encoding is ASCII-8BIT
windows:File.expand_path expands a path with multi-byte characters
windows:File.expand_path does not modify a HOME string argument
8 changes: 8 additions & 0 deletions test/jruby/test_file.rb
Original file line number Diff line number Diff line change
@@ -98,6 +98,14 @@ def test_expand_path_cross_platform
}
end

# JRUBY-3849
def test_expand_path_encoding
assert_equal(Encoding.find('UTF-8'), File.expand_path('/'.force_encoding('UTF-8')).encoding)
assert_equal(Encoding.find('US-ASCII'), File.expand_path('/'.force_encoding('US-ASCII')).encoding)
assert_equal(Encoding.find('UTF-8'), File.expand_path(Pathname.new('/'.force_encoding('UTF-8'))).encoding)
assert_equal(Encoding.find('US-ASCII'), File.expand_path(Pathname.new('/'.force_encoding('US-ASCII'))).encoding)
end

def test_expand_path_nil
assert_raise(TypeError) { File.expand_path(nil) }
assert_raise(TypeError) { File.expand_path(nil, "/") }