UNPKG

@fontoxml/fontoxml-development-tools

Version:

Development tools for Fonto.

115 lines (105 loc) 2.79 kB
import fs from 'fs'; import path from 'path'; /** * @typedef Stats * * @property {string} path * @property {boolean} symlink * @property {boolean} file * @property {boolean} directory * @property {number} size * @property {Date} accessed * @property {Date} modified * @property {Date} changed * @property {Date} created */ /** * @param {string} fileOrDirectoryPath * @param {boolean} indiscriminateOfSymlinks * * @return {Stats} */ function getStatForPath(fileOrDirectoryPath, indiscriminateOfSymlinks) { /* istanbul ignore next: No symlinks in this package, so we won't test this for now */ const statMethodName = indiscriminateOfSymlinks ? 'statSync' : 'lstatSync'; const stat = fs[statMethodName](fileOrDirectoryPath); return { path: fileOrDirectoryPath, symlink: stat.isSymbolicLink() ? path.resolve(path.dirname(stat.path), fs.readlinkSync(stat.path)) : false, file: stat.isFile(), directory: stat.isDirectory(), size: stat.size, accessed: stat.atime, modified: stat.mtime, changed: stat.ctime, created: stat.birthtime, }; } /** * @param {string} dir * @param {boolean} indiscriminateOfSymlinks * * @return {Stats[]} */ function getAllStatsInPath(dir, indiscriminateOfSymlinks) { return fs .readdirSync(dir) .map((file) => path.resolve(dir, file)) .map((fileOrDirectoryPath) => { try { return getStatForPath( fileOrDirectoryPath, indiscriminateOfSymlinks ); } catch (_error) { // Do nothing } return null; }) .filter((result) => !!result); } /** * @param {string} cwd * @param {string|string[]|RegExp} matcher * * @return {string|null} */ export function getFileMatchInDirectoryAncestrySync(cwd, matcher) { const rootDir = path.parse(cwd).root; const matchingStats = getAllStatsInPath(cwd, false).filter((stat) => { if (!stat.file) { return false; } const basename = path.basename(stat.path); return typeof matcher === 'string' ? basename === matcher : Array.isArray(matcher) ? matcher.includes(basename) : basename.match(matcher); }); // If we have a match, return it. if (matchingStats.length) { return matchingStats[0].path; } // If we have reached the root, we cannot look any further. if (cwd === rootDir) { return null; } // Try to find a match in the parent directory. return getFileMatchInDirectoryAncestrySync(path.dirname(cwd), matcher); } /** * @param {string} cwd * @param {string|string[]|RegExp} matcher * * @return {string|null} */ export default function getParentDirectoryContainingFileSync(cwd, matcher) { const matchingFilename = getFileMatchInDirectoryAncestrySync(cwd, matcher); if (!matchingFilename) { return null; } return path.dirname(matchingFilename); }