-
Notifications
You must be signed in to change notification settings - Fork 739
refactor(mkdir): consistent error handling #854
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This refactors mkdir() to (for the most part) invoke mkdirSync() and catch any exceptions, instead of the error-prone approach of trying to predict when specific errors would happen. This adds two new tests for "name too long" and that it's OK to `mkdir -p` a directory which already exists. The latter was implicitly covered by another test case, but this should be explicit. Lastly, this changes error messages to be more consistent with Linux mkdir, and adds the "avoid-escape" rule in the test directory to allow using double-quoted strings when it aids readability. Fixes #722
@freitagbr take a look, but this should probably be considered as a breaking change because it changes error messages. |
@@ -51,29 +51,13 @@ function mkdirSyncRecursive(dir) { | |||
function _mkdir(options, dirs) { | |||
if (!dirs) common.error('no paths given'); | |||
|
|||
if (typeof dirs === 'string') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the type is always string. We introduced some code to flatten out arrays. Even in the case of ShellStrings, I think we also convert those into bare strings.
var reason; | ||
if (e.code === 'EACCES') { | ||
reason = 'Permission denied'; | ||
} else if (e.code === 'ENOTDIR' || e.code === 'ENOENT') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think ENOENT
should be handled distinctly from ENOTDIR
, not sure why they're in the same branch here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm this is weird. On unix, ENNOTDIR and ENOENT are for different reasons. On appveyor, I see ENOENT when part of the path is a regular file. Not sure yet how we should handle this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this still causing the appveyor CI to fail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I haven't fixed this yet.
src/mkdir.js
Outdated
EEXIST: 'File exists', | ||
ENAMETOOLONG: 'File name too long', | ||
ENOENT: 'No such file or directory', | ||
ENOTDIR: 'Not a directory', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I limited this to the list of error codes I could repro locally. I think that's fine for now, and we can add more later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this enum something that should be declared globally? Perhaps in src/common.js
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of the error codes can be shared (e.g., EEXIST
). However, there's no real advantage to moving these to common.js. It's the difference between common.codes.EEXIST
and 'EEXIST'
.
When it comes to user-facing error messages, I think each command wants a different message as it sees fit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, makes sense. This enum could at least be declared globally in this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -11,6 +11,7 @@ | |||
"no-param-reassign": "off", | |||
"no-console": "off", | |||
"curly": "off", | |||
"quotes": ["error", "single", "avoid-escape"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me know if you'd like to promote this to the top-level config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any escaped quotes outside of test/
? I can't find any in src/
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guess there's not. Let's keep it here then.
@@ -145,6 +159,21 @@ test('-p flag', t => { | |||
shell.rm('-Rf', `${t.context.tmp}/a`); // revert | |||
}); | |||
|
|||
test('create same dir twice with -p flag', t => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is implicitly covered in the "globbed dir" test, but this merits explicit coverage.
This didn't fix the issue for Windows. This reverts commit 03d08f3.
src/mkdir.js
Outdated
EEXIST: 'File exists', | ||
ENAMETOOLONG: 'File name too long', | ||
ENOENT: 'No such file or directory', | ||
ENOTDIR: 'Not a directory', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, makes sense. This enum could at least be declared globally in this file.
This refactors mkdir() to (for the most part) invoke mkdirSync() and
catch any exceptions, instead of the error-prone approach of trying to
predict when specific errors would happen.
This adds two new tests for "name too long" and that it's OK to
mkdir -p
a directory which already exists. The latter was implicitly coveredby another test case, but this should be explicit.
Lastly, this changes error messages to be more consistent with Linux
mkdir, and adds the "avoid-escape" rule in the test directory to allow
using double-quoted strings when it aids readability.
Fixes #722