/**
* 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 strict
* @format
*/
'use strict';
const {dirname, join, parse} = require('path');
module.exports = class HasteFS {
directories: Set<string>;
directoryEntries: Map<string, Array<string>>;
files: Set<string>;
constructor(files: Array<string>) {
this.directories = buildDirectorySet(files);
this.directoryEntries = buildDirectoryEntries(files.map(parse));
this.files = new Set(files);
}
closest(path: string, fileName: string): ?string {
const parsedPath = parse(path);
const root = parsedPath.root;
let dir = parsedPath.dir;
do {
const candidate = join(dir, fileName);
if (this.files.has(candidate)) {
return candidate;
}
dir = dirname(dir);
} while (dir !== '.' && dir !== root);
return null;
}
dirExists(path: string) {
return this.directories.has(path);
}
exists(path: string) {
return this.files.has(path);
}
getAllFiles() {
/* $FlowFixMe(>=0.70.0 site=react_native_fb) This comment suppresses an
* error found when Flow v0.70 was deployed. To see the error delete this
* comment and run Flow. */
return Array.from(this.files.keys());
}
matchFiles() {
throw new Error('HasteFS.matchFiles is not implemented yet.');
}
matches(directory: string, pattern: RegExp) {
const entries = this.directoryEntries.get(directory);
/* $FlowFixMe(>=0.70.0 site=react_native_fb) This comment suppresses an
* error found when Flow v0.70 was deployed. To see the error delete this
* comment and run Flow. */
return entries ? entries.filter(pattern.test, pattern) : [];
}
};
function buildDirectorySet(files) {
const directories = new Set();
files.forEach(path => {
const parsedPath = parse(path);
const root = parsedPath.root;
let dir = parsedPath.dir;
while (dir !== '.' && dir !== root && !directories.has(dir)) {
directories.add(dir);
dir = dirname(dir);
}
});
return directories;
}
function buildDirectoryEntries(files) {
const directoryEntries = new Map();
files.forEach(({base, dir}) => {
const entries = directoryEntries.get(dir);
if (entries) {
entries.push(base);
} else {
directoryEntries.set(dir, [base]);
}
});
return directoryEntries;
}