UNPKG

snapshot-fs

Version:

Create a filesystem snapshot for use with memfs

101 lines 3.96 kB
/** * Provides {@link toTree a function} to dump the contents of a `Volume`, * comparing it to the real filesystem. * * Portions of this code adapted from * https://github.com/streamich/memfs/blob/2c6a6ca55ad2e661f40e488fe5ea4087438bae0e/src/print/index.ts#L6-L30 * and are copyrighted by the original author and licesned under Apache-2.0. */ import nodeFs from 'node:fs'; import path from 'node:path'; import { basename, sep } from 'path/posix'; import { printTree } from 'tree-dump'; export const toTree = (fs, { depth = 10, separator = sep, dir = separator, formatNew = (str) => `+ ${str}`, formatOverwrite = (str) => `! ${str}`, tab = '', }) => { if (dir[dir.length - 1] !== separator) { dir += separator; } let subtree = ' (...)'; if (depth > 0) { const list = fs.readdirSync(dir, { withFileTypes: true }); let actualFiles; try { actualFiles = new Map(nodeFs .readdirSync(dir, { withFileTypes: true }) .map((entry) => [entry.name, entry])); } catch { actualFiles = new Map(); } subtree = printTree(tab, list.map((entry) => (tab) => { if (entry.isDirectory()) { return toTree(fs, { depth: depth - 1, dir: `${dir}${entry.name}`, formatNew, formatOverwrite, tab, }); } let formattedName; let willBeOverwritten = false; const willBeCreated = !actualFiles.has(`${entry.name}`); if (!willBeCreated) { const actualDirent = actualFiles.get(`${entry.name}`); if (entry.isSymbolicLink()) { if (!actualDirent.isSymbolicLink()) { willBeOverwritten = true; } else { try { const actualRealpath = nodeFs.realpathSync(path.join(dir, `${entry.name}`)); const realpath = fs.readlinkSync(path.join(dir, `${entry.name}`)); if (actualRealpath !== realpath) { willBeOverwritten = true; } } catch { willBeOverwritten = true; } } } else { // implies file if (!actualDirent.isFile()) { willBeOverwritten = true; } else { try { const actualStat = nodeFs.statSync(path.join(dir, `${entry.name}`)); const stat = fs.statSync(path.join(dir, `${entry.name}`)); if (actualStat.size !== stat.size) { willBeOverwritten = true; } } catch { willBeOverwritten = true; } } } } if (willBeOverwritten) { formattedName = formatOverwrite(`${entry.name}`); } else if (willBeCreated) { formattedName = formatNew(`${entry.name}`); } else { // identical, hopefully formattedName = `${entry.name}`; } if (entry.isSymbolicLink()) { return `${formattedName}${fs.readlinkSync(path.join(dir, `${entry.name}`))}`; } else { return formattedName; } })); } const base = basename(dir, separator) + separator; return base + subtree; }; //# sourceMappingURL=tree.js.map