From 7e523b21e578039cf8efed2c8fbec039c5bdcd41 Mon Sep 17 00:00:00 2001 From: Jean Lauliac Date: Wed, 4 Apr 2018 02:50:22 -0700 Subject: [PATCH] metro-memory-fs: add unlinkSync() Reviewed By: rubennorte Differential Revision: D7443805 fbshipit-source-id: 53368103f9230622250be62cde2474c21a930be8 --- .../src/__tests__/index-test.js | 57 +++++++++++++++++++ packages/metro-memory-fs/src/index.js | 18 ++++++ 2 files changed, 75 insertions(+) diff --git a/packages/metro-memory-fs/src/__tests__/index-test.js b/packages/metro-memory-fs/src/__tests__/index-test.js index bca21de1..4ae824ff 100644 --- a/packages/metro-memory-fs/src/__tests__/index-test.js +++ b/packages/metro-memory-fs/src/__tests__/index-test.js @@ -411,6 +411,15 @@ describe('watch', () => { watcher.close(); }); + it('reports unlinked files', () => { + const changedPaths = []; + fs.writeFileSync('/bar.txt', 'text'); + const watcher = collectWatchEvents('/', {}, changedPaths); + fs.unlinkSync('/bar.txt'); + expect(changedPaths).toEqual([['rename', 'bar.txt']]); + watcher.close(); + }); + function collectWatchEvents(entPath, options, events) { return fs.watch(entPath, options, (eventName, filePath) => { events.push([eventName, filePath]); @@ -418,6 +427,54 @@ describe('watch', () => { } }); +describe('unlink', () => { + it('removes a file', () => { + fs.writeFileSync('/foo.txt', 'test'); + expect(fs.readdirSync('/')).toEqual(['foo.txt']); + fs.unlinkSync('/foo.txt'); + expect(fs.readdirSync('/')).toEqual([]); + try { + fs.readFileSync('/foo.txt', 'utf8'); + throw new Error('should not reach here'); + } catch (error) { + if (error.code !== 'ENOENT') { + throw error; + } + } + }); + + it('removes a symlink (not the linked file)', () => { + fs.writeFileSync('/foo.txt', 'test'); + fs.symlinkSync('foo.txt', '/bar.txt'); + expect(fs.readdirSync('/')).toEqual(['foo.txt', 'bar.txt']); + fs.unlinkSync('/bar.txt'); + expect(fs.readdirSync('/')).toEqual(['foo.txt']); + }); + + it('throws for non existent files', () => { + try { + fs.unlinkSync('/nonexistent.txt'); + throw new Error('should not reach here'); + } catch (error) { + if (error.code !== 'ENOENT') { + throw error; + } + } + }); + + it('throws for directories', () => { + fs.mkdirSync('/foo'); + try { + fs.unlinkSync('/foo'); + throw new Error('should not reach here'); + } catch (error) { + if (error.code !== 'EISDIR') { + throw error; + } + } + }); +}); + it('throws when trying to read inexistent file', () => { expectFsError('ENOENT', () => fs.readFileSync('/foo.txt')); }); diff --git a/packages/metro-memory-fs/src/index.js b/packages/metro-memory-fs/src/index.js index 6d0a1dee..db2561a1 100644 --- a/packages/metro-memory-fs/src/index.js +++ b/packages/metro-memory-fs/src/index.js @@ -101,6 +101,7 @@ const ASYNC_FUNC_NAMES = [ 'readFile', 'realpath', 'stat', + 'unlink', 'write', 'writeFile', ]; @@ -488,6 +489,23 @@ class MemoryFs { return rst; }; + unlinkSync = (filePath: string | Buffer) => { + filePath = pathStr(filePath); + const {basename, dirNode, dirPath, node} = this._resolve(filePath, { + keepFinalSymlink: true, + }); + if (node == null) { + throw makeError('ENOENT', filePath, 'no such file or directory'); + } + if (node.type !== 'file' && node.type !== 'symbolicLink') { + throw makeError('EISDIR', filePath, 'cannot unlink a directory'); + } + dirNode.entries.delete(basename); + this._emitFileChange(dirPath.concat([[basename, node]]), { + eventType: 'rename', + }); + }; + createWriteStream = ( filePath: string | Buffer, options?: