feat: add File.realPath() to resolve symlinks and normalize paths
Implement a new static method `File.realPath(path)` that resolves the given path by traversing symlinks and removing redundant `./` and `../` components, returning the canonical absolute path. The implementation uses libuv's `uv_fs_realpath` via an asynchronous callback pattern consistent with other File operations. Includes documentation, foreign method declarations, and two error-case tests for nonexistent paths and wrong argument types.
This commit is contained in:
@@ -302,6 +302,23 @@ void fileReadBytes(WrenVM* vm)
|
||||
fileReadBytesCallback);
|
||||
}
|
||||
|
||||
static void realPathCallback(uv_fs_t* request)
|
||||
{
|
||||
if (handleRequestError(request)) return;
|
||||
|
||||
wrenEnsureSlots(getVM(), 3);
|
||||
wrenSetSlotString(getVM(), 2, (char*)request->ptr);
|
||||
schedulerResume(freeRequest(request), true);
|
||||
schedulerFinishResume();
|
||||
}
|
||||
|
||||
void fileRealPath(WrenVM* vm)
|
||||
{
|
||||
const char* path = wrenGetSlotString(vm, 1);
|
||||
uv_fs_t* request = createRequest(wrenGetSlotValue(vm, 2));
|
||||
uv_fs_realpath(getLoop(), request, path, realPathCallback);
|
||||
}
|
||||
|
||||
// Called by libuv when the stat call completes.
|
||||
static void statCallback(uv_fs_t* request)
|
||||
{
|
||||
|
||||
@@ -91,6 +91,14 @@ foreign class File {
|
||||
return File.open(path) {|file| file.readBytes(file.size) }
|
||||
}
|
||||
|
||||
// TODO: This works for directories too, so putting it on File is kind of
|
||||
// lame. Consider reorganizing these classes some.
|
||||
static realPath(path) {
|
||||
ensurePath_(path)
|
||||
realPath_(path, Fiber.current)
|
||||
return Scheduler.runNextScheduled_()
|
||||
}
|
||||
|
||||
static size(path) {
|
||||
ensurePath_(path)
|
||||
sizePath_(path, Fiber.current)
|
||||
@@ -158,6 +166,7 @@ foreign class File {
|
||||
|
||||
foreign static delete_(path, fiber)
|
||||
foreign static open_(path, flags, fiber)
|
||||
foreign static realPath_(path, fiber)
|
||||
foreign static sizePath_(path, fiber)
|
||||
|
||||
foreign close_(fiber)
|
||||
|
||||
@@ -93,6 +93,14 @@ static const char* ioModuleSource =
|
||||
" return File.open(path) {|file| file.readBytes(file.size) }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // TODO: This works for directories too, so putting it on File is kind of\n"
|
||||
" // lame. Consider reorganizing these classes some.\n"
|
||||
" static realPath(path) {\n"
|
||||
" ensurePath_(path)\n"
|
||||
" realPath_(path, Fiber.current)\n"
|
||||
" return Scheduler.runNextScheduled_()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static size(path) {\n"
|
||||
" ensurePath_(path)\n"
|
||||
" sizePath_(path, Fiber.current)\n"
|
||||
@@ -160,6 +168,7 @@ static const char* ioModuleSource =
|
||||
"\n"
|
||||
" foreign static delete_(path, fiber)\n"
|
||||
" foreign static open_(path, flags, fiber)\n"
|
||||
" foreign static realPath_(path, fiber)\n"
|
||||
" foreign static sizePath_(path, fiber)\n"
|
||||
"\n"
|
||||
" foreign close_(fiber)\n"
|
||||
|
||||
Reference in New Issue
Block a user