trouble-in-terror-town/node_modules/make-dir/index.js
Mikolaj 2bbacbea09 did some more work on networking and removed EOS in favor of LRM
did some more work on networking and removed EOS in favor of Light Reflective Mirror
2022-05-31 15:04:31 +02:00

156 lines
3.1 KiB
JavaScript

'use strict';
const fs = require('fs');
const path = require('path');
const {promisify} = require('util');
const semver = require('semver');
const useNativeRecursiveOption = semver.satisfies(process.version, '>=10.12.0');
// https://github.com/nodejs/node/issues/8987
// https://github.com/libuv/libuv/pull/1088
const checkPath = pth => {
if (process.platform === 'win32') {
const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path.parse(pth).root, ''));
if (pathHasInvalidWinCharacters) {
const error = new Error(`Path contains invalid characters: ${pth}`);
error.code = 'EINVAL';
throw error;
}
}
};
const processOptions = options => {
// https://github.com/sindresorhus/make-dir/issues/18
const defaults = {
mode: 0o777,
fs
};
return {
...defaults,
...options
};
};
const permissionError = pth => {
// This replicates the exception of `fs.mkdir` with native the
// `recusive` option when run on an invalid drive under Windows.
const error = new Error(`operation not permitted, mkdir '${pth}'`);
error.code = 'EPERM';
error.errno = -4048;
error.path = pth;
error.syscall = 'mkdir';
return error;
};
const makeDir = async (input, options) => {
checkPath(input);
options = processOptions(options);
const mkdir = promisify(options.fs.mkdir);
const stat = promisify(options.fs.stat);
if (useNativeRecursiveOption && options.fs.mkdir === fs.mkdir) {
const pth = path.resolve(input);
await mkdir(pth, {
mode: options.mode,
recursive: true
});
return pth;
}
const make = async pth => {
try {
await mkdir(pth, options.mode);
return pth;
} catch (error) {
if (error.code === 'EPERM') {
throw error;
}
if (error.code === 'ENOENT') {
if (path.dirname(pth) === pth) {
throw permissionError(pth);
}
if (error.message.includes('null bytes')) {
throw error;
}
await make(path.dirname(pth));
return make(pth);
}
try {
const stats = await stat(pth);
if (!stats.isDirectory()) {
throw new Error('The path is not a directory');
}
} catch (_) {
throw error;
}
return pth;
}
};
return make(path.resolve(input));
};
module.exports = makeDir;
module.exports.sync = (input, options) => {
checkPath(input);
options = processOptions(options);
if (useNativeRecursiveOption && options.fs.mkdirSync === fs.mkdirSync) {
const pth = path.resolve(input);
fs.mkdirSync(pth, {
mode: options.mode,
recursive: true
});
return pth;
}
const make = pth => {
try {
options.fs.mkdirSync(pth, options.mode);
} catch (error) {
if (error.code === 'EPERM') {
throw error;
}
if (error.code === 'ENOENT') {
if (path.dirname(pth) === pth) {
throw permissionError(pth);
}
if (error.message.includes('null bytes')) {
throw error;
}
make(path.dirname(pth));
return make(pth);
}
try {
if (!options.fs.statSync(pth).isDirectory()) {
throw new Error('The path is not a directory');
}
} catch (_) {
throw error;
}
}
return pth;
};
return make(path.resolve(input));
};