You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
File.realpath on Windows: 8.3 short names are not expanded, and MRI's behaviour there is unwitnessed #636
On the windows CI lane, File.realdirpath of a path under the runner's temp directory answers
C:/Users/RUNNER~1/AppData/Local/Temp/.../file
while Go's filepath.EvalSymlinks — which TestFileRealdirpath had been using as its oracle — answers
C:/Users/runneradmin/AppData/Local/Temp/.../file
RUNNER~1 is the 8.3 short name of runneradmin. Go's EvalSymlinks expands it on Windows (it calls GetFinalPathNameByHandle); realpath_rec in internal/vm/file.go resolves symlinks and .. but leaves the short name alone.
What is not known
Whether MRI expands it. MRI's rb_check_realpath_internal takes a different path on Windows from the emulated walk, and there is no Windows MRI on this development host to witness against. Both answers are defensible from reading alone:
the short and long names denote the same file, so neither is "wrong";
but File.realpath's contract is a canonical path, and two canonical paths for one file defeats the purpose.
What was done meanwhile
TestFileRealdirpath no longer compares the two canonicalisers on Windows, because they disagree by construction there and the comparison was testing Go's normalisation rather than ours. On POSIX the full equality still holds; on Windows the test asserts the properties that hold either way — absolute, forward-slashed, naming the file. The assertion was not deleted or skipped: it still exercises realdirpath on the windows lane.
Closing this needs a witness: run ruby -e 'p File.realpath(ENV["TMP"] + "/x")' on a Windows box where the temp path contains an 8.3 component, and make rbgo agree.
Related: #635 (File::Stat members Windows cannot supply), #633 (per-platform errno numbers and texts).
Reproduced on a runner. This was carried as "the two canonicalisers disagree
by construction, and MRI's behaviour is unwitnessed"; three assertions added in #685 now witness it directly, on Dir.pwd rather than on File.realdirpath,
so the defect has a live reproduction rather than only a reading.
From the windows lane of runs/36250946599 (job 108428733698), with the
process's working directory set to t.TempDir():
So the short name is not confined to realpath_rec: it comes straight out of GetCurrentDirectory through os.Getwd, which means Dir.pwd, File.expand_path and File.absolute_path all inherit it, not just the
realpath family. The expectation in those two lines is Go's filepath.EvalSymlinks — the same oracle that disagreed here originally — so this
is the same disagreement, one layer lower down.
A second, separate Windows fact showed up beside it in the same test, and it is not the 8.3 issue:
dir_getwd_test.go:248: Dir.pwd through a symlink = "C:/.../002/link"
want the physical path "C:/.../001"
GetCurrentDirectory does not resolve a symlink or junction in the path it
reports, so a working directory entered through a link is reported as the link.
On POSIX getcwd(3) always answers the physical path, and MRI's specs rely on
that. Whether rb_w32_ugetcwd resolves it is unwitnessed here, the same gap this
issue names — worth recording on this issue since the fix for one is likely the
fix for both.
TestDirPwdIntact skips on Windows naming this issue rather than canonicalising
the expected path, so as not to bake either behaviour into a test. What this issue
still needs is unchanged: a Windows MRI witness for Dir.pwd, File.expand_path and File.realpath on a short-named and on a symlinked path.
Activity
test: stop asserting POSIX-only shapes on the windows lane
README: the subsystems that landed since the feature list was written…
file+filetest+exception: FileTest, the Errno subsystem, realpath_rec …
README: the subsystems that landed since the feature list was written…
README: the subsystems that landed since the feature list was written…
README: measured ruby/spec conformance (21,982 vs the 15,400+ claimed…
Windows: narrow two over-specified assertions, skip the canonical-pat…
tannevaled commentedon Sep 26, 2026
Reproduced on a runner. This was carried as "the two canonicalisers disagree
by construction, and MRI's behaviour is unwitnessed"; three assertions added in
#685 now witness it directly, on
Dir.pwdrather than onFile.realdirpath,so the defect has a live reproduction rather than only a reading.
From the windows lane of
runs/36250946599(job108428733698), with theprocess's working directory set to
t.TempDir():So the short name is not confined to
realpath_rec: it comes straight out ofGetCurrentDirectorythroughos.Getwd, which meansDir.pwd,File.expand_pathandFile.absolute_pathall inherit it, not just therealpath family. The expectation in those two lines is Go's
filepath.EvalSymlinks— the same oracle that disagreed here originally — so thisis the same disagreement, one layer lower down.
A second, separate Windows fact showed up beside it in the same test, and it is
not the 8.3 issue:
GetCurrentDirectorydoes not resolve a symlink or junction in the path itreports, so a working directory entered through a link is reported as the link.
On POSIX
getcwd(3)always answers the physical path, and MRI's specs rely onthat. Whether
rb_w32_ugetcwdresolves it is unwitnessed here, the same gap thisissue names — worth recording on this issue since the fix for one is likely the
fix for both.
TestDirPwdIntactskips on Windows naming this issue rather than canonicalisingthe expected path, so as not to bake either behaviour into a test. What this issue
still needs is unchanged: a Windows MRI witness for
Dir.pwd,File.expand_pathandFile.realpathon a short-named and on a symlinked path.Dir.pwd raises when the working directory is gone (ruby_getcwd), and …