forked from Mirror/wren
File.realPath().
Not tested yet, because we can't create symlinks from Wren and I don't want to check symlinks into the repo, but it seems to do the right thing.
This commit is contained in:
@ -51,6 +51,15 @@ No encoding or decoding is done. If the file is UTF-8, then the resulting
|
||||
string will be a UTF-8 string. Otherwise, it will be a string of bytes in
|
||||
whatever encoding the file uses.
|
||||
|
||||
### File.**realPath**(path)
|
||||
|
||||
Resolves `path`, traversing symlinks and removining any unneeded `./` and `../`
|
||||
components. Returns the canonical absolute path to the file.
|
||||
|
||||
:::wren
|
||||
var path = "/some/./symlink/a/../b/file.txt"
|
||||
System.print(File.realPath(path)) //> /real/path/a/file.txt
|
||||
|
||||
### File.**size**(path)
|
||||
|
||||
Returns the size in bytes of the contents of the file at `path`.
|
||||
|
||||
@ -17,6 +17,7 @@ extern void fileSizePath(WrenVM* vm);
|
||||
extern void fileClose(WrenVM* vm);
|
||||
extern void fileDescriptor(WrenVM* vm);
|
||||
extern void fileReadBytes(WrenVM* vm);
|
||||
extern void fileRealPath(WrenVM* vm);
|
||||
extern void fileSize(WrenVM* vm);
|
||||
extern void fileStat(WrenVM* vm);
|
||||
extern void fileWriteBytes(WrenVM* vm);
|
||||
@ -115,6 +116,7 @@ static ModuleRegistry modules[] =
|
||||
FINALIZER(fileFinalize)
|
||||
STATIC_METHOD("delete_(_,_)", fileDelete)
|
||||
STATIC_METHOD("open_(_,_,_)", fileOpen)
|
||||
STATIC_METHOD("realPath_(_,_)", fileRealPath)
|
||||
STATIC_METHOD("sizePath_(_,_)", fileSizePath)
|
||||
METHOD("close_(_)", fileClose)
|
||||
METHOD("descriptor", fileDescriptor)
|
||||
|
||||
@ -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"
|
||||
|
||||
3
test/io/file/real_path_nonexistent.wren
Normal file
3
test/io/file/real_path_nonexistent.wren
Normal file
@ -0,0 +1,3 @@
|
||||
import "io" for File
|
||||
|
||||
File.realPath("nonexistent") // expect runtime error: no such file or directory
|
||||
6
test/io/file/real_path_wrong_arg_type.wren
Normal file
6
test/io/file/real_path_wrong_arg_type.wren
Normal file
@ -0,0 +1,6 @@
|
||||
import "io" for File
|
||||
|
||||
File.realPath(123) // expect runtime error: Path must be a string.
|
||||
|
||||
// TODO: Write success case tests too when we have an API to create symlinks
|
||||
// from Wren.
|
||||
Reference in New Issue
Block a user