Skip to content

Commit d7b3775

Browse files
committed
Fix the absolute path of the main script after chdir
* Fixes #2709
1 parent 0c7f6b2 commit d7b3775

File tree

5 files changed

+28
-8
lines changed

5 files changed

+28
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Compatibility:
2929
* Fix `Kernel#sprintf` formatting for `%c` when used non-ASCII encoding (#2369, @andrykonchin).
3030
* Fix `Kernel#sprintf` argument casting for `%c` (@andrykonchin).
3131
* Implement the `rb_enc_strlen` function for use by native extensions (@nirvdrum).
32+
* Fix the absolute path of the main script after chdir (#2709, @eregon).
3233

3334
Performance:
3435

src/main/java/org/truffleruby/core/kernel/KernelNodes.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.oracle.truffle.api.interop.InteropLibrary;
2323
import com.oracle.truffle.api.interop.UnsupportedMessageException;
2424
import com.oracle.truffle.api.object.PropertyGetter;
25+
import com.oracle.truffle.api.source.Source;
2526
import com.oracle.truffle.api.strings.AbstractTruffleString;
2627
import com.oracle.truffle.api.strings.TruffleString;
2728
import com.oracle.truffle.api.utilities.AssumedValue;
@@ -300,9 +301,9 @@ protected RubyString getCallerPath(Object feature,
300301
coreExceptions().loadError("cannot infer basepath", featureString, this));
301302
}
302303

303-
String sourcePath = getLanguage().getSourcePath(sourceSection.getSource());
304-
305-
sourcePath = getContext().getFeatureLoader().canonicalize(sourcePath);
304+
Source source = sourceSection.getSource();
305+
String sourcePath = getLanguage().getSourcePath(source);
306+
sourcePath = getContext().getFeatureLoader().canonicalize(sourcePath, source);
306307

307308
featurePath = getContext().getFeatureLoader().dirname(sourcePath) + "/" + featureString;
308309
}
@@ -394,7 +395,7 @@ protected RubyString canonicalPath(Object string,
394395
@Cached TruffleString.FromJavaStringNode fromJavaStringNode) {
395396
final String expandedPath = getContext()
396397
.getFeatureLoader()
397-
.canonicalize(RubyGuards.getJavaString(string));
398+
.canonicalize(RubyGuards.getJavaString(string), null);
398399
return createString(fromJavaStringNode, expandedPath, Encodings.UTF_8);
399400
}
400401

src/main/java/org/truffleruby/core/thread/ThreadBacktraceLocationNodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public static Object getAbsolutePath(SourceSection sourceSection, RubyBaseNode n
6666
return nil;
6767
} else if (source.getPath() != null) { // A normal file
6868
final String path = language.getSourcePath(source);
69-
final String canonicalPath = context.getFeatureLoader().canonicalize(path);
69+
final String canonicalPath = context.getFeatureLoader().canonicalize(path, source);
7070
var cachedRope = language.tstringCache.getTString(TStringUtils.utf8TString(canonicalPath),
7171
Encodings.UTF_8);
7272
return node.createString(cachedRope, Encodings.UTF_8);

src/main/java/org/truffleruby/language/loader/FeatureLoader.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464

6565
public class FeatureLoader {
6666

67+
private static final int PATH_MAX = 1024; // jnr-posix hard codes this value
68+
private static final String[] EXTENSIONS = new String[]{ TruffleRuby.EXTENSION, RubyLanguage.CEXT_EXTENSION };
69+
6770
private final RubyContext context;
6871
private final RubyLanguage language;
6972

@@ -80,9 +83,9 @@ public class FeatureLoader {
8083

8184
private String cwd = null;
8285
private Object getcwd;
83-
private static final int PATH_MAX = 1024; // jnr-posix hard codes this value
8486

85-
private static final String[] EXTENSIONS = new String[]{ TruffleRuby.EXTENSION, RubyLanguage.CEXT_EXTENSION };
87+
private Source mainScriptSource;
88+
private String mainScriptAbsolutePath;
8689

8790
public FeatureLoader(RubyContext context, RubyLanguage language) {
8891
this.context = context;
@@ -95,6 +98,13 @@ public void initialize(NativeConfiguration nativeConfiguration, TruffleNFIPlatfo
9598
}
9699
}
97100

101+
public void setMainScript(Source source, String absolutePath) {
102+
assert mainScriptSource == null;
103+
assert mainScriptAbsolutePath == null;
104+
mainScriptSource = source;
105+
mainScriptAbsolutePath = absolutePath;
106+
}
107+
98108
public void addAutoload(RubyConstant autoloadConstant) {
99109
final String autoloadPath = autoloadConstant.getAutoloadConstant().getAutoloadPath();
100110
final String basename = basenameWithoutExtension(autoloadPath);
@@ -229,7 +239,13 @@ private String makeAbsolute(String path) {
229239
}
230240
}
231241

232-
public String canonicalize(String path) {
242+
public String canonicalize(String path, Source source) {
243+
// Special case for the main script which has a relative Source#getPath():
244+
// We need to resolve it correctly, even if the CWD changed since then.
245+
if (source != null && source.equals(mainScriptSource)) {
246+
return mainScriptAbsolutePath;
247+
}
248+
233249
// First, make the path absolute, by expanding relative to the context CWD
234250
// Otherwise, getCanonicalPath() uses user.dir as CWD which is incorrect.
235251
final String absolutePath = makeAbsolute(path);

src/main/java/org/truffleruby/language/loader/MainLoader.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ public RubySource loadFromFile(Env env, Node currentNode, String mainPath) throw
100100

101101
final Source mainSource = fileLoader.buildSource(file, mainPath, sourceTString, false, true);
102102

103+
context.getFeatureLoader().setMainScript(mainSource, file.getCanonicalFile().getPath());
104+
103105
return new RubySource(mainSource, mainPath, sourceTString);
104106
}
105107

0 commit comments

Comments
 (0)