1const {dirname} = require('path')
2
3const mkdirpManual = (path, opts, made) => {
4  opts.recursive = false
5  const parent = dirname(path)
6  if (parent === path) {
7    return opts.mkdirAsync(path, opts).catch(er => {
8      // swallowed by recursive implementation on posix systems
9      // any other error is a failure
10      if (er.code !== 'EISDIR')
11        throw er
12    })
13  }
14
15  return opts.mkdirAsync(path, opts).then(() => made || path, er => {
16    if (er.code === 'ENOENT')
17      return mkdirpManual(parent, opts)
18        .then(made => mkdirpManual(path, opts, made))
19    if (er.code !== 'EEXIST' && er.code !== 'EROFS')
20      throw er
21    return opts.statAsync(path).then(st => {
22      if (st.isDirectory())
23        return made
24      else
25        throw er
26    }, () => { throw er })
27  })
28}
29
30const mkdirpManualSync = (path, opts, made) => {
31  const parent = dirname(path)
32  opts.recursive = false
33
34  if (parent === path) {
35    try {
36      return opts.mkdirSync(path, opts)
37    } catch (er) {
38      // swallowed by recursive implementation on posix systems
39      // any other error is a failure
40      if (er.code !== 'EISDIR')
41        throw er
42      else
43        return
44    }
45  }
46
47  try {
48    opts.mkdirSync(path, opts)
49    return made || path
50  } catch (er) {
51    if (er.code === 'ENOENT')
52      return mkdirpManualSync(path, opts, mkdirpManualSync(parent, opts, made))
53    if (er.code !== 'EEXIST' && er.code !== 'EROFS')
54      throw er
55    try {
56      if (!opts.statSync(path).isDirectory())
57        throw er
58    } catch (_) {
59      throw er
60    }
61  }
62}
63
64module.exports = {mkdirpManual, mkdirpManualSync}
65