diff --git a/packages/metro-cache/src/stores/FileStore.js b/packages/metro-cache/src/stores/FileStore.js index 46088b9483..595b35462e 100644 --- a/packages/metro-cache/src/stores/FileStore.js +++ b/packages/metro-cache/src/stores/FileStore.js @@ -49,15 +49,29 @@ class FileStore { } set(key: Buffer, value: T): void { + const filePath = this._getFilePath(key); + try { + this._set(filePath, value); + } catch (err) { + if (err.code === 'ENOENT') { + mkdirp.sync(path.dirname(filePath)); + this._set(filePath, value); + } else { + throw err; + } + } + } + + _set(filePath: string, value: T): void { if (value instanceof Buffer) { - const fd = fs.openSync(this._getFilePath(key), 'w'); + const fd = fs.openSync(filePath, 'w'); fs.writeSync(fd, NULL_BYTE_BUFFER); fs.writeSync(fd, value); fs.closeSync(fd); } else { - fs.writeFileSync(this._getFilePath(key), JSON.stringify(value)); + fs.writeFileSync(filePath, JSON.stringify(value)); } } diff --git a/packages/metro-cache/src/stores/__tests__/FileStore-test.js b/packages/metro-cache/src/stores/__tests__/FileStore-test.js index 84e4aca71c..33005b09b0 100644 --- a/packages/metro-cache/src/stores/__tests__/FileStore-test.js +++ b/packages/metro-cache/src/stores/__tests__/FileStore-test.js @@ -41,6 +41,16 @@ describe('FileStore', () => { expect(fileStore.get(cache)).toEqual(null); }); + it('writes into cache if folder is missing', () => { + const fileStore = new FileStore({root: '/root'}); + const cache = Buffer.from([0xfa, 0xce, 0xb0, 0x0c]); + const data = Buffer.from([0xca, 0xc4, 0xe5]); + + require('rimraf').sync('/root'); + fileStore.set(cache, data); + expect(fileStore.get(cache)).toEqual(data); + }); + it('reads and writes binary data', () => { const fileStore = new FileStore({root: '/root'}); const cache = Buffer.from([0xfa, 0xce, 0xb0, 0x0c]); diff --git a/packages/metro-memory-fs/src/index.js b/packages/metro-memory-fs/src/index.js index 2fd6bf0783..42f935b68c 100644 --- a/packages/metro-memory-fs/src/index.js +++ b/packages/metro-memory-fs/src/index.js @@ -570,6 +570,23 @@ class MemoryFs { dirNode.entries.set(basename, this._makeDir(mode)); }; + rmdirSync = (dirPath: string | Buffer): void => { + dirPath = pathStr(dirPath); + const {dirNode, node, basename} = this._resolve(dirPath); + if (node == null) { + throw makeError('ENOENT', dirPath, 'directory does not exist'); + } else if (node.type === 'file') { + if (this._platform === 'posix') { + throw makeError('ENOTDIR', dirPath, 'cannot rm a file'); + } else { + throw makeError('ENOENT', dirPath, 'cannot rm a file'); + } + } else if (node.type === 'directory' && node.entries.size) { + throw makeError('ENOTEMPTY', dirPath, 'directory not empty'); + } + dirNode.entries.delete(basename); + }; + symlinkSync = ( target: string | Buffer, filePath: FilePath,