1
0
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:
Bob Nystrom
2016-02-27 15:53:02 -08:00
parent e6b48de598
commit 1e4b9e5175
7 changed files with 55 additions and 0 deletions

View File

@ -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`.

View File

@ -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)

View File

@ -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)
{

View File

@ -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)

View File

@ -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"

View File

@ -0,0 +1,3 @@
import "io" for File
File.realPath("nonexistent") // expect runtime error: no such file or directory

View 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.