index.js 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. 'use strict';
  2. const fs = require('fs');
  3. const path = require('path');
  4. const pify = require('pify');
  5. const defaults = {
  6. mode: 0o777 & (~process.umask()),
  7. fs
  8. };
  9. // https://github.com/nodejs/node/issues/8987
  10. // https://github.com/libuv/libuv/pull/1088
  11. const checkPath = pth => {
  12. if (process.platform === 'win32') {
  13. const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path.parse(pth).root, ''));
  14. if (pathHasInvalidWinCharacters) {
  15. const err = new Error(`Path contains invalid characters: ${pth}`);
  16. err.code = 'EINVAL';
  17. throw err;
  18. }
  19. }
  20. };
  21. module.exports = (input, opts) => Promise.resolve().then(() => {
  22. checkPath(input);
  23. opts = Object.assign({}, defaults, opts);
  24. const mkdir = pify(opts.fs.mkdir);
  25. const stat = pify(opts.fs.stat);
  26. const make = pth => {
  27. return mkdir(pth, opts.mode)
  28. .then(() => pth)
  29. .catch(err => {
  30. if (err.code === 'ENOENT') {
  31. if (err.message.includes('null bytes') || path.dirname(pth) === pth) {
  32. throw err;
  33. }
  34. return make(path.dirname(pth)).then(() => make(pth));
  35. }
  36. return stat(pth)
  37. .then(stats => stats.isDirectory() ? pth : Promise.reject())
  38. .catch(() => {
  39. throw err;
  40. });
  41. });
  42. };
  43. return make(path.resolve(input));
  44. });
  45. module.exports.sync = (input, opts) => {
  46. checkPath(input);
  47. opts = Object.assign({}, defaults, opts);
  48. const make = pth => {
  49. try {
  50. opts.fs.mkdirSync(pth, opts.mode);
  51. } catch (err) {
  52. if (err.code === 'ENOENT') {
  53. if (err.message.includes('null bytes') || path.dirname(pth) === pth) {
  54. throw err;
  55. }
  56. make(path.dirname(pth));
  57. return make(pth);
  58. }
  59. try {
  60. if (!opts.fs.statSync(pth).isDirectory()) {
  61. throw new Error('The path is not a directory');
  62. }
  63. } catch (_) {
  64. throw err;
  65. }
  66. }
  67. return pth;
  68. };
  69. return make(path.resolve(input));
  70. };