fix Issue 15771 - FileLogger should create the output directory if it…#5370
fix Issue 15771 - FileLogger should create the output directory if it…#5370burner wants to merge 1 commit intodlang:masterfrom
Conversation
wilzbach
left a comment
There was a problem hiding this comment.
I found the documentation quite hard to read and I added a couple of small nits.
std/experimental/logger/filelogger.d
Outdated
| if (createFileNameFolder && !exists(d)) | ||
| { | ||
| () @trusted { mkdirRecurse(d); }(); | ||
| assert(exists(d)); |
There was a problem hiding this comment.
assert should always come with a helpful error message.
There was a problem hiding this comment.
Hm... mkdirRecurse is already telling you whether it made the directory or not. Why not just assert that? Edit: no it's not. I misread the code. But it is already checking that the directory exists, see https://github.com/dlang/phobos/blob/master/std/file.d#L2308, so we can probably remove the assert altogether.
As far as a helpful message, I don't know the requirements, but isn't printing the line number and file (as asserts always do) helpful enough? No need if we remove the assert.
There was a problem hiding this comment.
Asserting on I/O errors is almost always a mistake. If mkdirRecurse's contract is that on its successful return (and barring any race conditions you can't avoid anyway) the directory exists, then the program should assume the directory exists - thus the assert is redundant.
std/experimental/logger/filelogger.d
Outdated
| auto d = dirName(this.filename); | ||
| if (createFileNameFolder && !exists(d)) | ||
| { | ||
| () @trusted { mkdirRecurse(d); }(); |
There was a problem hiding this comment.
What's the underlying assumption that mkdirRecurse will be @safe.
Imho we should eat our dogfood and make Phobos usable with @safe and not create more holes.
There was a problem hiding this comment.
none, but the Issue can't be fixed without mkdirRecurse. It is not safe as it uses a C function again.
There was a problem hiding this comment.
but we can't simply add @trusted just to make functions @safe ...
CC @schveiguy
There was a problem hiding this comment.
Looking at mkdirRecurse, I think the trusted escape is OK. However, the best solution is to actually make mkdirRecurse @safe, and put the trusted escape on the C call inside there. If you want to do that, it would benefit others as well.
There was a problem hiding this comment.
I don't see why mkdirRecurse shouldn't @safe - mkdir is already @safe.
There was a problem hiding this comment.
cool, I'll change this PR
std/experimental/logger/filelogger.d
Outdated
| file can not be opened for writting an exception will be thrown. | ||
| lv = The $(D LogLevel) for the $(D FileLogger). By default the | ||
| $(D LogLevel) for $(D FileLogger) is $(D LogLevel.all). | ||
| createFileNameFolder = if true and fn contains a folder name, this |
There was a problem hiding this comment.
Nits:
- How about using a Flag instead of a boolean?
- How about naming it to sth. similar to
make -p
makeParentDirectories = If set totrue`, parent directories will be created as needed
There was a problem hiding this comment.
Definitely use Flag. We've essentially decided that all new Phobos APIs that take bool parameters to take Flags instead.
std/experimental/logger/filelogger.d
Outdated
| this(fn, lv, false); | ||
| } | ||
|
|
||
| this(in string fn, const LogLevel lv, bool createFileNameFolder) @safe |
There was a problem hiding this comment.
Btw CircleCi is failing due to
std/experimental/logger/filelogger.d(34): Warning: Ddoc: function declaration has no parameter 'createFileNameFolder'
std/experimental/logger/filelogger.d(34): Warning: Ddoc: parameter count mismatch
make: *** [style] Error 1
(you will need /// ditto to fix this)
std/experimental/logger/filelogger.d
Outdated
|
|
||
| this.filename = fn; | ||
| auto d = dirName(this.filename); | ||
| if (createFileNameFolder && !exists(d)) |
There was a problem hiding this comment.
mkdirRecurse will already check for existence. The exists check is redundant, remove it.
std/experimental/logger/filelogger.d
Outdated
| super(lv); | ||
|
|
||
| this.filename = fn; | ||
| auto d = dirName(this.filename); |
There was a problem hiding this comment.
Move this into the if (createFileNameFolder) block to avoid a calculation that's unnecessary for the default case.
|
all fixed up I hope |
| { | ||
| import std.file : exists, rmdirRecurse; | ||
|
|
||
| string logpath = "super/long/path/"; |
There was a problem hiding this comment.
Please prepend with std.file.deleteme, don't just create test files in the local directory.
There was a problem hiding this comment.
FYI: deleteme just returns a string sth. like /tmp/deleteme.dmd.unittest.pid1234 - it can be used to construct temporary folders as well.
std/experimental/logger/filelogger.d
Outdated
| auto d = dirName(this.filename); | ||
| mkdirRecurse(d); | ||
| assert(exists(d), "The folder the FileLogger should have been" | ||
| ~ " created in '" ~ d ~ "' could not be created."); |
There was a problem hiding this comment.
You can use std.conv.text to make this a bit more efficient and legible (text uses an appender)
| { | ||
| import std.file : exists, rmdirRecurse; | ||
|
|
||
| string logpath = "super/long/path/"; |
There was a problem hiding this comment.
FYI: deleteme just returns a string sth. like /tmp/deleteme.dmd.unittest.pid1234 - it can be used to construct temporary folders as well.
std/experimental/logger/filelogger.d
Outdated
|
|
||
| fl.file.close(); | ||
| () @trusted { rmdirRecurse(logpath); }(); | ||
| assert(!exists(logpath)); |
There was a problem hiding this comment.
this seems unnecessary - you don't need to test rmdirRecurse
std/experimental/logger/filelogger.d
Outdated
| assert(exists(logpath)); | ||
|
|
||
| fl.file.close(); | ||
| () @trusted { rmdirRecurse(logpath); }(); |
There was a problem hiding this comment.
How about scope(exit) in the beginning, s.t. the temporary folder is removed even in case of failures?
std/experimental/logger/filelogger.d
Outdated
| super(lv); | ||
| this.filename = fn; | ||
|
|
||
| if (createFileNameFolder == CreateFolder.yes) |
There was a problem hiding this comment.
if (createFileNameFolder)
There was a problem hiding this comment.
hm, this feels like it would defeats the purpose of the Flag type.
|
Ping @burner |
|
@wilzbach I can't use deleteme as need a bunch of subdirs to check if this patch actually fixes the problem. |
As mentioned before: "FYI: See also: https://github.com/dlang/phobos/pull/5594/files |
|
@burner My PR uses deleteme and addresses the rest of the comments, but I copy-pasted your implementation. I'm down with whatever option you prefer, but I think it would be less pain for you to just close this one as mine is already in a mergeable condition |
… does not exist