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: 49a293b12ff2
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 83edfadd9c2d
Choose a head ref
  • 8 commits
  • 4 files changed
  • 1 contributor

Commits on Mar 19, 2016

  1. make ? expr an one liner

    kares committed Mar 19, 2016
    Copy the full SHA
    cc6725b View commit details
  2. indent method body correctly

    kares committed Mar 19, 2016
    Copy the full SHA
    589ce32 View commit details
  3. RubyFile cleanup - invent String#startsWith for char(s) + find-bugs :

    - avoid replace with Strings when char does
    - avoid String#equals("") in favor of length == 0
    kares committed Mar 19, 2016
    Copy the full SHA
    85c2773 View commit details
  4. Copy the full SHA
    c665c97 View commit details
  5. Copy the full SHA
    d39cdb7 View commit details
  6. Copy the full SHA
    efd520e View commit details
  7. Copy the full SHA
    9bccf14 View commit details
  8. Copy the full SHA
    83edfad View commit details
25 changes: 16 additions & 9 deletions core/src/main/java/org/jruby/RubyDir.java
Original file line number Diff line number Diff line change
@@ -812,24 +812,31 @@ public static IRubyObject getHomeDirectoryPath(ThreadContext context, String use
throw runtime.newArgumentError("user " + user + " doesn't exist");
}

static final ByteList HOME = new ByteList(new byte[] {'H','O','M','E'}, false);

public static RubyString getHomeDirectoryPath(ThreadContext context) {
Ruby runtime = context.runtime;
IRubyObject systemHash = runtime.getObject().getConstant("ENV_JAVA");
RubyHash envHash = (RubyHash) runtime.getObject().getConstant("ENV");
IRubyObject home = envHash.op_aref(context, runtime.newString("HOME"));
final RubyString homeKey = RubyString.newStringShared(context.runtime, HOME);
return getHomeDirectoryPath(context, context.runtime.getENV().op_aref(context, homeKey));
}

if (home == null || home.isNil()) {
home = systemHash.callMethod(context, "[]", runtime.newString("user.home"));
static RubyString getHomeDirectoryPath(ThreadContext context, IRubyObject home) {
final Ruby runtime = context.runtime;

if (home == null || home == context.nil) {
IRubyObject ENV_JAVA = runtime.getObject().getConstant("ENV_JAVA");
home = ENV_JAVA.callMethod(context, "[]", runtime.newString("user.home"));
}

if (home == null || home.isNil()) {
home = envHash.op_aref(context, runtime.newString("LOGDIR"));
if (home == null || home == context.nil) {
RubyHash ENV = (RubyHash) runtime.getObject().getConstant("ENV");
home = ENV.op_aref(context, runtime.newString("LOGDIR"));
}

if (home == null || home.isNil()) {
if (home == null || home == context.nil) {
throw runtime.newArgumentError("user.home/LOGDIR not set");
}

return (RubyString) home;
}

}
112 changes: 67 additions & 45 deletions core/src/main/java/org/jruby/RubyFile.java
Original file line number Diff line number Diff line change
@@ -496,8 +496,8 @@ public IRubyObject inspect() {
return getRuntime().newString(val.toString());
}

private static String URI_PREFIX_STRING = "^(uri|jar|file|classpath):([^:/]{2,}:([^:/]{2,}:)?)?";
private static Pattern ROOT_PATTERN = Pattern.compile(URI_PREFIX_STRING + "/?/?$");
private static final String URI_PREFIX_STRING = "^(uri|jar|file|classpath):([^:/]{2,}:([^:/]{2,}:)?)?";
private static final Pattern ROOT_PATTERN = Pattern.compile(URI_PREFIX_STRING + "/?/?$");

/* File class methods */
@JRubyMethod(required = 1, optional = 1, meta = true)
@@ -607,7 +607,7 @@ public static IRubyObject chmod(ThreadContext context, IRubyObject recv, IRubyOb
throw runtime.newErrnoENOENTError(filename.toString());
}

if (0 != runtime.getPosix().chmod(filename.getAbsolutePath(), (int)mode.getLongValue())) {
if (0 != runtime.getPosix().chmod(filename.getAbsolutePath(), (int) mode.getLongValue())) {
throw runtime.newErrnoFromLastPOSIXErrno();
} else {
count++;
@@ -719,11 +719,10 @@ public static String dirname(ThreadContext context, String jfilename) {
index++;
}

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

@@ -938,7 +937,7 @@ public static IRubyObject lchmod(ThreadContext context, IRubyObject recv, IRubyO
RubyInteger mode = args[0].convertToInteger();
for (int i = 1; i < args.length; i++) {
JRubyFile file = file(args[i]);
if (0 != runtime.getPosix().lchmod(file.toString(), (int)mode.getLongValue())) {
if (0 != runtime.getPosix().lchmod(file.toString(), (int) mode.getLongValue())) {
throw runtime.newErrnoFromLastPOSIXErrno();
} else {
count++;
@@ -1473,6 +1472,10 @@ private static boolean isAbsolutePath(String path) {
startsWithDriveLetterOnWindows(path);
}

private static boolean isWindowsDriveLetter(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}

public static boolean startsWithDriveLetterOnWindows(String path) {
return (path != null)
&& Platform.IS_WINDOWS &&
@@ -1497,7 +1500,7 @@ static String adjustRootPathOnWindows(Ruby runtime, String path, String dir) {
// Basically, '/path' is treated as a *RELATIVE* path,
// relative to the current drive. '//path' is treated
// as absolute one.
if ((path.startsWith("/") && !(path.length() > 2 && path.charAt(2) == ':')) || path.startsWith("\\")) {
if ((startsWith(path, '/') && !(path.length() > 2 && path.charAt(2) == ':')) || startsWith(path, '\\')) {
if (path.length() > 1 && (path.charAt(1) == '/' || path.charAt(1) == '\\')) {
return path;
}
@@ -1550,11 +1553,8 @@ private void checkClosed(ThreadContext context) {
openFile.checkClosed();
}

private static boolean isWindowsDriveLetter(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
private static final Pattern PROTOCOL_PREFIX_PATTERN = Pattern.compile(URI_PREFIX_STRING);

private static Pattern PROTOCOL_PREFIX_PATTERN = Pattern.compile(URI_PREFIX_STRING);
private static IRubyObject expandPathInternal(ThreadContext context, IRubyObject recv, IRubyObject[] args, boolean expandUser, boolean canonicalize) {
Ruby runtime = context.runtime;

@@ -1592,22 +1592,28 @@ else if (protocol.find()) {
preFix = protocol.group();
int offset = protocol.end();
String extra = "";
if (relativePath.contains("file://")) {
if (relativePath.contains("file:///")) {
offset += 2;
extra = "//";
int index = relativePath.indexOf("file://");
if (index >= 0) {
index += 7; // "file://".length == 7
// chck if its "file:///"
if (relativePath.length() > index && relativePath.charAt(index) == '/') {
offset += 2; extra = "//";
}
else {
offset += 1;
extra = "/";
offset += 1; extra = "/";
}
}
else if ( ( preFix.equals("uri:classloader:") || preFix.equals("classpath:") )
&& relativePath.startsWith("//", offset) ) {
// on Windows "uri:classloader://home" ends up as "//home" - trying a network drive!
offset += 1; // skip one '/'
}
relativePath = canonicalizePath(relativePath.substring(offset));
if (Platform.IS_WINDOWS && !preFix.contains("file:") && startsWithDriveLetterOnWindows(relativePath)) {
// this is basically for classpath:/ and uri:classloader:/
relativePath = relativePath.substring(2).replace("\\", "/");
relativePath = relativePath.substring(2).replace('\\', '/');
}
return runtime.newString(preFix + extra + relativePath);
return concatStrings(runtime, preFix, extra, relativePath);
}

String[] uriParts = splitURI(relativePath);
@@ -1621,9 +1627,8 @@ else if (protocol.find()) {
if (uriParts != null) {
//If the path was an absolute classpath path, return it as-is.
if (uriParts[0].equals("classpath:")) {
return runtime.newString(preFix + relativePath + postFix);
return concatStrings(runtime, preFix, relativePath, postFix);
}

relativePath = uriParts[1];
}

@@ -1662,7 +1667,7 @@ else if (protocol.find()) {
// If the path isn't absolute, then prepend the current working
// directory to the path.
if (!startsWithSlashNotOnWindows && !startsWithDriveLetterOnWindows(cwd)) {
if ("".equals(cwd)) cwd = ".";
if (cwd.length() == 0) cwd = ".";
cwd = JRubyFile.create(runtime.getCurrentDirectory(), cwd).getAbsolutePath();
}
}
@@ -1732,23 +1737,29 @@ else if (protocol.find()) {
}
}
if (postFix.contains("..")) {
postFix = "!" + canonicalizePath(postFix.substring(1));
if (Platform.IS_WINDOWS && postFix.startsWith("!")) {
postFix = postFix.replace("\\", "/");
postFix = '!' + canonicalizePath(postFix.substring(1));
if (Platform.IS_WINDOWS /* && startsWith(postFix, '!') */) {
postFix = postFix.replace('\\', '/');
if (startsWithDriveLetterOnWindows(postFix.substring(1))) {
postFix = "!" + postFix.substring(3);
postFix = '!' + postFix.substring(3);
}
}
}
return runtime.newString(preFix + realPath + postFix);
return concatStrings(runtime, preFix, realPath, postFix);
}

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

private static String canonicalizePath(String path) {
try {
return new File(path).getCanonicalPath();
} catch (IOException ignore) {
return path;
}
catch (IOException ignore) { return path; }
}

public static String[] splitURI(String path) {
@@ -1794,7 +1805,7 @@ public static String expandUserPath(ThreadContext context, String path) {

// FIXME: The variations of expand* and need for each to have a boolean discriminator makes
// this code ripe for refactoring...
public static String expandUserPath(ThreadContext context, String path, boolean raiseOnRelativePath) {
public static String expandUserPath(ThreadContext context, String path, final boolean raiseOnRelativePath) {
int pathLength = path.length();

if (pathLength >= 1 && path.charAt(0) == '~') {
@@ -1804,10 +1815,11 @@ public static String expandUserPath(ThreadContext context, String path, boolean
if (userEnd == -1) {
if (pathLength == 1) {
// Single '~' as whole path to expand
checkHome(context);
path = RubyDir.getHomeDirectoryPath(context).toString();
path = RubyDir.getHomeDirectoryPath(context, checkHome(context)).toString();

if (raiseOnRelativePath && !isAbsolutePath(path)) throw context.runtime.newArgumentError("non-absolute home");
if (raiseOnRelativePath && !isAbsolutePath(path)) {
throw context.runtime.newArgumentError("non-absolute home");
}
} else {
// No directory delimeter. Rest of string is username
userEnd = pathLength;
@@ -1816,11 +1828,11 @@ public static String expandUserPath(ThreadContext context, String path, boolean

if (userEnd == 1) {
// '~/...' as path to expand
checkHome(context);
path = RubyDir.getHomeDirectoryPath(context).toString() +
path.substring(1);
path = RubyDir.getHomeDirectoryPath(context, checkHome(context)).toString() + path.substring(1);

if (raiseOnRelativePath && !isAbsolutePath(path)) throw context.runtime.newArgumentError("non-absolute home");
if (raiseOnRelativePath && !isAbsolutePath(path)) {
throw context.runtime.newArgumentError("non-absolute home");
}
} else if (userEnd > 1){
// '~user/...' as path to expand
String user = path.substring(1, userEnd);
@@ -1833,7 +1845,9 @@ public static String expandUserPath(ThreadContext context, String path, boolean
path = dir + (pathLength == userEnd ? "" : path.substring(userEnd));

// getpwd (or /etc/passwd fallback) returns a home which is not absolute!!! [mecha-unlikely]
if (raiseOnRelativePath && !isAbsolutePath(path)) throw context.runtime.newArgumentError("non-absolute home of " + user);
if (raiseOnRelativePath && !isAbsolutePath(path)) {
throw context.runtime.newArgumentError("non-absolute home of " + user);
}
}
}
return path;
@@ -1881,7 +1895,7 @@ public static String canonicalize(String path) {

private static String canonicalize(String canonicalPath, String remaining) {
if (remaining == null) {
if ("".equals(canonicalPath)) return "/";
if (canonicalPath.length() == 0) return "/";
// compensate for missing slash after drive letter on windows
if (startsWithDriveLetterOnWindows(canonicalPath) && canonicalPath.length() == 2) {
canonicalPath += '/';
@@ -1932,13 +1946,13 @@ private static String canonicalize(String canonicalPath, String remaining) {
* Check if HOME environment variable is not nil nor empty
* @param context
*/
private static void checkHome(ThreadContext context) {
private static RubyString checkHome(ThreadContext context) {
Ruby runtime = context.runtime;
RubyHash env = runtime.getENV();
String home = (String) env.get(runtime.newString("HOME"));
if (home == null || home.length() == 0) {
IRubyObject home = runtime.getENV().fastARef(RubyString.newStringShared(runtime, RubyDir.HOME));
if (home == null || home == context.nil || ((RubyString) home).size() == 0) {
throw runtime.newArgumentError("couldn't find HOME environment -- expanding `~'");
}
return (RubyString) home;
}

private static RubyString doJoin(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
@@ -2034,6 +2048,14 @@ private static boolean startsWith(final CharSequence str, final String prefix) {
return true;
}

private static boolean startsWith(final CharSequence str, final char c) {
return ( str.length() < 1 ) ? false : 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;
}

// without any char[] array copying, also StringBuilder only has lastIndexOf(String)
private static int lastIndexOf(final CharSequence str, final char c, int index) {
while ( index >= 0 ) {
3 changes: 1 addition & 2 deletions core/src/main/java/org/jruby/RubyString.java
Original file line number Diff line number Diff line change
@@ -2313,8 +2313,7 @@ public RubyString crypt(ThreadContext context, IRubyObject other) {

/* RubyString aka rb_string_value */
public static RubyString stringValue(IRubyObject object) {
return (RubyString) (object instanceof RubyString ? object :
object.convertToString());
return (RubyString) (object instanceof RubyString ? object : object.convertToString());
}

/** rb_str_sub / rb_str_sub_bang
20 changes: 10 additions & 10 deletions core/src/main/java/org/jruby/runtime/Helpers.java
Original file line number Diff line number Diff line change
@@ -2636,20 +2636,20 @@ public static String decodeByteList(Ruby runtime, ByteList value) {
Encoding encoding = value.getEncoding();

if (encoding == UTF8Encoding.INSTANCE) {
return RubyEncoding.decodeUTF8(unsafeBytes, begin, length);
}
return RubyEncoding.decodeUTF8(unsafeBytes, begin, length);
}

Charset charset = runtime.getEncodingService().charsetForEncoding(encoding);
Charset charset = runtime.getEncodingService().charsetForEncoding(encoding);

if (charset == null) {
try {
return new String(unsafeBytes, begin, length, encoding.toString());
} catch (UnsupportedEncodingException uee) {
return value.toString();
}
if (charset == null) {
try {
return new String(unsafeBytes, begin, length, encoding.toString());
} catch (UnsupportedEncodingException uee) {
return value.toString();
}
}

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

/**