mirror of
https://github.com/dlang/phobos.git
synced 2025-05-14 17:05:58 +03:00
Merge pull request #6320 from wilzbach/example-file
Add public examples to std.file + enable DScanner check merged-on-behalf-of: Jack Stouffer <jack@jackstouffer.com>
This commit is contained in:
commit
00581b83df
2 changed files with 554 additions and 41 deletions
|
@ -162,7 +162,6 @@ has_public_example="-etc.c.curl,\
|
||||||
-std.experimental.logger.filelogger,\
|
-std.experimental.logger.filelogger,\
|
||||||
-std.experimental.logger.multilogger,\
|
-std.experimental.logger.multilogger,\
|
||||||
-std.experimental.typecons,\
|
-std.experimental.typecons,\
|
||||||
-std.file,\
|
|
||||||
-std.format,\
|
-std.format,\
|
||||||
-std.getopt,\
|
-std.getopt,\
|
||||||
-std.internal.math.biguintcore,\
|
-std.internal.math.biguintcore,\
|
||||||
|
|
594
std/file.d
594
std/file.d
|
@ -214,6 +214,14 @@ class FileException : Exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
assertThrown!FileException("non.existing.file.".readText);
|
||||||
|
}
|
||||||
|
|
||||||
private T cenforce(T)(T condition, lazy const(char)[] name, string file = __FILE__, size_t line = __LINE__)
|
private T cenforce(T)(T condition, lazy const(char)[] name, string file = __FILE__, size_t line = __LINE__)
|
||||||
{
|
{
|
||||||
if (condition)
|
if (condition)
|
||||||
|
@ -568,7 +576,7 @@ if (isSomeString!S && (isInputRange!R && !isInfinite!R && isSomeChar!(ElementTyp
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read file with UTF-8 text.
|
/// Read file with UTF-8 text.
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
write(deleteme, "abc"); // deleteme is the name of a temporary file
|
write(deleteme, "abc"); // deleteme is the name of a temporary file
|
||||||
|
@ -923,6 +931,21 @@ if (isConvertibleToString!RF || isConvertibleToString!RT)
|
||||||
static assert(__traits(compiles, rename(TestAliasedString(null), "".byChar)));
|
static assert(__traits(compiles, rename(TestAliasedString(null), "".byChar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
auto t1 = deleteme, t2 = deleteme~"2";
|
||||||
|
scope(exit) foreach (t; [t1, t2]) if (t.exists) t.remove();
|
||||||
|
|
||||||
|
t1.write("1");
|
||||||
|
t1.rename(t2);
|
||||||
|
assert(t2.readText == "1");
|
||||||
|
|
||||||
|
t1.write("2");
|
||||||
|
t1.rename(t2);
|
||||||
|
assert(t2.readText == "2");
|
||||||
|
}
|
||||||
|
|
||||||
private void renameImpl(const(char)[] f, const(char)[] t, const(FSChar)* fromz, const(FSChar)* toz) @trusted
|
private void renameImpl(const(char)[] f, const(char)[] t, const(FSChar)* fromz, const(FSChar)* toz) @trusted
|
||||||
{
|
{
|
||||||
version(Windows)
|
version(Windows)
|
||||||
|
@ -960,15 +983,16 @@ private void renameImpl(const(char)[] f, const(char)[] t, const(FSChar)* fromz,
|
||||||
|
|
||||||
auto t1 = deleteme, t2 = deleteme~"2";
|
auto t1 = deleteme, t2 = deleteme~"2";
|
||||||
scope(exit) foreach (t; [t1, t2]) if (t.exists) t.remove();
|
scope(exit) foreach (t; [t1, t2]) if (t.exists) t.remove();
|
||||||
|
|
||||||
write(t1, "1");
|
write(t1, "1");
|
||||||
rename(t1, t2);
|
rename(t1, t2);
|
||||||
assert(readText(t2) == "1");
|
assert(readText(t2) == "1");
|
||||||
|
|
||||||
write(t1, "2");
|
write(t1, "2");
|
||||||
rename(t1, t2.byWchar);
|
rename(t1, t2.byWchar);
|
||||||
assert(readText(t2) == "2");
|
assert(readText(t2) == "2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************
|
/***************************************************
|
||||||
Delete file $(D name).
|
Delete file $(D name).
|
||||||
|
|
||||||
|
@ -994,6 +1018,18 @@ if (isConvertibleToString!R)
|
||||||
remove!(StringTypeOf!R)(name);
|
remove!(StringTypeOf!R)(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
deleteme.write("Hello");
|
||||||
|
assert(deleteme.readText == "Hello");
|
||||||
|
|
||||||
|
deleteme.remove;
|
||||||
|
assertThrown!FileException(deleteme.readText);
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
static assert(__traits(compiles, remove(TestAliasedString("foo"))));
|
static assert(__traits(compiles, remove(TestAliasedString("foo"))));
|
||||||
|
@ -1108,11 +1144,25 @@ if (isConvertibleToString!R)
|
||||||
static assert(__traits(compiles, getSize(TestAliasedString("foo"))));
|
static assert(__traits(compiles, getSize(TestAliasedString("foo"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
scope(exit) deleteme.remove;
|
||||||
|
|
||||||
|
// create a file of size 1
|
||||||
|
write(deleteme, "a");
|
||||||
|
assert(getSize(deleteme) == 1);
|
||||||
|
|
||||||
|
// create a file of size 3
|
||||||
|
write(deleteme, "abc");
|
||||||
|
assert(getSize(deleteme) == 3);
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
// create a file of size 1
|
// create a file of size 1
|
||||||
write(deleteme, "a");
|
write(deleteme, "a");
|
||||||
scope(exit) { assert(exists(deleteme)); remove(deleteme); }
|
scope(exit) deleteme.exists && deleteme.remove;
|
||||||
assert(getSize(deleteme) == 1);
|
assert(getSize(deleteme) == 1);
|
||||||
// create a file of size 3
|
// create a file of size 3
|
||||||
write(deleteme, "abc");
|
write(deleteme, "abc");
|
||||||
|
@ -1120,7 +1170,6 @@ if (isConvertibleToString!R)
|
||||||
assert(getSize(deleteme.byChar) == 3);
|
assert(getSize(deleteme.byChar) == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Reads a time field from a stat_t with full precision.
|
// Reads a time field from a stat_t with full precision.
|
||||||
version(Posix)
|
version(Posix)
|
||||||
private SysTime statTimeToStdTime(char which)(ref stat_t statbuf)
|
private SysTime statTimeToStdTime(char which)(ref stat_t statbuf)
|
||||||
|
@ -1200,6 +1249,28 @@ if (isConvertibleToString!R)
|
||||||
return getTimes!(StringTypeOf!R)(name, accessTime, modificationTime);
|
return getTimes!(StringTypeOf!R)(name, accessTime, modificationTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.datetime : abs, SysTime;
|
||||||
|
|
||||||
|
scope(exit) deleteme.remove;
|
||||||
|
write(deleteme, "a");
|
||||||
|
|
||||||
|
SysTime accessTime, modificationTime;
|
||||||
|
|
||||||
|
getTimes(deleteme, accessTime, modificationTime);
|
||||||
|
|
||||||
|
import std.datetime : Clock, seconds;
|
||||||
|
auto currTime = Clock.currTime();
|
||||||
|
enum leeway = 5.seconds;
|
||||||
|
|
||||||
|
auto diffAccess = accessTime - currTime;
|
||||||
|
auto diffModification = modificationTime - currTime;
|
||||||
|
assert(abs(diffAccess) <= leeway);
|
||||||
|
assert(abs(diffModification) <= leeway);
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
SysTime atime, mtime;
|
SysTime atime, mtime;
|
||||||
|
@ -1213,14 +1284,14 @@ if (isConvertibleToString!R)
|
||||||
auto currTime = Clock.currTime();
|
auto currTime = Clock.currTime();
|
||||||
|
|
||||||
write(deleteme, "a");
|
write(deleteme, "a");
|
||||||
scope(exit) { assert(exists(deleteme)); remove(deleteme); }
|
scope(exit) assert(deleteme.exists), deleteme.remove;
|
||||||
|
|
||||||
SysTime accessTime1 = void;
|
SysTime accessTime1 = void;
|
||||||
SysTime modificationTime1 = void;
|
SysTime modificationTime1 = void;
|
||||||
|
|
||||||
getTimes(deleteme, accessTime1, modificationTime1);
|
getTimes(deleteme, accessTime1, modificationTime1);
|
||||||
|
|
||||||
enum leeway = dur!"seconds"(5);
|
enum leeway = 5.seconds;
|
||||||
|
|
||||||
{
|
{
|
||||||
auto diffa = accessTime1 - currTime;
|
auto diffa = accessTime1 - currTime;
|
||||||
|
@ -1492,6 +1563,25 @@ if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.datetime : DateTime, hnsecs, SysTime;
|
||||||
|
|
||||||
|
scope(exit) deleteme.remove;
|
||||||
|
write(deleteme, "a");
|
||||||
|
|
||||||
|
SysTime accessTime = SysTime(DateTime(2010, 10, 4, 0, 0, 30));
|
||||||
|
SysTime modificationTime = SysTime(DateTime(2018, 10, 4, 0, 0, 30));
|
||||||
|
setTimes(deleteme, accessTime, modificationTime);
|
||||||
|
|
||||||
|
SysTime accessTimeResolved, modificationTimeResolved;
|
||||||
|
getTimes(deleteme, accessTimeResolved, modificationTimeResolved);
|
||||||
|
|
||||||
|
assert(accessTime == accessTimeResolved);
|
||||||
|
assert(modificationTime == modificationTimeResolved);
|
||||||
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
void setTimes(R)(auto ref R name,
|
void setTimes(R)(auto ref R name,
|
||||||
SysTime accessTime,
|
SysTime accessTime,
|
||||||
|
@ -1585,6 +1675,19 @@ if (isConvertibleToString!R)
|
||||||
return timeLastModified!(StringTypeOf!R)(name);
|
return timeLastModified!(StringTypeOf!R)(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.datetime : abs, DateTime, hnsecs, SysTime;
|
||||||
|
scope(exit) deleteme.remove;
|
||||||
|
|
||||||
|
import std.datetime : Clock, seconds;
|
||||||
|
auto currTime = Clock.currTime();
|
||||||
|
enum leeway = 5.seconds;
|
||||||
|
deleteme.write("bb");
|
||||||
|
assert(abs(deleteme.timeLastModified - currTime) <= leeway);
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
static assert(__traits(compiles, timeLastModified(TestAliasedString("foo"))));
|
static assert(__traits(compiles, timeLastModified(TestAliasedString("foo"))));
|
||||||
|
@ -1610,7 +1713,7 @@ if (isConvertibleToString!R)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
--------------------
|
--------------------
|
||||||
if (timeLastModified(source) >= timeLastModified(target, SysTime.min))
|
if (source.timeLastModified >= target.timeLastModified(SysTime.min))
|
||||||
{
|
{
|
||||||
// must (re)build
|
// must (re)build
|
||||||
}
|
}
|
||||||
|
@ -1650,6 +1753,23 @@ if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.datetime : SysTime;
|
||||||
|
|
||||||
|
assert("file.does.not.exist".timeLastModified(SysTime.min) == SysTime.min);
|
||||||
|
|
||||||
|
auto source = deleteme ~ "source";
|
||||||
|
auto target = deleteme ~ "target";
|
||||||
|
scope(exit) source.remove, target.remove;
|
||||||
|
|
||||||
|
source.write(".");
|
||||||
|
assert(target.timeLastModified(SysTime.min) < source.timeLastModified);
|
||||||
|
target.write(".");
|
||||||
|
assert(target.timeLastModified(SysTime.min) >= source.timeLastModified);
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
//std.process.system("echo a > deleteme") == 0 || assert(false);
|
//std.process.system("echo a > deleteme") == 0 || assert(false);
|
||||||
|
@ -1721,6 +1841,19 @@ if (isConvertibleToString!R)
|
||||||
return exists!(StringTypeOf!R)(name);
|
return exists!(StringTypeOf!R)(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
auto f = deleteme ~ "does.not.exist";
|
||||||
|
assert(!f.exists);
|
||||||
|
|
||||||
|
f.write("hello");
|
||||||
|
assert(f.exists);
|
||||||
|
|
||||||
|
f.remove;
|
||||||
|
assert(!f.exists);
|
||||||
|
}
|
||||||
|
|
||||||
private bool existsImpl(const(FSChar)* namez) @trusted nothrow @nogc
|
private bool existsImpl(const(FSChar)* namez) @trusted nothrow @nogc
|
||||||
{
|
{
|
||||||
version(Windows)
|
version(Windows)
|
||||||
|
@ -1758,13 +1891,14 @@ private bool existsImpl(const(FSChar)* namez) @trusted nothrow @nogc
|
||||||
static assert(0);
|
static assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
assert(exists("."));
|
assert(".".exists);
|
||||||
assert(!exists("this file does not exist"));
|
assert(!"this file does not exist".exists);
|
||||||
write(deleteme, "a\n");
|
deleteme.write("a\n");
|
||||||
scope(exit) { assert(exists(deleteme)); remove(deleteme); }
|
scope(exit) deleteme.remove;
|
||||||
assert(exists(deleteme));
|
assert(deleteme.exists);
|
||||||
}
|
}
|
||||||
|
|
||||||
@safe unittest // Bugzilla 16573
|
@safe unittest // Bugzilla 16573
|
||||||
|
@ -1840,6 +1974,40 @@ if (isConvertibleToString!R)
|
||||||
return getAttributes!(StringTypeOf!R)(name);
|
return getAttributes!(StringTypeOf!R)(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getAttributes with a file
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
auto f = deleteme ~ "file";
|
||||||
|
scope(exit) f.remove;
|
||||||
|
|
||||||
|
assert(!f.exists);
|
||||||
|
assertThrown!FileException(f.getAttributes);
|
||||||
|
|
||||||
|
f.write(".");
|
||||||
|
auto attributes = f.getAttributes;
|
||||||
|
assert(!attributes.attrIsDir);
|
||||||
|
assert(attributes.attrIsFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getAttributes with a directory
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
auto dir = deleteme ~ "dir";
|
||||||
|
scope(exit) dir.rmdir;
|
||||||
|
|
||||||
|
assert(!dir.exists);
|
||||||
|
assertThrown!FileException(dir.getAttributes);
|
||||||
|
|
||||||
|
dir.mkdir;
|
||||||
|
auto attributes = dir.getAttributes;
|
||||||
|
assert(attributes.attrIsDir);
|
||||||
|
assert(!attributes.attrIsFile);
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
static assert(__traits(compiles, getAttributes(TestAliasedString(null))));
|
static assert(__traits(compiles, getAttributes(TestAliasedString(null))));
|
||||||
|
@ -1896,6 +2064,59 @@ if (isConvertibleToString!R)
|
||||||
return getLinkAttributes!(StringTypeOf!R)(name);
|
return getLinkAttributes!(StringTypeOf!R)(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
auto source = deleteme ~ "source";
|
||||||
|
auto target = deleteme ~ "target";
|
||||||
|
scope(exit) source.remove, target.remove;
|
||||||
|
|
||||||
|
assert(!source.exists);
|
||||||
|
assertThrown!FileException(source.getLinkAttributes);
|
||||||
|
|
||||||
|
target.write("target");
|
||||||
|
target.symlink(source);
|
||||||
|
assert(source.readText == "target");
|
||||||
|
assert(source.isSymlink);
|
||||||
|
assert(source.getLinkAttributes.attrIsSymlink);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// if the file is no symlink, getLinkAttributes behaves like getAttributes
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
auto f = deleteme ~ "file";
|
||||||
|
scope(exit) f.remove;
|
||||||
|
|
||||||
|
assert(!f.exists);
|
||||||
|
assertThrown!FileException(f.getLinkAttributes);
|
||||||
|
|
||||||
|
f.write(".");
|
||||||
|
auto attributes = f.getLinkAttributes;
|
||||||
|
assert(!attributes.attrIsDir);
|
||||||
|
assert(attributes.attrIsFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// if the file is no symlink, getLinkAttributes behaves like getAttributes
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
auto dir = deleteme ~ "dir";
|
||||||
|
scope(exit) dir.rmdir;
|
||||||
|
|
||||||
|
assert(!dir.exists);
|
||||||
|
assertThrown!FileException(dir.getLinkAttributes);
|
||||||
|
|
||||||
|
dir.mkdir;
|
||||||
|
auto attributes = dir.getLinkAttributes;
|
||||||
|
assert(attributes.attrIsDir);
|
||||||
|
assert(!attributes.attrIsFile);
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
static assert(__traits(compiles, getLinkAttributes(TestAliasedString(null))));
|
static assert(__traits(compiles, getLinkAttributes(TestAliasedString(null))));
|
||||||
|
@ -1956,6 +2177,50 @@ if (isConvertibleToString!R)
|
||||||
static assert(__traits(compiles, setAttributes(TestAliasedString(null), 0)));
|
static assert(__traits(compiles, setAttributes(TestAliasedString(null), 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// setAttributes with a file
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
import std.conv : octal;
|
||||||
|
|
||||||
|
auto f = deleteme ~ "file";
|
||||||
|
scope(exit) f.remove;
|
||||||
|
|
||||||
|
assert(!f.exists);
|
||||||
|
assertThrown!FileException(f.setAttributes(octal!777));
|
||||||
|
|
||||||
|
f.write(".");
|
||||||
|
auto attributes = f.getAttributes;
|
||||||
|
assert(!attributes.attrIsDir);
|
||||||
|
assert(attributes.attrIsFile);
|
||||||
|
|
||||||
|
f.setAttributes(octal!777);
|
||||||
|
attributes = f.getAttributes;
|
||||||
|
assert((attributes & 1023) == octal!777);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// setAttributes with a directory
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
import std.conv : octal;
|
||||||
|
|
||||||
|
auto dir = deleteme ~ "dir";
|
||||||
|
scope(exit) dir.rmdir;
|
||||||
|
|
||||||
|
assert(!dir.exists);
|
||||||
|
assertThrown!FileException(dir.setAttributes(octal!777));
|
||||||
|
|
||||||
|
dir.mkdir;
|
||||||
|
auto attributes = dir.getAttributes;
|
||||||
|
assert(attributes.attrIsDir);
|
||||||
|
assert(!attributes.attrIsFile);
|
||||||
|
|
||||||
|
dir.setAttributes(octal!777);
|
||||||
|
attributes = dir.getAttributes;
|
||||||
|
assert((attributes & 1023) == octal!777);
|
||||||
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Returns whether the given file is a directory.
|
Returns whether the given file is a directory.
|
||||||
|
|
||||||
|
@ -1967,12 +2232,6 @@ if (isConvertibleToString!R)
|
||||||
|
|
||||||
Throws:
|
Throws:
|
||||||
$(D FileException) if the given file does not exist.
|
$(D FileException) if the given file does not exist.
|
||||||
|
|
||||||
Example:
|
|
||||||
--------------------
|
|
||||||
assert(!"/etc/fonts/fonts.conf".isDir);
|
|
||||||
assert("/usr/share/include".isDir);
|
|
||||||
--------------------
|
|
||||||
+/
|
+/
|
||||||
@property bool isDir(R)(R name)
|
@property bool isDir(R)(R name)
|
||||||
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
|
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
|
||||||
|
@ -1995,6 +2254,26 @@ if (isConvertibleToString!R)
|
||||||
return name.isDir!(StringTypeOf!R);
|
return name.isDir!(StringTypeOf!R);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
auto dir = deleteme ~ "dir";
|
||||||
|
auto f = deleteme ~ "f";
|
||||||
|
scope(exit) dir.rmdir, f.remove;
|
||||||
|
|
||||||
|
assert(!dir.exists);
|
||||||
|
assertThrown!FileException(dir.isDir);
|
||||||
|
|
||||||
|
dir.mkdir;
|
||||||
|
assert(dir.isDir);
|
||||||
|
|
||||||
|
f.write(".");
|
||||||
|
assert(!f.isDir);
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
static assert(__traits(compiles, TestAliasedString(null).isDir));
|
static assert(__traits(compiles, TestAliasedString(null).isDir));
|
||||||
|
@ -2043,13 +2322,7 @@ if (isConvertibleToString!R)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
true if attributes specifies a directory
|
true if attributes specifies a directory
|
||||||
|
+/
|
||||||
Example:
|
|
||||||
--------------------
|
|
||||||
assert(!attrIsDir(getAttributes("/etc/fonts/fonts.conf")));
|
|
||||||
assert(!attrIsDir(getLinkAttributes("/etc/fonts/fonts.conf")));
|
|
||||||
--------------------
|
|
||||||
+/
|
|
||||||
bool attrIsDir(uint attributes) @safe pure nothrow @nogc
|
bool attrIsDir(uint attributes) @safe pure nothrow @nogc
|
||||||
{
|
{
|
||||||
version(Windows)
|
version(Windows)
|
||||||
|
@ -2062,6 +2335,27 @@ bool attrIsDir(uint attributes) @safe pure nothrow @nogc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
auto dir = deleteme ~ "dir";
|
||||||
|
auto f = deleteme ~ "f";
|
||||||
|
scope(exit) dir.rmdir, f.remove;
|
||||||
|
|
||||||
|
assert(!dir.exists);
|
||||||
|
assertThrown!FileException(dir.getAttributes.attrIsDir);
|
||||||
|
|
||||||
|
dir.mkdir;
|
||||||
|
assert(dir.isDir);
|
||||||
|
assert(dir.getAttributes.attrIsDir);
|
||||||
|
|
||||||
|
f.write(".");
|
||||||
|
assert(!f.isDir);
|
||||||
|
assert(!f.getAttributes.attrIsDir);
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
version(Windows)
|
version(Windows)
|
||||||
|
@ -2118,13 +2412,7 @@ bool attrIsDir(uint attributes) @safe pure nothrow @nogc
|
||||||
|
|
||||||
Throws:
|
Throws:
|
||||||
$(D FileException) if the given file does not exist.
|
$(D FileException) if the given file does not exist.
|
||||||
|
+/
|
||||||
Example:
|
|
||||||
--------------------
|
|
||||||
assert("/etc/fonts/fonts.conf".isFile);
|
|
||||||
assert(!"/usr/share/include".isFile);
|
|
||||||
--------------------
|
|
||||||
+/
|
|
||||||
@property bool isFile(R)(R name)
|
@property bool isFile(R)(R name)
|
||||||
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
|
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
|
||||||
!isConvertibleToString!R)
|
!isConvertibleToString!R)
|
||||||
|
@ -2142,6 +2430,25 @@ if (isConvertibleToString!R)
|
||||||
return isFile!(StringTypeOf!R)(name);
|
return isFile!(StringTypeOf!R)(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
auto dir = deleteme ~ "dir";
|
||||||
|
auto f = deleteme ~ "f";
|
||||||
|
scope(exit) dir.rmdir, f.remove;
|
||||||
|
|
||||||
|
dir.mkdir;
|
||||||
|
assert(!dir.isFile);
|
||||||
|
|
||||||
|
assert(!f.exists);
|
||||||
|
assertThrown!FileException(f.isFile);
|
||||||
|
|
||||||
|
f.write(".");
|
||||||
|
assert(f.isFile);
|
||||||
|
}
|
||||||
|
|
||||||
@system unittest // bugzilla 15658
|
@system unittest // bugzilla 15658
|
||||||
{
|
{
|
||||||
DirEntry e = DirEntry(".");
|
DirEntry e = DirEntry(".");
|
||||||
|
@ -2212,6 +2519,27 @@ bool attrIsFile(uint attributes) @safe pure nothrow @nogc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
auto dir = deleteme ~ "dir";
|
||||||
|
auto f = deleteme ~ "f";
|
||||||
|
scope(exit) dir.rmdir, f.remove;
|
||||||
|
|
||||||
|
dir.mkdir;
|
||||||
|
assert(!dir.isFile);
|
||||||
|
assert(!dir.getAttributes.attrIsFile);
|
||||||
|
|
||||||
|
assert(!f.exists);
|
||||||
|
assertThrown!FileException(f.getAttributes.attrIsFile);
|
||||||
|
|
||||||
|
f.write(".");
|
||||||
|
assert(f.isFile);
|
||||||
|
assert(f.getAttributes.attrIsFile);
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
version(Windows)
|
version(Windows)
|
||||||
|
@ -2282,6 +2610,24 @@ if (isConvertibleToString!R)
|
||||||
static assert(__traits(compiles, TestAliasedString(null).isSymlink));
|
static assert(__traits(compiles, TestAliasedString(null).isSymlink));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
auto source = deleteme ~ "source";
|
||||||
|
auto target = deleteme ~ "target";
|
||||||
|
scope(exit) source.remove, target.remove;
|
||||||
|
|
||||||
|
assert(!source.exists);
|
||||||
|
assertThrown!FileException(source.isSymlink);
|
||||||
|
|
||||||
|
target.write("target");
|
||||||
|
target.symlink(source);
|
||||||
|
assert(source.readText == "target");
|
||||||
|
assert(source.isSymlink);
|
||||||
|
}
|
||||||
|
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
version(Windows)
|
version(Windows)
|
||||||
|
@ -2384,6 +2730,25 @@ bool attrIsSymlink(uint attributes) @safe pure nothrow @nogc
|
||||||
return (attributes & S_IFMT) == S_IFLNK;
|
return (attributes & S_IFMT) == S_IFLNK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
auto source = deleteme ~ "source";
|
||||||
|
auto target = deleteme ~ "target";
|
||||||
|
scope(exit) source.remove, target.remove;
|
||||||
|
|
||||||
|
assert(!source.exists);
|
||||||
|
assertThrown!FileException(source.getLinkAttributes.attrIsSymlink);
|
||||||
|
|
||||||
|
target.write("target");
|
||||||
|
target.symlink(source);
|
||||||
|
assert(source.readText == "target");
|
||||||
|
assert(source.isSymlink);
|
||||||
|
assert(source.getLinkAttributes.attrIsSymlink);
|
||||||
|
assert(!source.getAttributes.attrIsSymlink);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* Change directory to $(D pathname).
|
* Change directory to $(D pathname).
|
||||||
|
@ -2424,6 +2789,25 @@ if (isConvertibleToString!R)
|
||||||
return chdir!(StringTypeOf!R)(pathname);
|
return chdir!(StringTypeOf!R)(pathname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@system unittest
|
||||||
|
{
|
||||||
|
import std.algorithm.comparison : equal;
|
||||||
|
import std.path : buildPath;
|
||||||
|
|
||||||
|
auto cwd = getcwd;
|
||||||
|
auto dir = deleteme ~ "dir";
|
||||||
|
dir.mkdir;
|
||||||
|
scope(exit) cwd.chdir, dir.rmdirRecurse;
|
||||||
|
|
||||||
|
dir.buildPath("a").write(".");
|
||||||
|
dir.chdir; // step into dir
|
||||||
|
"b".write(".");
|
||||||
|
dirEntries(".", SpanMode.shallow).equal(
|
||||||
|
[".".buildPath("b"), ".".buildPath("a")]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
static assert(__traits(compiles, chdir(TestAliasedString(null))));
|
static assert(__traits(compiles, chdir(TestAliasedString(null))));
|
||||||
|
@ -2483,6 +2867,25 @@ if (isConvertibleToString!R)
|
||||||
static assert(__traits(compiles, mkdir(TestAliasedString(null))));
|
static assert(__traits(compiles, mkdir(TestAliasedString(null))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.file : mkdir;
|
||||||
|
|
||||||
|
auto dir = deleteme ~ "dir";
|
||||||
|
scope(exit) dir.rmdir;
|
||||||
|
|
||||||
|
dir.mkdir;
|
||||||
|
assert(dir.exists);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
assertThrown!FileException("a/b/c/d/e".mkdir);
|
||||||
|
}
|
||||||
|
|
||||||
// Same as mkdir but ignores "already exists" errors.
|
// Same as mkdir but ignores "already exists" errors.
|
||||||
// Returns: "true" if the directory was created,
|
// Returns: "true" if the directory was created,
|
||||||
// "false" if it already existed.
|
// "false" if it already existed.
|
||||||
|
@ -2533,6 +2936,36 @@ void mkdirRecurse(in char[] pathname) @safe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@system unittest
|
||||||
|
{
|
||||||
|
import std.path : buildPath;
|
||||||
|
|
||||||
|
auto dir = deleteme ~ "dir";
|
||||||
|
scope(exit) dir.rmdirRecurse;
|
||||||
|
|
||||||
|
dir.mkdir;
|
||||||
|
assert(dir.exists);
|
||||||
|
dir.mkdirRecurse; // does nothing
|
||||||
|
|
||||||
|
// creates all parent directories as needed
|
||||||
|
auto nested = dir.buildPath("a", "b", "c");
|
||||||
|
nested.mkdirRecurse;
|
||||||
|
assert(nested.exists);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.exception : assertThrown;
|
||||||
|
|
||||||
|
scope(exit) deleteme.remove;
|
||||||
|
deleteme.write("a");
|
||||||
|
|
||||||
|
// cannot make directory as it's already a file
|
||||||
|
assertThrown!FileException(deleteme.mkdirRecurse);
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
import std.exception : assertThrown;
|
import std.exception : assertThrown;
|
||||||
|
@ -2628,6 +3061,17 @@ if (isConvertibleToString!R)
|
||||||
static assert(__traits(compiles, rmdir(TestAliasedString(null))));
|
static assert(__traits(compiles, rmdir(TestAliasedString(null))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@system unittest
|
||||||
|
{
|
||||||
|
auto dir = deleteme ~ "dir";
|
||||||
|
|
||||||
|
dir.mkdir;
|
||||||
|
assert(dir.exists);
|
||||||
|
dir.rmdir;
|
||||||
|
assert(!dir.exists);
|
||||||
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
$(BLUE This function is Posix-Only.)
|
$(BLUE This function is Posix-Only.)
|
||||||
|
|
||||||
|
@ -2883,6 +3327,7 @@ else version (Posix) string getcwd() @trusted
|
||||||
return p[0 .. core.stdc.string.strlen(p)].idup;
|
return p[0 .. core.stdc.string.strlen(p)].idup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
auto s = getcwd();
|
auto s = getcwd();
|
||||||
|
@ -2992,6 +3437,7 @@ else version (NetBSD)
|
||||||
static assert(0, "thisExePath is not supported on this platform");
|
static assert(0, "thisExePath is not supported on this platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
import std.path : isAbsolute;
|
import std.path : isAbsolute;
|
||||||
|
@ -3622,6 +4068,27 @@ if (isConvertibleToString!RF || isConvertibleToString!RT)
|
||||||
copy!Types(from, to, preserve);
|
copy!Types(from, to, preserve);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
auto source = deleteme ~ "source";
|
||||||
|
auto target = deleteme ~ "target";
|
||||||
|
auto targetNonExistent = deleteme ~ "target2";
|
||||||
|
|
||||||
|
scope(exit) source.remove, target.remove, targetNonExistent.remove;
|
||||||
|
|
||||||
|
source.write("source");
|
||||||
|
target.write("target");
|
||||||
|
|
||||||
|
assert(target.readText == "target");
|
||||||
|
|
||||||
|
source.copy(target);
|
||||||
|
assert(target.readText == "source");
|
||||||
|
|
||||||
|
source.copy(targetNonExistent);
|
||||||
|
assert(targetNonExistent.readText == "source");
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest // issue 15319
|
@safe unittest // issue 15319
|
||||||
{
|
{
|
||||||
assert(__traits(compiles, copy("from.txt", "to.txt")));
|
assert(__traits(compiles, copy("from.txt", "to.txt")));
|
||||||
|
@ -3767,14 +4234,7 @@ void rmdirRecurse(in char[] pathname)
|
||||||
rmdirRecurse(DirEntry(cast(string) pathname));
|
rmdirRecurse(DirEntry(cast(string) pathname));
|
||||||
}
|
}
|
||||||
|
|
||||||
/++
|
/// ditto
|
||||||
Remove directory and all of its content and subdirectories,
|
|
||||||
recursively.
|
|
||||||
|
|
||||||
Throws:
|
|
||||||
$(D FileException) if there is an error (including if the given
|
|
||||||
file is not a directory).
|
|
||||||
+/
|
|
||||||
void rmdirRecurse(ref DirEntry de)
|
void rmdirRecurse(ref DirEntry de)
|
||||||
{
|
{
|
||||||
if (!de.isDir)
|
if (!de.isDir)
|
||||||
|
@ -3810,6 +4270,21 @@ void rmdirRecurse(DirEntry de)
|
||||||
rmdirRecurse(de);
|
rmdirRecurse(de);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@system unittest
|
||||||
|
{
|
||||||
|
import std.path : buildPath;
|
||||||
|
|
||||||
|
auto dir = deleteme.buildPath("a", "b", "c");
|
||||||
|
|
||||||
|
dir.mkdirRecurse;
|
||||||
|
assert(dir.exists);
|
||||||
|
|
||||||
|
deleteme.rmdirRecurse;
|
||||||
|
assert(!dir.exists);
|
||||||
|
assert(!deleteme.exists);
|
||||||
|
}
|
||||||
|
|
||||||
version(Windows) @system unittest
|
version(Windows) @system unittest
|
||||||
{
|
{
|
||||||
import std.exception : enforce;
|
import std.exception : enforce;
|
||||||
|
@ -3893,6 +4368,34 @@ enum SpanMode
|
||||||
breadth,
|
breadth,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@system unittest
|
||||||
|
{
|
||||||
|
import std.algorithm.comparison : equal;
|
||||||
|
import std.algorithm.iteration : map;
|
||||||
|
import std.path : buildPath, relativePath;
|
||||||
|
|
||||||
|
auto root = tempDir.buildPath("root");
|
||||||
|
scope(exit) root.rmdirRecurse;
|
||||||
|
root.mkdir;
|
||||||
|
|
||||||
|
root.buildPath("animals").mkdir;
|
||||||
|
root.buildPath("animals", "cat").mkdir;
|
||||||
|
root.buildPath("animals", "dog").mkdir;
|
||||||
|
root.buildPath("plants").mkdir;
|
||||||
|
|
||||||
|
alias removeRoot = (e) => e.relativePath(root);
|
||||||
|
|
||||||
|
root.dirEntries(SpanMode.shallow).map!removeRoot.equal(
|
||||||
|
["plants", "animals"]);
|
||||||
|
|
||||||
|
root.dirEntries(SpanMode.depth).map!removeRoot.equal(
|
||||||
|
["plants", "animals/dog", "animals/cat", "animals"]);
|
||||||
|
|
||||||
|
root.dirEntries(SpanMode.breadth).map!removeRoot.equal(
|
||||||
|
["plants", "animals", "animals/dog", "animals/cat"]);
|
||||||
|
}
|
||||||
|
|
||||||
private struct DirIteratorImpl
|
private struct DirIteratorImpl
|
||||||
{
|
{
|
||||||
@safe:
|
@safe:
|
||||||
|
@ -4575,3 +5078,14 @@ string tempDir() @trusted
|
||||||
}
|
}
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.path : buildPath;
|
||||||
|
auto myFile = tempDir.buildPath("my_tmp_file");
|
||||||
|
scope(exit) myFile.remove;
|
||||||
|
|
||||||
|
myFile.write("hello");
|
||||||
|
assert(myFile.readText == "hello");
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue