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: 07313c1446c6
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 221ba4f3b0f9
Choose a head ref
  • 6 commits
  • 5 files changed
  • 1 contributor

Commits on May 25, 2016

  1. Copy the full SHA
    c36509d View commit details
  2. Copy the full SHA
    e7f1605 View commit details
  3. Copy the full SHA
    c5b5a02 View commit details
  4. Normalize PATH set to filesystem encoding, as in MRI.

    Fixes the rest of #3907.
    headius committed May 25, 2016
    Copy the full SHA
    e211eca View commit details
  5. Copy the full SHA
    141c57f View commit details
  6. Temporarily pass env values through bytes for locale encoding.

    This fixes the one regression in my previous changes. Because MRI
    always creates new strings when you read from ENV, they just
    normalize to locale encoding for setenv, and then either use
    locale encoding or filesystem encoding for getenv. The equivalent
    for us here is to just let the setenv string decode to Java String
    and then use the default getBytes to match it up with the default
    Charset used for locale, rather than attempting to transcode the
    string directly.
    headius committed May 25, 2016
    Copy the full SHA
    221ba4f View commit details
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyFile.java
Original file line number Diff line number Diff line change
@@ -1640,7 +1640,7 @@ else if ( ( preFix.equals("uri:classloader:") || preFix.equals("classpath:") )
if (path.startsWith("uri:")) {
cwd = path;
} else {
cwd = StringSupport.checkEmbeddedNulls(runtime, get_path(context, args[1])).getUnicodeValue();
cwd = StringSupport.checkEmbeddedNulls(runtime, get_path(context, args[1])).toString();

// Handle ~user paths.
if (expandUser) {
29 changes: 20 additions & 9 deletions core/src/main/java/org/jruby/RubyGlobal.java
Original file line number Diff line number Diff line change
@@ -58,6 +58,7 @@
import org.jruby.util.OSEnvironment;
import org.jruby.util.RegexpOptions;
import org.jruby.util.cli.OutputStrings;
import org.jruby.util.io.EncodingUtils;
import org.jruby.util.io.OpenFile;
import org.jruby.util.io.STDIO;

@@ -420,9 +421,9 @@ protected IRubyObject case_aware_op_aset(ThreadContext context,
return super.delete(context, key, org.jruby.runtime.Block.NULL_BLOCK);
}

IRubyObject keyAsStr = normalizeEnvString(Helpers.invoke(context, key, "to_str"));
IRubyObject keyAsStr = normalizeEnvString(context, key, Helpers.invoke(context, key, "to_str"));
IRubyObject valueAsStr = value.isNil() ? context.nil :
normalizeEnvString(Helpers.invoke(context, value, "to_str"));
normalizeEnvString(context, key, Helpers.invoke(context, value, "to_str"));

if (updateRealENV) {
POSIX posix = context.runtime.getPosix();
@@ -458,14 +459,24 @@ private RubyString getCorrectKey(IRubyObject key, ThreadContext context) {
return actualKey;
}

private IRubyObject normalizeEnvString(IRubyObject str) {
if (str instanceof RubyString) {
Encoding enc = getRuntime().getEncodingService().getLocaleEncoding();
RubyString newStr = getRuntime().newString(new ByteList(str.toString().getBytes(), enc));
newStr.setFrozen(true);
return newStr;
private IRubyObject normalizeEnvString(ThreadContext context, IRubyObject key, IRubyObject value) {
if (value instanceof RubyString) {
Ruby runtime = context.runtime;
RubyString valueStr = (RubyString) value;

// Ensure PATH is encoded like filesystem
if (key.toString().equalsIgnoreCase("PATH")) {
Encoding enc = runtime.getEncodingService().getFileSystemEncoding();
valueStr = EncodingUtils.strConvEnc(context, valueStr, valueStr.getEncoding(), enc);
} else {
valueStr = RubyString.newString(runtime, valueStr.toString(), runtime.getEncodingService().getLocaleEncoding());
}

valueStr.setFrozen(true);

return valueStr;
}
return str;
return value;
}
}

12 changes: 6 additions & 6 deletions core/src/main/java/org/jruby/runtime/Helpers.java
Original file line number Diff line number Diff line change
@@ -57,6 +57,7 @@
import static org.jruby.util.StringSupport.EMPTY_STRING_ARRAY;

import org.jruby.util.JavaNameMangler;
import org.jruby.util.io.EncodingUtils;

/**
* Helper methods which are called by the compiler. Note: These will show no consumers, but
@@ -2645,15 +2646,14 @@ public static String decodeByteList(Ruby runtime, ByteList value) {
Charset charset = runtime.getEncodingService().charsetForEncoding(encoding);

if (charset == null) {
try {
return new String(unsafeBytes, begin, length, encoding.toString());
} catch (UnsupportedEncodingException uee) {
return value.toString();
}
// No JDK Charset available for this encoding; convert to UTF-16 ourselves.
Encoding utf16 = EncodingUtils.getUTF16ForPlatform();

return EncodingUtils.strConvEnc(runtime.getCurrentContext(), value, value.getEncoding(), utf16).toString();
}

return RubyEncoding.decode(unsafeBytes, begin, length, charset);
}
}

/**
* Convert a ByteList into a Java String by using its Encoding's Charset. If
20 changes: 13 additions & 7 deletions core/src/main/java/org/jruby/util/OSEnvironment.java
Original file line number Diff line number Diff line change
@@ -89,15 +89,15 @@ public Map<RubyString, RubyString> getSystemPropertiesMap(Ruby runtime) {
private static Map<RubyString, RubyString> asMapOfRubyStrings(final Ruby runtime, final Map<?, ?> map) {
@SuppressWarnings("unchecked")
final Map<RubyString, RubyString> rubyMap = new HashMap(map.size() + 2);
Encoding encoding = runtime.getEncodingService().getLocaleEncoding();
Encoding keyEncoding = runtime.getEncodingService().getLocaleEncoding();

// On Windows, map doesn't have corresponding keys for these
if (Platform.IS_WINDOWS) {
// these may be null when in a restricted environment (JRUBY-6514)
String home = SafePropertyAccessor.getProperty("user.home");
String user = SafePropertyAccessor.getProperty("user.name");
putRubyKeyValuePair(runtime, rubyMap, "HOME", home == null ? "/" : home, encoding);
putRubyKeyValuePair(runtime, rubyMap, "USER", user == null ? "" : user, encoding);
putRubyKeyValuePair(runtime, rubyMap, "HOME", keyEncoding, home == null ? "/" : home, keyEncoding);
putRubyKeyValuePair(runtime, rubyMap, "USER", keyEncoding, user == null ? "" : user, keyEncoding);
}

for (Map.Entry<?, ?> entry : map.entrySet()) {
@@ -111,17 +111,23 @@ private static Map<RubyString, RubyString> asMapOfRubyStrings(final Ruby runtime
val = entry.getValue();
if ( ! (val instanceof String) ) continue; // Java devs can stuff non-string objects into env

putRubyKeyValuePair(runtime, rubyMap, key, (String) val, encoding);
// Ensure PATH is encoded like filesystem
Encoding valueEncoding = keyEncoding;
if ( key.equalsIgnoreCase("PATH") ) {
valueEncoding = runtime.getEncodingService().getFileSystemEncoding();
}

putRubyKeyValuePair(runtime, rubyMap, key, keyEncoding, (String) val, valueEncoding);
}

return rubyMap;
}

private static void putRubyKeyValuePair(Ruby runtime,
final Map<RubyString, RubyString> map,
String key, String value, Encoding encoding) {
ByteList keyBytes = new ByteList(key.getBytes(), encoding);
ByteList valueBytes = new ByteList(value.getBytes(), encoding);
String key, Encoding keyEncoding, String value, Encoding valueEncoding) {
ByteList keyBytes = RubyString.encodeBytelist(key, keyEncoding);
ByteList valueBytes = RubyString.encodeBytelist(value, valueEncoding);

RubyString keyString = runtime.newString(keyBytes);
RubyString valueString = runtime.newString(valueBytes);
17 changes: 11 additions & 6 deletions core/src/main/java/org/jruby/util/io/EncodingUtils.java
Original file line number Diff line number Diff line change
@@ -1268,12 +1268,7 @@ public static void transcodeLoop(ThreadContext context, byte[] inBytes, Ptr inPo
public static ByteList transcodeString(String string, Encoding toEncoding, int ecflags) {
Encoding encoding;

// This may be inefficient if we aren't matching endianness right
if (Platform.BYTE_ORDER == Platform.LITTLE_ENDIAN) {
encoding = UTF16LEEncoding.INSTANCE;
} else {
encoding = UTF16BEEncoding.INSTANCE;
}
encoding = getUTF16ForPlatform();

EConv ec = TranscoderDB.open(encoding.getName(), toEncoding.getName(), ecflags);

@@ -1298,6 +1293,16 @@ public static ByteList transcodeString(String string, Encoding toEncoding, int e
return destination;
}

public static Encoding getUTF16ForPlatform() {
Encoding encoding;// This may be inefficient if we aren't matching endianness right
if (Platform.BYTE_ORDER == Platform.LITTLE_ENDIAN) {
encoding = UTF16LEEncoding.INSTANCE;
} else {
encoding = UTF16BEEncoding.INSTANCE;
}
return encoding;
}

/**
* Perform the inner transcoding loop.
*