forked from dominictarr/node-mkdirp
-
-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
282 additions
and
132 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,68 @@ | ||
#!/usr/bin/env node | ||
|
||
var mkdirp = require('../'); | ||
var minimist = require('minimist'); | ||
var fs = require('fs'); | ||
|
||
var argv = minimist(process.argv.slice(2), { | ||
alias: { m: 'mode', h: 'help' }, | ||
string: [ 'mode' ] | ||
}); | ||
if (argv.help) { | ||
fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout); | ||
return; | ||
} | ||
const usage = () => ` | ||
usage: mkdirp [DIR1,DIR2..] {OPTIONS} | ||
Create each supplied directory including any necessary parent directories | ||
that don't yet exist. | ||
If the directory already exists, do nothing. | ||
OPTIONS are: | ||
-m<mode> If a directory needs to be created, set the mode as an octal | ||
--mode=<mode> permission string. | ||
-v --version Print the mkdirp version number | ||
var paths = argv._.slice(); | ||
var mode = argv.mode ? parseInt(argv.mode, 8) : undefined; | ||
|
||
(function next () { | ||
if (paths.length === 0) return; | ||
var p = paths.shift(); | ||
|
||
if (mode === undefined) mkdirp(p, cb) | ||
else mkdirp(p, mode, cb) | ||
|
||
function cb (err) { | ||
if (err) { | ||
console.error(err.message); | ||
process.exit(1); | ||
} | ||
else next(); | ||
-h --help Print this helpful banner | ||
-p --print Print the first directories created for each path provided | ||
--manual Use manual implementation, even if native is available | ||
` | ||
|
||
const dirs = [] | ||
const opts = {} | ||
let print = false | ||
let dashdash = false | ||
let manual = false | ||
for (const arg of process.argv.slice(2)) { | ||
if (dashdash) | ||
dirs.push(arg) | ||
else if (arg === '--') | ||
dashdash = true | ||
else if (arg === '--manual') | ||
manual = true | ||
else if (/^-h/.test(arg) || /^--help/.test(arg)) { | ||
console.log(usage()) | ||
process.exit(0) | ||
} else if (arg === '-v' || arg === '--version') { | ||
console.log(require('../package.json').version) | ||
process.exit(0) | ||
} else if (arg === '-p' || arg === '--print') { | ||
print = true | ||
} else if (/^-m/.test(arg) || /^--mode=/.test(arg)) { | ||
const mode = parseInt(arg.replace(/^(-m|--mode=)/, ''), 8) | ||
if (isNaN(mode)) { | ||
console.error(`invalid mode argument: ${arg}\nMust be an octal number.`) | ||
process.exit(1) | ||
} | ||
})(); | ||
opts.mode = mode | ||
} else | ||
dirs.push(arg) | ||
} | ||
|
||
const mkdirp = require('../') | ||
const impl = manual ? mkdirp.manual : mkdirp | ||
if (dirs.length === 0) | ||
console.error(usage()) | ||
|
||
Promise.all(dirs.map(dir => impl(dir, opts))) | ||
.then(made => print ? made.forEach(m => m && console.log(m)) : null) | ||
.catch(er => { | ||
console.error(er.message) | ||
if (er.code) | ||
console.error(' code: ' + er.code) | ||
process.exit(1) | ||
}) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,98 +1,31 @@ | ||
var path = require('path'); | ||
var fs = require('fs'); | ||
var _0777 = parseInt('0777', 8); | ||
const optsArg = require('./lib/opts-arg.js') | ||
const pathArg = require('./lib/path-arg.js') | ||
|
||
module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; | ||
const {mkdirpNative, mkdirpNativeSync} = require('./lib/mkdirp-native.js') | ||
const {mkdirpManual, mkdirpManualSync} = require('./lib/mkdirp-manual.js') | ||
const {useNative, useNativeSync} = require('./lib/use-native.js') | ||
|
||
function mkdirP (p, opts, f, made) { | ||
if (typeof opts === 'function') { | ||
f = opts; | ||
opts = {}; | ||
} | ||
else if (!opts || typeof opts !== 'object') { | ||
opts = { mode: opts }; | ||
} | ||
|
||
var mode = opts.mode; | ||
var xfs = opts.fs || fs; | ||
|
||
if (mode === undefined) { | ||
mode = _0777 & (~process.umask()); | ||
} | ||
if (!made) made = null; | ||
|
||
var cb = f || function () {}; | ||
p = path.resolve(p); | ||
|
||
xfs.mkdir(p, mode, function (er) { | ||
if (!er) { | ||
made = made || p; | ||
return cb(null, made); | ||
} | ||
switch (er.code) { | ||
case 'ENOENT': | ||
mkdirP(path.dirname(p), opts, function (er, made) { | ||
if (er) cb(er, made); | ||
else mkdirP(p, opts, cb, made); | ||
}); | ||
break; | ||
|
||
// In the case of any other error, just see if there's a dir | ||
// there already. If so, then hooray! If not, then something | ||
// is borked. | ||
default: | ||
xfs.stat(p, function (er2, stat) { | ||
// if the stat fails, then that's super weird. | ||
// let the original error be the failure reason. | ||
if (er2 || !stat.isDirectory()) cb(er, made) | ||
else cb(null, made); | ||
}); | ||
break; | ||
} | ||
}); | ||
const mkdirp = (path, opts) => { | ||
path = pathArg(path) | ||
opts = optsArg(opts) | ||
return useNative(opts) | ||
? mkdirpNative(path, opts) | ||
: mkdirpManual(path, opts) | ||
} | ||
|
||
mkdirP.sync = function sync (p, opts, made) { | ||
if (!opts || typeof opts !== 'object') { | ||
opts = { mode: opts }; | ||
} | ||
|
||
var mode = opts.mode; | ||
var xfs = opts.fs || fs; | ||
|
||
if (mode === undefined) { | ||
mode = _0777 & (~process.umask()); | ||
} | ||
if (!made) made = null; | ||
|
||
p = path.resolve(p); | ||
|
||
try { | ||
xfs.mkdirSync(p, mode); | ||
made = made || p; | ||
} | ||
catch (err0) { | ||
switch (err0.code) { | ||
case 'ENOENT' : | ||
made = sync(path.dirname(p), opts, made); | ||
sync(p, opts, made); | ||
break; | ||
const mkdirpSync = (path, opts) => { | ||
path = pathArg(path) | ||
opts = optsArg(opts) | ||
return useNativeSync(opts) | ||
? mkdirpNativeSync(path, opts) | ||
: mkdirpManualSync(path, opts) | ||
} | ||
|
||
// In the case of any other error, just see if there's a dir | ||
// there already. If so, then hooray! If not, then something | ||
// is borked. | ||
default: | ||
var stat; | ||
try { | ||
stat = xfs.statSync(p); | ||
} | ||
catch (err1) { | ||
throw err0; | ||
} | ||
if (!stat.isDirectory()) throw err0; | ||
break; | ||
} | ||
} | ||
mkdirp.sync = mkdirpSync | ||
mkdirp.native = (path, opts) => mkdirpNative(pathArg(path), optsArg(opts)) | ||
mkdirp.manual = (path, opts) => mkdirpManual(pathArg(path), optsArg(opts)) | ||
mkdirp.nativeSync = (path, opts) => mkdirpNativeSync(pathArg(path), optsArg(opts)) | ||
mkdirp.manualSync = (path, opts) => mkdirpManualSync(pathArg(path), optsArg(opts)) | ||
|
||
return made; | ||
}; | ||
module.exports = mkdirp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
const {dirname} = require('path') | ||
|
||
const findMade = (opts, parent, path = undefined) => { | ||
// we never want the 'made' return value to be a root directory | ||
if (path === parent) | ||
return Promise.resolve() | ||
|
||
return opts.statAsync(parent).then( | ||
st => st.isDirectory() ? path : undefined, // will fail later | ||
er => er.code === 'ENOENT' | ||
? findMade(opts, dirname(parent), parent) | ||
: undefined | ||
) | ||
} | ||
|
||
const findMadeSync = (opts, parent, path = undefined) => { | ||
if (path === parent) | ||
return undefined | ||
|
||
try { | ||
return opts.statSync(parent).isDirectory() ? path : undefined | ||
} catch (er) { | ||
return er.code === 'ENOENT' | ||
? findMadeSync(opts, dirname(parent), parent) | ||
: undefined | ||
} | ||
} | ||
|
||
module.exports = {findMade, findMadeSync} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
const {dirname} = require('path') | ||
|
||
const mkdirpManual = (path, opts, made) => { | ||
opts.recursive = false | ||
const parent = dirname(path) | ||
if (parent === path) { | ||
return opts.mkdirAsync(path, opts).catch(er => { | ||
// swallowed by recursive implementation on posix systems | ||
// any other error is a failure | ||
if (er.code !== 'EISDIR') | ||
throw er | ||
}) | ||
} | ||
|
||
return opts.mkdirAsync(path, opts).then(() => made || path, er => { | ||
if (er.code === 'ENOENT') | ||
return mkdirpManual(parent, opts) | ||
.then(made => mkdirpManual(path, opts, made)) | ||
if (er.code !== 'EEXIST') | ||
throw er | ||
return opts.statAsync(path).then(st => { | ||
if (st.isDirectory()) | ||
return made | ||
else | ||
throw er | ||
}, () => { throw er }) | ||
}) | ||
} | ||
|
||
const mkdirpManualSync = (path, opts, made) => { | ||
const parent = dirname(path) | ||
opts.recursive = false | ||
|
||
if (parent === path) { | ||
try { | ||
return opts.mkdirSync(path, opts) | ||
} catch (er) { | ||
// swallowed by recursive implementation on posix systems | ||
// any other error is a failure | ||
if (er.code !== 'EISDIR') | ||
throw er | ||
else | ||
return | ||
} | ||
} | ||
|
||
try { | ||
opts.mkdirSync(path, opts) | ||
return made || path | ||
} catch (er) { | ||
if (er.code === 'ENOENT') | ||
return mkdirpManualSync(path, opts, mkdirpManualSync(parent, opts, made)) | ||
if (er.code !== 'EEXIST') | ||
throw er | ||
try { | ||
if (!opts.statSync(path).isDirectory()) | ||
throw er | ||
} catch (_) { | ||
throw er | ||
} | ||
} | ||
} | ||
|
||
module.exports = {mkdirpManual, mkdirpManualSync} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
const {dirname} = require('path') | ||
const {findMade, findMadeSync} = require('./find-made.js') | ||
const {mkdirpManual, mkdirpManualSync} = require('./mkdirp-manual.js') | ||
|
||
const mkdirpNative = (path, opts) => { | ||
opts.recursive = true | ||
const parent = dirname(path) | ||
if (parent === path) | ||
return opts.mkdirAsync(path, opts) | ||
|
||
return findMade(opts, path).then(made => | ||
opts.mkdirAsync(path, opts).then(() => made) | ||
.catch(er => { | ||
if (er.code === 'ENOENT') | ||
return mkdirpManual(path, opts) | ||
else | ||
throw er | ||
})) | ||
} | ||
|
||
const mkdirpNativeSync = (path, opts) => { | ||
opts.recursive = true | ||
const parent = dirname(path) | ||
if (parent === path) | ||
return opts.mkdirSync(path, opts) | ||
|
||
const made = findMadeSync(opts, path) | ||
try { | ||
opts.mkdirSync(path, opts) | ||
return made | ||
} catch (er) { | ||
if (er.code === 'ENOENT') | ||
return mkdirpManualSync(path, opts) | ||
else | ||
throw er | ||
} | ||
} | ||
|
||
module.exports = {mkdirpNative, mkdirpNativeSync} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
const { promisify } = require('util') | ||
const fs = require('fs') | ||
const optsArg = opts => { | ||
if (!opts) | ||
opts = { mode: 0o777 & (~process.umask()), fs } | ||
else if (typeof opts === 'object') | ||
opts = { mode: 0o777 & (~process.umask()), fs, ...opts } | ||
else if (typeof opts === 'number') | ||
opts = { mode: opts, fs } | ||
else if (typeof opts === 'string') | ||
opts = { mode: parseInt(opts, 8), fs } | ||
else | ||
throw new TypeError('invalid options argument') | ||
|
||
opts.mkdir = opts.mkdir || opts.fs.mkdir || fs.mkdir | ||
opts.mkdirAsync = promisify(opts.mkdir) | ||
opts.stat = opts.stat || opts.fs.stat || fs.stat | ||
opts.statAsync = promisify(opts.stat) | ||
opts.statSync = opts.statSync || opts.fs.statSync || fs.statSync | ||
opts.mkdirSync = opts.mkdirSync || opts.fs.mkdirSync || fs.mkdirSync | ||
return opts | ||
} | ||
module.exports = optsArg |
Oops, something went wrong.