diff --git a/flow-typed/npm/mkdirp_v0.5.x.js b/flow-typed/npm/mkdirp_v0.5.x.js deleted file mode 100644 index 92900f9413..0000000000 --- a/flow-typed/npm/mkdirp_v0.5.x.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - * @format - */ - -declare module 'mkdirp' { - declare type Options = - | number - | { - mode?: number, - fs?: mixed, - ... - }; - - declare type Callback = (err: ?Error, path: ?string) => void; - - declare module.exports: { - (path: string, options?: Options | Callback, callback?: Callback): void, - sync(path: string, options?: Options): void, - ... - }; -} diff --git a/package.json b/package.json index a8cb42141a..45102e5e56 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ "jest": "^26.6.3", "lerna": "2.4.0", "micromatch": "^4.0.2", - "mkdirp": "^0.5.1", "prettier": "^2.4.1", "progress": "^2.0.0", "promise": "^8.0.3", diff --git a/packages/buck-worker-tool/package.json b/packages/buck-worker-tool/package.json index ca12b8e156..2b6cc54ac6 100644 --- a/packages/buck-worker-tool/package.json +++ b/packages/buck-worker-tool/package.json @@ -12,8 +12,7 @@ "temp": "^0.8.3" }, "devDependencies": { - "metro-memory-fs": "0.68.0", - "mkdirp": "^0.5.1" + "metro-memory-fs": "0.68.0" }, "scripts": { "prepare-release": "test -d build && rm -rf src.real && mv src src.real && mv build src", diff --git a/packages/buck-worker-tool/src/__tests__/worker-test.js b/packages/buck-worker-tool/src/__tests__/worker-test.js index ff14d461ef..e519c06ed1 100644 --- a/packages/buck-worker-tool/src/__tests__/worker-test.js +++ b/packages/buck-worker-tool/src/__tests__/worker-test.js @@ -35,7 +35,6 @@ const buckWorker = require('../worker-tool'); // mocked const {Console} = require('console'); const fs = require('fs'); -const mkdirp = require('mkdirp'); const path = require('path'); const {any, anything} = expect; @@ -123,7 +122,7 @@ describe('Buck worker:', () => { fs.writeFileSync(path.join(dirPath, key), entry || ''); } else { const subDirPath = path.join(dirPath, key); - mkdirp.sync(subDirPath); + fs.mkdirSync(subDirPath, {recursive: true}); writeFiles(entry, subDirPath); } } diff --git a/packages/metro-cache/package.json b/packages/metro-cache/package.json index 0f6217afaa..1605f4750d 100644 --- a/packages/metro-cache/package.json +++ b/packages/metro-cache/package.json @@ -13,7 +13,6 @@ }, "dependencies": { "metro-core": "0.68.0", - "mkdirp": "^0.5.1", "rimraf": "^2.5.4" }, "devDependencies": { diff --git a/packages/metro-cache/src/stores/FileStore.js b/packages/metro-cache/src/stores/FileStore.js index f62b396df2..ff42cb9782 100644 --- a/packages/metro-cache/src/stores/FileStore.js +++ b/packages/metro-cache/src/stores/FileStore.js @@ -11,7 +11,6 @@ 'use strict'; const fs = require('fs'); -const mkdirp = require('mkdirp'); const path = require('path'); const rimraf = require('rimraf'); @@ -54,7 +53,7 @@ class FileStore { await this._set(filePath, value); } catch (err) { if (err.code === 'ENOENT') { - mkdirp.sync(path.dirname(filePath)); + fs.mkdirSync(path.dirname(filePath), {recursive: true}); await this._set(filePath, value); } else { throw err; @@ -87,7 +86,9 @@ class FileStore { _createDirs() { for (let i = 0; i < 256; i++) { - mkdirp.sync(path.join(this._root, ('0' + i.toString(16)).slice(-2))); + fs.mkdirSync(path.join(this._root, ('0' + i.toString(16)).slice(-2)), { + recursive: true, + }); } } diff --git a/packages/metro-memory-fs/src/index.js b/packages/metro-memory-fs/src/index.js index d3d22678c6..4f0f215e35 100644 --- a/packages/metro-memory-fs/src/index.js +++ b/packages/metro-memory-fs/src/index.js @@ -675,19 +675,57 @@ class MemoryFs { } }; - mkdirSync: (dirPath: string | Buffer, mode?: number) => void = ( + mkdirSync: ( dirPath: string | Buffer, - mode?: number, + options?: number | {recursive?: boolean, mode?: number}, + ) => void = ( + dirPath: string | Buffer, + options?: number | {recursive?: boolean, mode?: number}, ): void => { - if (mode == null) { - mode = 0o777; - } + const recursive = typeof options != 'number' && options?.recursive; + const mode = + (typeof options == 'number' ? options : options?.mode) ?? 0o777; + dirPath = pathStr(dirPath); - const {dirNode, node, basename} = this._resolve(dirPath); - if (node != null) { - throw makeError('EEXIST', dirPath, 'directory or file already exists'); + if (recursive) { + const {drive, entNames} = this._parsePathWithCwd(dirPath); + const root = this._getRoot(drive, dirPath); + const context = { + drive, + node: root, + nodePath: [['', root]], + entNames, + symlinkCount: 0, + keepFinalSymlink: false, + }; + + while (context.entNames.length > 0) { + const entName = context.entNames.shift(); + this._resolveEnt(context, dirPath, entName); + if (context.node == null) { + const [_parentName, parentNode] = + context.nodePath[context.nodePath.length - 2]; + const childPair = context.nodePath[context.nodePath.length - 1]; + if (parentNode && parentNode.type === 'directory') { + context.node = this._makeDir(mode); + parentNode.entries.set(entName, context.node); + childPair[1] = context.node; + } else { + throw makeError( + 'EEXIST', + dirPath, + 'directory or file already exists', + ); + } + } + } + } else { + const {dirNode, node, basename} = this._resolve(dirPath); + if (node != null) { + throw makeError('EEXIST', dirPath, 'directory or file already exists'); + } + dirNode.entries.set(basename, this._makeDir(mode)); } - dirNode.entries.set(basename, this._makeDir(mode)); }; mkdtempSync: ( @@ -1216,21 +1254,10 @@ class MemoryFs { return {entNames: filePath.split(sep), drive}; } - /** - * Implemented according with - * http://man7.org/linux/man-pages/man7/path_resolution.7.html - */ - _resolve( - filePath: string, - options?: {keepFinalSymlink: boolean, ...}, - ): Resolution { - let keepFinalSymlink = false; - if (options != null) { - ({keepFinalSymlink} = options); - } - if (filePath === '') { - throw makeError('ENOENT', filePath, 'no such file or directory'); - } + _parsePathWithCwd(filePath: string): {| + +drive: string, + +entNames: Array, + |} { let {drive, entNames} = this._parsePath(filePath); if (drive == null) { const {_cwd} = this; @@ -1252,6 +1279,25 @@ class MemoryFs { } entNames = cwPath.entNames.concat(entNames); } + return {drive, entNames}; + } + + /** + * Implemented according with + * http://man7.org/linux/man-pages/man7/path_resolution.7.html + */ + _resolve( + filePath: string, + options?: {keepFinalSymlink: boolean, ...}, + ): Resolution { + let keepFinalSymlink = false; + if (options != null) { + ({keepFinalSymlink} = options); + } + if (filePath === '') { + throw makeError('ENOENT', filePath, 'no such file or directory'); + } + const {drive, entNames} = this._parsePathWithCwd(filePath); checkPathLength(entNames, filePath); const root = this._getRoot(drive, filePath); const context = { diff --git a/packages/metro-transform-worker/package.json b/packages/metro-transform-worker/package.json index ae8177c1d4..d0f7b330c5 100644 --- a/packages/metro-transform-worker/package.json +++ b/packages/metro-transform-worker/package.json @@ -30,7 +30,6 @@ "devDependencies": { "metro-memory-fs": "0.68.0", "metro-minify-uglify": "0.68.0", - "metro-react-native-babel-transformer": "0.68.0", - "mkdirp": "^0.5.1" + "metro-react-native-babel-transformer": "0.68.0" } } diff --git a/packages/metro-transform-worker/src/__tests__/index-test.js b/packages/metro-transform-worker/src/__tests__/index-test.js index feed5e725f..34d776f088 100644 --- a/packages/metro-transform-worker/src/__tests__/index-test.js +++ b/packages/metro-transform-worker/src/__tests__/index-test.js @@ -39,7 +39,6 @@ const HEADER_DEV = const HEADER_PROD = '__d(function (g, r, i, a, m, e, d) {'; let fs; -let mkdirp; let Transformer; const baseConfig: JsTransformerConfig = { @@ -72,12 +71,11 @@ beforeEach(() => { jest.mock('fs', () => new (require('metro-memory-fs'))()); fs = require('fs'); - mkdirp = require('mkdirp'); Transformer = require('../'); fs.reset(); - mkdirp.sync('/root/local'); - mkdirp.sync(path.dirname(babelTransformerPath)); + fs.mkdirSync('/root/local', {recursive: true}); + fs.mkdirSync(path.dirname(babelTransformerPath), {recursive: true}); fs.writeFileSync(babelTransformerPath, transformerContents); }); diff --git a/packages/metro/package.json b/packages/metro/package.json index acec493403..3a1595bc4f 100644 --- a/packages/metro/package.json +++ b/packages/metro/package.json @@ -53,7 +53,6 @@ "metro-transform-plugins": "0.68.0", "metro-transform-worker": "0.68.0", "mime-types": "^2.1.27", - "mkdirp": "^0.5.1", "node-fetch": "^2.2.0", "nullthrows": "^1.1.1", "rimraf": "^2.5.4", diff --git a/packages/metro/src/DeltaBundler/__tests__/Transformer-test.js b/packages/metro/src/DeltaBundler/__tests__/Transformer-test.js index 4cd7c8ab55..423c0f4a9c 100644 --- a/packages/metro/src/DeltaBundler/__tests__/Transformer-test.js +++ b/packages/metro/src/DeltaBundler/__tests__/Transformer-test.js @@ -22,7 +22,6 @@ var Transformer = require('../Transformer'); var fs = require('fs'); var {getDefaultValues} = require('metro-config/src/defaults'); var {mergeConfig} = require('metro-config/src/loadConfig'); -const mkdirp = require('mkdirp'); describe('Transformer', function () { let watchFolders; @@ -53,8 +52,8 @@ describe('Transformer', function () { projectRoot = '/root'; watchFolders = [projectRoot]; - mkdirp.sync('/path/to'); - mkdirp.sync('/root'); + fs.mkdirSync('/path/to', {recursive: true}); + fs.mkdirSync('/root', {recursive: true}); fs.writeFileSync('/path/to/transformer.js', ''); require('../getTransformCacheKey').mockClear(); diff --git a/packages/metro/src/__tests__/Assets-test.js b/packages/metro/src/__tests__/Assets-test.js index aa95675af6..1c8775b5b6 100644 --- a/packages/metro/src/__tests__/Assets-test.js +++ b/packages/metro/src/__tests__/Assets-test.js @@ -16,7 +16,6 @@ jest.mock('image-size'); const {getAsset, getAssetData} = require('../Assets'); const crypto = require('crypto'); const fs = require('fs'); -const mkdirp = require('mkdirp'); const path = require('path'); const mockImageWidth = 300; @@ -30,7 +29,7 @@ require('image-size').mockReturnValue({ describe('getAsset', () => { beforeEach(() => { fs.reset(); - mkdirp.sync('/root/imgs'); + fs.mkdirSync('/root/imgs', {recursive: true}); }); it('should fail if the extension is not registerd', async () => { @@ -121,7 +120,7 @@ describe('getAsset', () => { }); it('should find an image located on a watchFolder', async () => { - mkdirp.sync('/anotherfolder'); + fs.mkdirSync('/anotherfolder', {recursive: true}); writeImages({ '../../anotherfolder/b.png': 'b image', @@ -139,7 +138,7 @@ describe('getAsset', () => { }); it('should throw an error if an image is not located on any watchFolder', async () => { - mkdirp.sync('/anotherfolder'); + fs.mkdirSync('/anotherfolder', {recursive: true}); writeImages({ '../../anotherfolder/b.png': 'b image', @@ -154,7 +153,7 @@ describe('getAsset', () => { describe('getAssetData', () => { beforeEach(() => { fs.reset(); - mkdirp.sync('/root/imgs'); + fs.mkdirSync('/root/imgs', {recursive: true}); }); it('should get assetData', () => { diff --git a/packages/metro/src/shared/output/RamBundle/as-assets.js b/packages/metro/src/shared/output/RamBundle/as-assets.js index e94886b078..c0674e1f38 100644 --- a/packages/metro/src/shared/output/RamBundle/as-assets.js +++ b/packages/metro/src/shared/output/RamBundle/as-assets.js @@ -20,7 +20,7 @@ const buildSourcemapWithMetadata = require('./buildSourcemapWithMetadata'); const MAGIC_RAM_BUNDLE_NUMBER = require('./magic-number'); const {joinModules} = require('./util'); const writeSourceMap = require('./write-sourcemap'); -const mkdirp = require('mkdirp'); +const fsPromises = require('fs').promises; const path = require('path'); // must not start with a dot, as that won't go into the apk const MAGIC_RAM_BUNDLE_FILENAME = 'UNBUNDLE'; @@ -85,10 +85,8 @@ function saveAsAssets( } } -function createDir(dirName: string): Promise { - return new Promise((resolve: void => void, reject: mixed => mixed) => - mkdirp(dirName, error => (error ? reject(error) : resolve())), - ); +function createDir(dirName: string): Promise { + return fsPromises.mkdir(dirName, {recursive: true}); } function writeModuleFile( diff --git a/scripts/build.js b/scripts/build.js index d7754c3fc6..08f0505d7c 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -29,7 +29,6 @@ const chalk = require('chalk'); const fs = require('fs'); const glob = require('glob'); const micromatch = require('micromatch'); -const mkdirp = require('mkdirp'); const path = require('path'); const prettier = require('prettier'); @@ -80,7 +79,7 @@ function buildPackage(p) { function buildFile(file, silent) { const destPath = getBuildPath(file, BUILD_DIR); - mkdirp.sync(path.dirname(destPath)); + fs.mkdirSync(path.dirname(destPath), {recursive: true}); if (micromatch.isMatch(file, IGNORE_PATTERN)) { silent || process.stdout.write( diff --git a/yarn.lock b/yarn.lock index b466b24371..829c038358 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5598,7 +5598,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.1, mkdirp@~0.5.0: +mkdirp@~0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.3.tgz#5a514b7179259287952881e94410ec5465659f8c" integrity sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==