Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
Expand Up @@ -3583,7 +3583,7 @@ public RaiseException newArgumentError(String message) {
public RaiseException newArgumentError(int got, int expected) {
return newArgumentError(got, expected, expected);
}

public RaiseException newArgumentError(int got, int min, int max) {
if (min == max) {
return newRaiseException(getArgumentError(), "wrong number of arguments (given " + got + ", expected " + min + ")");
Expand Down Expand Up @@ -4929,6 +4929,10 @@ public RubyBinding getTopLevelBinding() {
return topLevelBinding;
}

public void setChdirThread(RubyThread thread) { this.chdirCurrentThread = thread; }

public RubyThread getChdirThread() { return this.chdirCurrentThread; }

static class FStringEqual {
RubyString string;
public boolean equals(Object other) {
Expand Down Expand Up @@ -5505,6 +5509,8 @@ public RubyClass getData() {
private RubyModule precisionModule;
private RubyModule errnoModule;

private RubyThread chdirCurrentThread;

private DynamicMethod privateMethodMissing, protectedMethodMissing, variableMethodMissing,
superMethodMissing, normalMethodMissing, defaultMethodMissing, defaultModuleMethodMissing,
respondTo, respondToMissing;
Expand Down
40 changes: 31 additions & 9 deletions core/src/main/java/org/jruby/RubyDir.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.concurrent.locks.ReentrantLock;

import jnr.posix.FileStat;
import jnr.posix.POSIX;
Expand Down Expand Up @@ -251,7 +251,7 @@ private static void globOptions(ThreadContext context, IRubyObject[] args, Strin

if (rets[0] == null || rets[0].isNil()) {
options.base = "";
return;
return;
}

RubyString path = RubyFile.get_path(context, rets[0]);
Expand Down Expand Up @@ -435,24 +435,43 @@ private static void checkDirIsTwoSlashesOnWindows(Ruby runtime, String path) {
@JRubyMethod(optional = 1, checkArity = false, meta = true)
public static IRubyObject chdir(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
int argc = Arity.checkArgumentCount(context, args, 0, 1);

Ruby runtime = context.runtime;
RubyHash env = context.runtime.getENV();

if(argc == 0 && env.op_aref(context, runtime.newString("LOG_DIR")).isNil() &&
env.op_aref(context, runtime.newString("HOME")).isNil()){
throw runtime.newArgumentError("HOME/LOGDIR not set");
}

RubyString path = argc == 1 ?
StringSupport.checkEmbeddedNulls(runtime, RubyFile.get_path(context, args[0])) :
getHomeDirectoryPath(context);
StringSupport.checkEmbeddedNulls(runtime, RubyFile.get_path(context, args[0])) :
getHomeDirectoryPath(context);

String adjustedPath = RubyFile.adjustRootPathOnWindows(runtime, path.asJavaString(), null);
checkDirIsTwoSlashesOnWindows(runtime, adjustedPath);

adjustedPath = getExistingDir(runtime, adjustedPath).canonicalPath();

if (context.runtime.getChdirThread() != null && context.getThread() != context.runtime.getChdirThread()) {
throw runtime.newRuntimeError("conflicting chdir during another chdir block");
}

if(!block.isGiven() && context.runtime.getChdirThread() != null) {
context.runtime.getWarnings().warn("conflicting chdir during another chdir block");
}

IRubyObject result;

if (block.isGiven()) {
context.runtime.setChdirThread(context.getThread());
final String oldCwd = runtime.getCurrentDirectory();
// FIXME: Don't allow multiple threads to do this at once

runtime.setCurrentDirectory(adjustedPath);
try {
result = block.yield(context, path);
} finally {
context.runtime.setChdirThread(null);
getExistingDir(runtime, oldCwd); // needed in case the block deleted the oldCwd
runtime.setCurrentDirectory(oldCwd);
}
Expand All @@ -479,7 +498,7 @@ public static IRubyObject chroot(IRubyObject recv, IRubyObject path) {
public RubyArray children(ThreadContext context) {
return entriesCommon(context, path, encoding, true);
}

@JRubyMethod(name = "children", meta = true)
public static RubyArray children(ThreadContext context, IRubyObject recv, IRubyObject arg) {
return children(context, recv, arg, context.nil);
Expand Down Expand Up @@ -1141,7 +1160,9 @@ private static RubyString newFilesystemString(Ruby runtime, String home) {

public static RubyString getHomeDirectoryPath(ThreadContext context) {
final RubyString homeKey = RubyString.newStringShared(context.runtime, HOME);
return getHomeDirectoryPath(context, context.runtime.getENV().op_aref(context, homeKey));
IRubyObject home = context.runtime.getENV().op_aref(context, homeKey);

return getHomeDirectoryPath(context, home);
}

public static Optional<String> getHomeFromEnv(Ruby runtime) {
Expand All @@ -1158,15 +1179,16 @@ public static Optional<String> getHomeFromEnv(Ruby runtime) {
private static final ByteList user_home = new ByteList(new byte[] {'u','s','e','r','.','h','o','m','e'}, false);

static RubyString getHomeDirectoryPath(ThreadContext context, IRubyObject home) {
final Ruby runtime = context.runtime;
Ruby runtime = context.runtime;
RubyHash env = context.runtime.getENV();

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

if (home == null || home == context.nil) {
home = context.runtime.getENV().op_aref(context, runtime.newString("LOGDIR"));
home = env.op_aref(context, runtime.newString("LOGDIR"));
}

if (home == null || home == context.nil) {
Expand Down
1 change: 0 additions & 1 deletion test/mri/excludes/TestDir.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
exclude :test_chdir, "uses user.home as a fallback home path"
exclude :test_glob, '\0 delimiter is not handled'
exclude :test_glob_gc_for_fd, "tweaks rlimit and never restores it, depends on GC effects"
exclude :test_glob_too_may_open_files, "our glob does not appear to open files, and so the expected EMFILE does not happen"