RM fastfs.js: @flow

Reviewed By: cpojer

Differential Revision: D4118175

fbshipit-source-id: ad9d1f98bcde0c1be17d36c74c3662e6e55165f8
This commit is contained in:
Jean Lauliac 2016-11-03 04:50:19 -07:00 committed by Facebook Github Bot
parent d730928b0c
commit 4fe80636fb
1 changed files with 60 additions and 11 deletions

View File

@ -5,7 +5,10 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
*/
'use strict';
const fs = require('fs');
@ -15,8 +18,34 @@ const {EventEmitter} = require('events');
const NOT_FOUND_IN_ROOTS = 'NotFoundInRootsError';
interface Activity {
startEvent(title: string, m: mixed, opts: mixed): mixed,
endEvent(activity: mixed): void,
}
interface FileWatcher {
on(event: 'all', handler: (type: string, filePath: string, rootPath: string, fstat: fs.Stats) => void): void,
}
class Fastfs extends EventEmitter {
constructor(name, roots, fileWatcher, files, {ignore, activity}) {
_name: string;
_fileWatcher: FileWatcher;
_ignore: (filePath: string) => boolean;
_roots: Array<File>;
_fastPaths: {[filePath: string]: File};
_activity: mixed;
constructor(
name: string,
roots: Array<string>,
fileWatcher: FileWatcher,
files: Array<string>,
{ignore, activity}: {
ignore: (filePath: string) => boolean,
activity: Activity,
},
) {
super();
this._name = name;
this._fileWatcher = fileWatcher;
@ -68,7 +97,7 @@ class Fastfs extends EventEmitter {
}
}
stat(filePath) {
stat(filePath: string) {
return Promise.resolve().then(() => this._getFile(filePath).stat());
}
@ -77,7 +106,10 @@ class Fastfs extends EventEmitter {
.filter(filePath => !this._fastPaths[filePath].isDir);
}
findFilesByExts(exts, { ignore } = {}) {
findFilesByExts(
exts: Array<string>,
{ignore}: {ignore: (filePath: string) => boolean} = {},
) {
return this.getAllFiles()
.filter(filePath => (
exts.indexOf(path.extname(filePath).substr(1)) !== -1 &&
@ -85,11 +117,11 @@ class Fastfs extends EventEmitter {
));
}
matchFilesByPattern(pattern) {
matchFilesByPattern(pattern: RegExp) {
return this.getAllFiles().filter(file => file.match(pattern));
}
readFile(filePath) {
readFile(filePath: string) {
const file = this._getFile(filePath);
if (!file) {
throw new Error(`Unable to find file with path: ${filePath}`);
@ -97,10 +129,11 @@ class Fastfs extends EventEmitter {
return file.read();
}
closest(filePath, name) {
closest(filePath: string, name: string) {
for (let file = this._getFile(filePath).parent;
file;
file = file.parent) {
/* $FlowFixMe: will crash if not `isDir`, see constructor */
if (file.children[name]) {
return file.children[name].path;
}
@ -108,7 +141,7 @@ class Fastfs extends EventEmitter {
return null;
}
fileExists(filePath) {
fileExists(filePath: string) {
let file;
try {
file = this._getFile(filePath);
@ -122,7 +155,7 @@ class Fastfs extends EventEmitter {
return file && !file.isDir;
}
dirExists(filePath) {
dirExists(filePath: string) {
let file;
try {
file = this._getFile(filePath);
@ -136,12 +169,13 @@ class Fastfs extends EventEmitter {
return file && file.isDir;
}
matches(dir, pattern) {
matches(dir: string, pattern: RegExp) {
const dirFile = this._getFile(dir);
if (!dirFile.isDir) {
throw new Error(`Expected file ${dirFile.path} to be a directory`);
}
/* $FlowFixMe: will crash if not `isDir`, see constructor */
return Object.keys(dirFile.children)
.filter(name => name.match(pattern))
.map(name => path.join(dirFile.path, name));
@ -161,6 +195,7 @@ class Fastfs extends EventEmitter {
const root = this._getRoot(filePath);
if (!root) {
const error = new Error(`File ${filePath} not found in any of the roots`);
/* $FlowFixMe: Monkey-patching Error. */
error.type = NOT_FOUND_IN_ROOTS;
throw error;
}
@ -210,7 +245,16 @@ class Fastfs extends EventEmitter {
}
class File {
constructor(filePath, isDir) {
path: string;
isDir: boolean;
children: ?{[filePath: string]: File};
parent: ?File;
_read: ?Promise<string>;
_stat: ?Promise<fs.Stats>;
constructor(filePath: string, isDir: boolean) {
this.path = filePath;
this.isDir = isDir;
this.children = this.isDir ? Object.create(null) : null;
@ -243,16 +287,19 @@ class File {
return this._stat;
}
addChild(file, fileMap) {
addChild(file: File, fileMap: {[filePath: string]: File}) {
const parts = file.path.substr(this.path.length + 1).split(path.sep);
if (parts.length === 1) {
/* $FlowFixMe: will crash if not `isDir`, see constructor */
this.children[parts[0]] = file;
file.parent = this;
/* $FlowFixMe: will crash if not `isDir`, see constructor */
} else if (this.children[parts[0]]) {
this.children[parts[0]].addChild(file, fileMap);
} else {
const dir = new File(this.path + path.sep + parts[0], true);
dir.parent = this;
/* $FlowFixMe: will crash if not `isDir`, see constructor */
this.children[parts[0]] = dir;
fileMap[dir.path] = dir;
dir.addChild(file, fileMap);
@ -275,6 +322,7 @@ class File {
return null;
}
/* $FlowFixMe: will crash if not `isDir`, see constructor */
file = file.children[fileName];
}
@ -290,6 +338,7 @@ class File {
throw new Error(`No parent to delete ${this.path} from`);
}
/* $FlowFixMe: will crash if parent is not `isDir`, see constructor */
delete this.parent.children[path.basename(this.path)];
}
}