1
0
Fork 0

Simplify mkdirP implementation (#781)

Co-authored-by: Linus Unnebäck <linus@folkdatorn.se>
pull/590/head
Thomas Boop 2021-04-28 14:38:41 -04:00 committed by GitHub
parent dd046652c3
commit 15fef78171
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 3 additions and 74 deletions

View File

@ -3,7 +3,6 @@ import {promises as fs} from 'fs'
import * as os from 'os' import * as os from 'os'
import * as path from 'path' import * as path from 'path'
import * as io from '../src/io' import * as io from '../src/io'
import * as ioUtil from '../src/io-util'
describe('cp', () => { describe('cp', () => {
beforeAll(async () => { beforeAll(async () => {
@ -825,31 +824,6 @@ describe('mkdirP', () => {
(await fs.lstat(path.join(realDirPath, 'sub_dir'))).isDirectory() (await fs.lstat(path.join(realDirPath, 'sub_dir'))).isDirectory()
).toBe(true) ).toBe(true)
}) })
it('breaks if mkdirP loop out of control', async () => {
const testPath = path.join(
getTestTemp(),
'mkdirP_failsafe',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10'
)
expect.assertions(1)
try {
await ioUtil.mkdirP(testPath, 10)
} catch (err) {
expect(err.code).toBe('ENOENT')
}
})
}) })
describe('which', () => { describe('which', () => {

View File

@ -1,4 +1,3 @@
import {ok} from 'assert'
import * as fs from 'fs' import * as fs from 'fs'
import * as path from 'path' import * as path from 'path'
@ -59,52 +58,6 @@ export function isRooted(p: string): boolean {
return p.startsWith('/') return p.startsWith('/')
} }
/**
* Recursively create a directory at `fsPath`.
*
* This implementation is optimistic, meaning it attempts to create the full
* path first, and backs up the path stack from there.
*
* @param fsPath The path to create
* @param maxDepth The maximum recursion depth
* @param depth The current recursion depth
*/
export async function mkdirP(
fsPath: string,
maxDepth: number = 1000,
depth: number = 1
): Promise<void> {
ok(fsPath, 'a path argument must be provided')
fsPath = path.resolve(fsPath)
if (depth >= maxDepth) return mkdir(fsPath)
try {
await mkdir(fsPath)
return
} catch (err) {
switch (err.code) {
case 'ENOENT': {
await mkdirP(path.dirname(fsPath), maxDepth, depth + 1)
await mkdir(fsPath)
return
}
default: {
let stats: fs.Stats
try {
stats = await stat(fsPath)
} catch (err2) {
throw err
}
if (!stats.isDirectory()) throw err
}
}
}
}
/** /**
* Best effort attempt to determine whether a file exists and is executable. * Best effort attempt to determine whether a file exists and is executable.
* @param filePath file path to check * @param filePath file path to check

View File

@ -1,3 +1,4 @@
import {ok} from 'assert'
import * as childProcess from 'child_process' import * as childProcess from 'child_process'
import * as path from 'path' import * as path from 'path'
import {promisify} from 'util' import {promisify} from 'util'
@ -161,7 +162,8 @@ export async function rmRF(inputPath: string): Promise<void> {
* @returns Promise<void> * @returns Promise<void>
*/ */
export async function mkdirP(fsPath: string): Promise<void> { export async function mkdirP(fsPath: string): Promise<void> {
await ioUtil.mkdirP(fsPath) ok(fsPath, 'a path argument must be provided')
await ioUtil.mkdir(fsPath, {recursive: true})
} }
/** /**