Skip to content

Commit

Permalink
Merge pull request jruby#7932 from headius/backport_main_cwd_fix
Browse files Browse the repository at this point in the history
Store absolute path of main at load time
  • Loading branch information
headius authored Sep 10, 2023
2 parents 703292e + 39250a0 commit 02531b3
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 7 deletions.
3 changes: 3 additions & 0 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,9 @@ public void runFromMain(InputStream inputStream, String filename) {
getGlobalVariables().define("$PROGRAM_NAME", d, GLOBAL);
getGlobalVariables().define("$0", d, GLOBAL);

// set main script and canonical path for require_relative use
loadService.setMainScript(filename, getCurrentDirectory());

for (Map.Entry<String, String> entry : config.getOptionGlobals().entrySet()) {
final IRubyObject varvalue;
if (entry.getValue() != null) {
Expand Down
16 changes: 11 additions & 5 deletions core/src/main/java/org/jruby/RubyKernel.java
Original file line number Diff line number Diff line change
Expand Up @@ -1036,10 +1036,11 @@ public static IRubyObject require_relative(ThreadContext context, IRubyObject re
throw runtime.newLoadError("cannot infer basepath");
}

file = runtime.getLoadService().getPathForLocation(file);

RubyClass fileClass = runtime.getFile();
IRubyObject realpath = RubyFile.realpath(context, fileClass, runtime.newString(file));
IRubyObject dirname = RubyFile.dirname(context, fileClass,
realpath);
IRubyObject dirname = RubyFile.dirname(context, fileClass, realpath);
IRubyObject absoluteFeature = RubyFile.expand_path(context, fileClass, relativePath, dirname);

return RubyKernel.require(context, runtime.getKernel(), absoluteFeature, Block.NULL_BLOCK);
Expand Down Expand Up @@ -1970,10 +1971,15 @@ public static IRubyObject __method__(ThreadContext context, IRubyObject recv) {

@JRubyMethod(name = "__dir__", module = true, visibility = PRIVATE, reads = FILENAME)
public static IRubyObject __dir__(ThreadContext context, IRubyObject recv) {
Ruby runtime = context.runtime;

// NOTE: not using __FILE__ = context.getFile() since it won't work with JIT
final String __FILE__ = context.getSingleBacktrace().getFileName();
RubyString path = RubyFile.expandPathInternal(context, RubyString.newString(context.runtime, __FILE__), null, false, true);
return RubyString.newString(context.runtime, RubyFile.dirname(context, path.asJavaString()));
String __FILE__ = context.getSingleBacktrace().getFileName();

__FILE__ = runtime.getLoadService().getPathForLocation(__FILE__);

RubyString path = RubyFile.expandPathInternal(context, RubyString.newString(runtime, __FILE__), null, false, true);
return RubyString.newString(runtime, RubyFile.dirname(context, path.asJavaString()));
}

@JRubyMethod(module = true)
Expand Down
5 changes: 4 additions & 1 deletion core/src/main/java/org/jruby/RubyThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
import org.jruby.runtime.backtrace.FrameType;
import org.jruby.runtime.backtrace.RubyStackTraceElement;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.LoadService;
import org.jruby.util.ByteList;
import org.jruby.util.StringSupport;
import org.jruby.util.io.BlockingIO;
Expand Down Expand Up @@ -482,7 +483,9 @@ public Location(Ruby runtime, RubyClass klass, RubyStackTraceElement element) {

@JRubyMethod
public IRubyObject absolute_path(ThreadContext context) {
return context.runtime.newString(element.getFileName());
Ruby runtime = context.runtime;
return runtime.newString(
runtime.getLoadService().getPathForLocation(element.getFileName()));
}

@JRubyMethod
Expand Down
34 changes: 34 additions & 0 deletions core/src/main/java/org/jruby/runtime/load/LoadService.java
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ public String[] getSuffixes() {
protected final Ruby runtime;
protected LibrarySearcher librarySearcher;

protected String mainScript;
protected String mainScriptPath;

public LoadService(Ruby runtime) {
this.runtime = runtime;
if (RubyInstanceConfig.DEBUG_LOAD_TIMINGS) {
Expand Down Expand Up @@ -1028,6 +1031,37 @@ protected String resolveLoadName(LoadServiceResource foundResource, String previ
return resolveLoadName(foundResource, previousPath);
}

public String getMainScript() {
return mainScript;
}

public String getMainScriptPath() {
return mainScriptPath;
}

public void setMainScript(String filename, String cwd) {
this.mainScript = filename;
File mainFile = new File(filename);

if (!mainFile.isAbsolute()) {
mainFile = new File(cwd, filename);
}

if (mainFile.exists()) {
this.mainScriptPath = mainFile.getAbsolutePath();
} else {
this.mainScriptPath = filename;
}
}

public String getPathForLocation(String filename) {
if (filename.equals(mainScript)) {
return mainScriptPath;
}

return filename;
}

//<editor-fold desc="Deprecated" defaultstate="collapsed">
@Deprecated
protected String getFileName(JRubyFile file, String namePlusSuffix) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ fails:Thread::Backtrace::Location#absolute_path returns a canonical path without
fails:Thread::Backtrace::Location#absolute_path returns a canonical path without symlinks, even when __FILE__ is removed
fails:Thread::Backtrace::Location#absolute_path canonicalization returns a canonical path without symlinks, even when __FILE__ does not
fails:Thread::Backtrace::Location#absolute_path canonicalization returns a canonical path without symlinks, even when __FILE__ is removed
fails:Thread::Backtrace::Location#absolute_path returns an absolute path when using a relative main script path
fails:Thread::Backtrace::Location#absolute_path when used in a core method returns nil

0 comments on commit 02531b3

Please sign in to comment.