Merge pull request #244 from vibe-d/osx_listdirectory_fix
Add `DirectoryListMode.shallowDirectories` and fix macOS `fstatat` declaration
This commit is contained in:
commit
58f6b06e2d
|
@ -515,11 +515,13 @@ enum FileMode {
|
||||||
|
|
||||||
enum DirectoryListMode {
|
enum DirectoryListMode {
|
||||||
/// Only iterate the directory itself
|
/// Only iterate the directory itself
|
||||||
shallow,
|
shallow = 0,
|
||||||
|
/// Only iterate over directories directly within the given directory
|
||||||
|
shallowDirectories = 1<<1,
|
||||||
/// Iterate recursively (depth-first, pre-order)
|
/// Iterate recursively (depth-first, pre-order)
|
||||||
recursive,
|
recursive = 1<<0,
|
||||||
/// Iterate only directories recursively (depth-first, pre-order)
|
/// Iterate only directories recursively (depth-first, pre-order)
|
||||||
recursiveDirectories,
|
recursiveDirectories = recursive | shallowDirectories,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -948,7 +950,8 @@ private void performListDirectory(ListDirectoryRequest req)
|
||||||
@trusted nothrow {
|
@trusted nothrow {
|
||||||
scope (exit) req.channel.close();
|
scope (exit) req.channel.close();
|
||||||
|
|
||||||
auto dirs_only = req.spanMode == DirectoryListMode.recursiveDirectories;
|
auto dirs_only = !!(req.spanMode & DirectoryListMode.shallowDirectories);
|
||||||
|
auto rec = !!(req.spanMode & DirectoryListMode.recursive);
|
||||||
|
|
||||||
bool scanRec(NativePath path)
|
bool scanRec(NativePath path)
|
||||||
{
|
{
|
||||||
|
@ -1001,7 +1004,7 @@ private void performListDirectory(ListDirectoryRequest req)
|
||||||
try req.channel.put(ListDirectoryData(fi, null));
|
try req.channel.put(ListDirectoryData(fi, null));
|
||||||
catch (Exception e) return false; // channel got closed
|
catch (Exception e) return false; // channel got closed
|
||||||
|
|
||||||
if (req.spanMode != DirectoryListMode.shallow && fi.isDirectory) {
|
if (rec && fi.isDirectory) {
|
||||||
if (fi.isSymlink && !req.followSymlinks)
|
if (fi.isSymlink && !req.followSymlinks)
|
||||||
continue;
|
continue;
|
||||||
try {
|
try {
|
||||||
|
@ -1030,18 +1033,17 @@ private void performListDirectory(ListDirectoryRequest req)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
FileInfo fi;
|
FileInfo fi;
|
||||||
auto zi = de.d_name[].countUntil(0);
|
auto zi = de.d_name[].representation.countUntil(0);
|
||||||
if (zi < 0) zi = de.d_name.length;
|
if (zi < 0) zi = de.d_name.length;
|
||||||
if (de.d_name[0 .. zi].among(".", ".."))
|
if (de.d_name[0 .. zi].among(".", ".."))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
fi.name = de.d_name[0 .. zi].idup;
|
fi.name = de.d_name[0 .. zi].idup;
|
||||||
fi.directory = path;
|
fi.directory = path;
|
||||||
|
fi.hidden = de.d_name[0] == '.';
|
||||||
|
|
||||||
stat_t st;
|
stat_t st;
|
||||||
if (fstatat(dfd, fi.name.toStringz, &st, AT_SYMLINK_NOFOLLOW) != 0)
|
if (fstatat(dfd, fi.name.toStringz, &st, AT_SYMLINK_NOFOLLOW) == 0) {
|
||||||
continue;
|
|
||||||
|
|
||||||
fi.isSymlink = S_ISLNK(st.st_mode);
|
fi.isSymlink = S_ISLNK(st.st_mode);
|
||||||
|
|
||||||
// apart from the symlink flag, get the rest of the information from the link target
|
// apart from the symlink flag, get the rest of the information from the link target
|
||||||
|
@ -1052,7 +1054,7 @@ private void performListDirectory(ListDirectoryRequest req)
|
||||||
fi.timeCreated = timebase + st.st_ctime.seconds + (st.st_ctimensec / 100).hnsecs;
|
fi.timeCreated = timebase + st.st_ctime.seconds + (st.st_ctimensec / 100).hnsecs;
|
||||||
fi.isDirectory = S_ISDIR(st.st_mode);
|
fi.isDirectory = S_ISDIR(st.st_mode);
|
||||||
fi.isFile = S_ISREG(st.st_mode);
|
fi.isFile = S_ISREG(st.st_mode);
|
||||||
fi.hidden = de.d_name[0] == '.';
|
}
|
||||||
|
|
||||||
// skip non-directories if requested
|
// skip non-directories if requested
|
||||||
if (dirs_only && !fi.isDirectory)
|
if (dirs_only && !fi.isDirectory)
|
||||||
|
@ -1061,7 +1063,7 @@ private void performListDirectory(ListDirectoryRequest req)
|
||||||
try req.channel.put(ListDirectoryData(fi, null));
|
try req.channel.put(ListDirectoryData(fi, null));
|
||||||
catch (Exception e) return false; // channel got closed
|
catch (Exception e) return false; // channel got closed
|
||||||
|
|
||||||
if (req.spanMode != DirectoryListMode.shallow && fi.isDirectory) {
|
if (rec && fi.isDirectory) {
|
||||||
if (fi.isSymlink && !req.followSymlinks)
|
if (fi.isSymlink && !req.followSymlinks)
|
||||||
continue;
|
continue;
|
||||||
try {
|
try {
|
||||||
|
@ -1089,8 +1091,12 @@ version (Posix) {
|
||||||
extern(C) @safe nothrow @nogc {
|
extern(C) @safe nothrow @nogc {
|
||||||
static if (!is(typeof(dirfd)))
|
static if (!is(typeof(dirfd)))
|
||||||
int dirfd(DIR*);
|
int dirfd(DIR*);
|
||||||
static if (!is(typeof(fstatat)))
|
static if (!is(typeof(fstatat))) {
|
||||||
|
version (OSX) {
|
||||||
|
pragma(mangle, "fstatat$INODE64")
|
||||||
int fstatat(int dirfd, const(char)* pathname, stat_t *statbuf, int flags);
|
int fstatat(int dirfd, const(char)* pathname, stat_t *statbuf, int flags);
|
||||||
|
} else int fstatat(int dirfd, const(char)* pathname, stat_t *statbuf, int flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
version (darwin) {
|
version (darwin) {
|
||||||
|
|
|
@ -440,7 +440,7 @@ final package class TaskFiber : Fiber {
|
||||||
debug if (ms_taskEventCallback) ms_taskEventCallback(TaskEvent.end, handle);
|
debug if (ms_taskEventCallback) ms_taskEventCallback(TaskEvent.end, handle);
|
||||||
|
|
||||||
debug if (() @trusted { return (cast(shared)this); } ().getTaskStatus().interrupt)
|
debug if (() @trusted { return (cast(shared)this); } ().getTaskStatus().interrupt)
|
||||||
logDebug("Task exited while an interrupt was in flight.");
|
logDebugV("Task exited while an interrupt was in flight.");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
debug if (ms_taskEventCallback) ms_taskEventCallback(TaskEvent.fail, handle);
|
debug if (ms_taskEventCallback) ms_taskEventCallback(TaskEvent.fail, handle);
|
||||||
e.logException!(LogLevel.critical)("Task terminated with uncaught exception");
|
e.logException!(LogLevel.critical)("Task terminated with uncaught exception");
|
||||||
|
|
|
@ -11,7 +11,7 @@ enum ubyte[] bytes(BYTES...) = [BYTES];
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
auto f = openFile("test.dat", FileMode.createTrunc);
|
auto f = openFile("têst.dat", FileMode.createTrunc);
|
||||||
assert(f.size == 0);
|
assert(f.size == 0);
|
||||||
assert(f.tell == 0);
|
assert(f.tell == 0);
|
||||||
f.write(bytes!(1, 2, 3, 4, 5));
|
f.write(bytes!(1, 2, 3, 4, 5));
|
||||||
|
@ -33,8 +33,8 @@ void main()
|
||||||
assert(dst[] == bytes!(3, 4, 5, 6, 7));
|
assert(dst[] == bytes!(3, 4, 5, 6, 7));
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
auto fi = getFileInfo("test.dat");
|
auto fi = getFileInfo("têst.dat");
|
||||||
assert(fi.name == "test.dat");
|
assert(fi.name == "têst.dat");
|
||||||
assert(fi.isFile);
|
assert(fi.isFile);
|
||||||
assert(!fi.isDirectory);
|
assert(!fi.isDirectory);
|
||||||
assert(!fi.isSymlink);
|
assert(!fi.isSymlink);
|
||||||
|
@ -43,5 +43,18 @@ void main()
|
||||||
|
|
||||||
assertThrown(getFileInfo("*impossible:file?"));
|
assertThrown(getFileInfo("*impossible:file?"));
|
||||||
|
|
||||||
removeFile("test.dat");
|
bool found = false;
|
||||||
|
listDirectory(".", (fi) {
|
||||||
|
if (fi.name != "têst.dat") return true;
|
||||||
|
assert(fi.isFile);
|
||||||
|
assert(!fi.isDirectory);
|
||||||
|
assert(!fi.isSymlink);
|
||||||
|
assert(!fi.hidden);
|
||||||
|
assert(fi.size == 10);
|
||||||
|
found = true;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
assert(found, "listDirectory did not find test file.");
|
||||||
|
|
||||||
|
removeFile("têst.dat");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue