Skip to content
Permalink
Browse files
Preserve incoming encoding in File.basename. Fixes #2259.
  • Loading branch information
headius committed Dec 10, 2014
1 parent 2d62cd2 commit 2c1c909fe2866515776afdfb334bbe7f8b60cbf6
Showing with 32 additions and 4 deletions.
  1. +25 −4 core/src/main/java/org/jruby/RubyFile.java
  2. +7 −0 spec/regression/GH-2259_file_basename_must_preserve_encoding_spec.rb
@@ -43,6 +43,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URL;
import java.nio.channels.Channel;
@@ -508,16 +509,28 @@ public IRubyObject inspect() {

@JRubyMethod(required = 1, optional = 1, meta = true)
public static IRubyObject basename(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
String name = get_path(context,args[0]).getUnicodeValue();
Ruby runtime = context.runtime;

RubyString origString = get_path(context,args[0]);
Encoding origEncoding = origString.getEncoding();
String name = origString.toString();

// MRI-compatible basename handling for windows drive letter paths
if (Platform.IS_WINDOWS) {
if (name.length() > 1 && name.charAt(1) == ':' && Character.isLetter(name.charAt(0))) {
switch (name.length()) {
case 2:
return RubyString.newEmptyString(context.runtime).infectBy(args[0]);
return RubyString.newEmptyString(runtime, origString.getEncoding()).infectBy(args[0]);
case 3:
return context.runtime.newString(name.substring(2)).infectBy(args[0]);
if (origEncoding.getCharset() != null) {
try {
return RubyString.newString(runtime, new ByteList(name.substring(2).getBytes(origEncoding.getCharsetName()), origString.getEncoding())).infectBy(args[0]);
} catch (UnsupportedEncodingException uee) {
// fall through to UTF-8 logic
}
}

return RubyString.newString(runtime, name.substring(2)).infectBy(args[0]);
default:
switch (name.charAt(2)) {
case '/':
@@ -572,7 +585,15 @@ public static IRubyObject basename(ThreadContext context, IRubyObject recv, IRub
name = name.substring(0, name.length() - ext.length());
}
}
return context.runtime.newString(name).infectBy(args[0]);
if (origEncoding.getCharset() != null) {
try {
return RubyString.newString(runtime, new ByteList(name.getBytes(origEncoding.getCharsetName()), origString.getEncoding())).infectBy(args[0]);
} catch (UnsupportedEncodingException uee) {
// fall through to UTF-8 logic
}
}

return RubyString.newString(runtime, name).infectBy(args[0]);
}

@JRubyMethod(required = 2, rest = true, meta = true)
@@ -0,0 +1,7 @@
if RUBY_VERSION > "1.9"
describe "File.basename when given a path with non-default encoding" do
it "produces the basename path with the same encoding" do
expect(File.basename('/foo/bar'.force_encoding('Windows-31J')).encoding).to eq Encoding::Windows_31J
end
end
end

0 comments on commit 2c1c909

Please sign in to comment.